-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature: add federation-link-util library #6452
base: main
Are you sure you want to change the base?
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
const metaSpec = new LinkableSpec('https://specs.graphql-hive.com/metadata', { | ||
// The return value could be used to map sdl, collect information, or create a graphql yoga plugin. | ||
// In this test, it's used to collect metadata information from the schema. | ||
'v0.1': resolveImportName => (typeDefs: DocumentNode) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is the best example of how I intended this API to be used.
The LinkableSpec
defines how the linked schemas are implemented.
The Link. resolveImportName
function is then passed to the handler to be used to resolve the names of nodes as they are referred to within the subgraph... I chose to only pass resolveImportName
to keep the API simpler.
And then the implementation uses that to figure out the names of things it supports.
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe changes introduce a new TypeScript package Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant detectLinkedImplementations
participant FederatedLink
participant LinkableSpec
Client->>detectLinkedImplementations: Call with typeDefs, supportedSpecs
detectLinkedImplementations->>FederatedLink: Extract links via fromTypedefs(typeDefs)
FederatedLink-->>detectLinkedImplementations: Return list of links
loop For each spec in supportedSpecs
detectLinkedImplementations->>LinkableSpec: spec.detectImplementation(links)
LinkableSpec-->>detectLinkedImplementations: Return implementation (or undefined)
end
detectLinkedImplementations-->>Client: Return array of implementations
Tip 🌐 Web search-backed reviews and chat
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
66dfc13
to
bf8c6e8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (6)
packages/libraries/linkable-specs/src/__tests__/index.spec.ts (3)
1-17
: LGTM! Consider adding JSDoc comments.The test setup provides a clear example of the API usage with proper imports and SDL definition. Consider adding JSDoc comments to document the test's purpose and the demonstrated functionality.
+/** + * Tests the integration between LinkableSpec and detectLinkedImplementations + * demonstrating how to implement versioned metadata collection from linked schemas. + */ test('LinkableSpec and detectLinkedImplementations can be used to easily implement linked schema functionality', () => {
32-44
: Extract repeated directive argument extraction logic.The pattern for extracting string values from directive arguments is duplicated. Consider extracting this into a helper function to improve maintainability and reduce duplication.
+const getDirectiveStringArg = (directive: any, argName: string) => + (directive.arguments?.find(a => a.name.value === argName)?.value as StringValueNode | undefined)?.value ?? '??'; -metaData['name'] = - ( - meta.arguments?.find(a => a.name.value === 'name')?.value as - | StringValueNode - | undefined - )?.value ?? '??'; -metaData['content'] = - ( - meta.arguments?.find(a => a.name.value === 'content')?.value as - | StringValueNode - | undefined - )?.value ?? '??'; +metaData['name'] = getDirectiveStringArg(meta, 'name'); +metaData['content'] = getDirectiveStringArg(meta, 'content'); -metaData['eg'] = - ( - example.arguments?.find(a => a.name.value === 'eg')?.value as - | StringValueNode - | undefined - )?.value ?? '??'; +metaData['eg'] = getDirectiveStringArg(example, 'eg');Also applies to: 48-54
65-68
: Add TODO comment for v0.2 implementation.The v0.2 implementation is currently a placeholder. Consider adding a TODO comment to track this for future implementation.
-'v0.2': _resolveImportName => (_typeDefs: DocumentNode) => { +'v0.2': _resolveImportName => (_typeDefs: DocumentNode) => { + // TODO: Implement v0.2 metadata collection logic // collect metadata return `running on v0.2...`; },packages/libraries/linkable-specs/src/link.ts (3)
5-32
: Consider explicit handling of unknown arguments or removing the commented-out log.
Currently, unrecognized arguments trigger the default case (line 23) with a commented-outconsole.warn
. Either remove the commented log or convert it into a meaningful handling or user feedback mechanism to clarify unsupported arguments.default: { - // console.warn('Unknown argument'); + console.warn(`Unknown argument: ${arg.name.value}`); }
44-66
: Ensure the@link
directive is relevant to the intended specification.
While filtering directives named'link'
is correct for Apollo’s federated spec, be cautious if multiple specifications or custom'link'
directives exist. Make sure that the directive name matches the intended spec usage or version.
85-119
: Replacets-expect-error
with a more robust type definition.
The overload notation forsupports()
could be handled via a single function signature that performs runtime checks on its parameters. This would eliminate the need forts-expect-error
and improve type clarity.- supports(...args: [string] | [number, number] | [FederatedLinkUrl]): boolean { - /** @ts-expect-error: ignore tuple error. These are tuples and can be spread. tsc is wrong. */ - return this.url.supports(...args); - } + supports(version: string | number | FederatedLinkUrl, minor?: number): boolean { + if (typeof version === 'string') { + return this.url.supports(version); + } else if (typeof version === 'number' && typeof minor === 'number') { + return this.url.supports(version, minor); + } else { + return this.url.supports(version); + } + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (12)
packages/libraries/linkable-specs/README.md
(1 hunks)packages/libraries/linkable-specs/package.json
(1 hunks)packages/libraries/linkable-specs/src/__tests__/index.spec.ts
(1 hunks)packages/libraries/linkable-specs/src/__tests__/link-url.spec.ts
(1 hunks)packages/libraries/linkable-specs/src/__tests__/link.spec.ts
(1 hunks)packages/libraries/linkable-specs/src/__tests__/linkable-spec.spec.ts
(1 hunks)packages/libraries/linkable-specs/src/index.ts
(1 hunks)packages/libraries/linkable-specs/src/link-import.ts
(1 hunks)packages/libraries/linkable-specs/src/link-url.ts
(1 hunks)packages/libraries/linkable-specs/src/link.ts
(1 hunks)packages/libraries/linkable-specs/src/linkable-spec.ts
(1 hunks)packages/libraries/linkable-specs/tsconfig.json
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (10)
- packages/libraries/linkable-specs/README.md
- packages/libraries/linkable-specs/tsconfig.json
- packages/libraries/linkable-specs/src/tests/linkable-spec.spec.ts
- packages/libraries/linkable-specs/src/tests/link.spec.ts
- packages/libraries/linkable-specs/src/index.ts
- packages/libraries/linkable-specs/src/tests/link-url.spec.ts
- packages/libraries/linkable-specs/src/link-import.ts
- packages/libraries/linkable-specs/package.json
- packages/libraries/linkable-specs/src/link-url.ts
- packages/libraries/linkable-specs/src/linkable-spec.ts
🧰 Additional context used
📓 Path-based instructions (2)
packages/libraries/linkable-specs/src/__tests__/index.spec.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/linkable-specs/src/link.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
🔇 Additional comments (4)
packages/libraries/linkable-specs/src/__tests__/index.spec.ts (1)
70-78
: Consider adding more test cases.The current test only covers the happy path for v0.1. Consider adding test cases for:
- v0.2 implementation
- Error cases (malformed directives, missing required arguments)
- Edge cases (no directives, multiple directives)
Would you like me to help generate these additional test cases?
packages/libraries/linkable-specs/src/link.ts (3)
1-4
: Imports look clean and straightforward.
No issues found in these imports; they accurately capture the dependencies needed to handleConstArgumentNode
and related types.
34-42
: Namespace function logic is clear.
The logic for prefixing names with a namespace is succinct and easy to read. No immediate concerns.
68-84
: Validate or sanitize user-provided identifiers intoString()
.
BecausetoString()
directly interpolatesurl
andimports
into an SDL string, confirm that upstream code or the parsing logic won’t cause malformed SDL or injection-like concerns if the input is external.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/libraries/linkable-specs/src/link-import.ts (2)
9-11
: Add JSDoc documentation for the toString method.While the implementation is correct, adding documentation would improve clarity about the expected string format.
+ /** + * Returns a string representation of the import in GraphQL SDL format. + * @returns {string} For imports with alias: { name: "name", as: "alias" } + * For imports without alias: "name" + */ public toString(): string {
13-47
: Add JSDoc documentation and empty string validation.
- Add JSDoc documentation for better API understanding.
- Add validation for empty strings in the 'name' field.
+ /** + * Parses GraphQL ConstValueNode to extract @link import declarations. + * @param {ConstValueNode} node - The node containing import declarations + * @returns {FederatedLinkImport[]} Array of parsed import declarations + * @throws {Error} If the node structure is invalid + */ static fromTypedefs(node: ConstValueNode): FederatedLinkImport[] { // ... existing code ... name = f.value.value; + if (name.trim() === '') { + throw new Error('Empty string is not allowed for @link "name" field'); + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (1)
packages/libraries/linkable-specs/src/link-import.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
packages/libraries/linkable-specs/src/link-import.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
📓 Learnings (1)
📓 Common learnings
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
🔇 Additional comments (2)
packages/libraries/linkable-specs/src/link-import.ts (2)
1-7
: LGTM! Clean and concise class declaration.The imports are appropriate, and the constructor uses TypeScript's parameter property syntax effectively.
17-17
: Replace 'this' with class name in static context.Using 'this' in static methods can be confusing as it refers to the class itself.
- return new this(v.value, null); + return new FederatedLinkImport(v.value, null); - return new this(name, as); + return new FederatedLinkImport(name, as);Also applies to: 40-40
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @jdolle my review is accumulating some questions and there's still a ways to go. Going to flush what I have so far in case you could already answer some. It would probably help me better understand what is going on etc. :)
[Hive](https://the-guild.dev/graphql/hive) is a fully open-source schema registry, analytics, | ||
metrics and gateway for [GraphQL federation](https://the-guild.dev/graphql/hive/federation) and | ||
other GraphQL APIs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if could make this even more maintainable by avoiding specific feature references, e.g.
... is a delightful MIT licensed platform for developing and operating your GraphQL services from idea to production, solo to enterprise.
And maybe there is/this is a template we can turn into a copy standard? CC @dotansimha @Urigo
This comment was marked as resolved.
This comment was marked as resolved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/libraries/linkable-specs/README.md (2)
9-12
: Grammar Correction in Custom Features DescriptionThe sentence “This library can be used to make a custom features for GraphQL schemas backed by Federation's directive.” contains a grammatical issue with the article used before the plural noun “features.” Consider revising to either:
- “This library can be used to create custom features for GraphQL schemas…”
or- “This library can be used to make a custom feature for GraphQL schemas…”
This change improves clarity and correctness.
🧰 Tools
🪛 LanguageTool
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...(VB_A_JJ_NNS)
66-68
: Clarify the "Yoga Plugin" RecommendationThe note stating “always return a yoga plugin” might be ambiguous to users who are not familiar with the term. Consider providing a brief explanation or a hyperlink to documentation that explains what a yoga plugin is and why it is recommended.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/libraries/linkable-specs/README.md
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
packages/libraries/linkable-specs/README.md (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
📓 Learnings (2)
📓 Common learnings
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
packages/libraries/linkable-specs/README.md (1)
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
🪛 LanguageTool
packages/libraries/linkable-specs/README.md
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...
(VB_A_JJ_NNS)
⏰ Context from checks skipped due to timeout of 90000ms (9)
- GitHub Check: test / unit
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: alpha / cli-artifacts
- GitHub Check: SonarCloud
🔇 Additional comments (4)
packages/libraries/linkable-specs/README.md (4)
1-2
: Header is Clear and InformativeThe header “GraphQL Hive - linkable-specs” clearly identifies the package and purpose.
3-5
: Adopt a Consistent Copy Standard for the IntroductionThe introductory text provides a good overview; however, consider revising it to follow a consistent copy standard. Previous feedback suggested using a generic template that avoids overly specific feature references. For example, instead of specific claims, a template outlining capabilities in a maintainable way could be beneficial.
13-18
: Features Section Looks GoodThe bulleted features list is concise and clearly communicates the key capabilities of the package.
19-34
: GraphQL Usage Example is InformativeThe provided GraphQL schema snippet adequately demonstrates the usage of the
@link
directive in context. The inclusion of a concrete example helps users understand how to apply the feature.
I considered using that package but federation links only have major and minor, have special requirements for v0.x that don't follow semantic versioning, and I didnt want to introduce a dependency for just the one or two relatively simple functions to write. If the link version spec is ever modified to specifically use semantic versions then we can add this package. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/libraries/linkable-specs/README.md (2)
9-12
: Grammar Correction Needed in Description.The sentence "This library can be used to make a custom features for GraphQL schemas backed by Federation's" contains a grammatical error ("a custom features"). Consider rephrasing to "This library can be used to create custom features for GraphQL schemas backed by Federation's" (or another phrasing that fits the intended meaning).
Diff Suggestion:
-This library can be used to make a custom features for GraphQL schemas backed by Federation's +This library can be used to create custom features for GraphQL schemas backed by Federation's🧰 Tools
🪛 LanguageTool
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...(VB_A_JJ_NNS)
65-68
: Clarify Recommendation on Consistent Implementation.The concluding note recommends that all LinkedSpecs always return a yoga plugin. It would be beneficial to provide a brief explanation or example of why this consistency is important and how it benefits the overall implementation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/libraries/linkable-specs/README.md
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
packages/libraries/linkable-specs/README.md (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
📓 Learnings (2)
📓 Common learnings
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
packages/libraries/linkable-specs/README.md (1)
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
🪛 LanguageTool
packages/libraries/linkable-specs/README.md
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...
(VB_A_JJ_NNS)
⏰ Context from checks skipped due to timeout of 90000ms (9)
- GitHub Check: typescript / typecheck
- GitHub Check: alpha / cli-artifacts
- GitHub Check: test / unit
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: SonarCloud
🔇 Additional comments (6)
packages/libraries/linkable-specs/README.md (6)
1-2
: Title and Header Are Clear.The title "GraphQL Hive - linkable-specs" succinctly informs the reader about the package’s purpose.
3-6
: Clear Description Provided.The introductory paragraph effectively describes GraphQL Hive as an open-source schema registry, analytics, and gateway for GraphQL APIs.
13-18
: Features Section is Concise and Informative.The bullet points clearly list the package’s key capabilities: link version support, import
as
/namespacing following the link spec, and maintaining minimal dependencies.
19-20
: Usage Section Header is Clear.The dedicated "Usage" section helps users quickly locate practical examples.
21-35
: GraphQL Schema Example Effectively Demonstrates Usage.The provided GraphQL code block clearly illustrates how to define a directive and utilize the
@link
directive. This practical example aligns well with the package’s objective of managing schemas with custom link features.
36-64
: TypeScript Example Illustrates Implementation Correctly.The TypeScript example demonstrates the instantiation of
LinkableSpec
and the resolution of directive names usingresolveImportName
, which is consistent with the automatic namespacing feature noted in the retrieved learnings. Ensure that functions likevisit
,parse
, anddetectLinkedImplementations
are either included in the context or referenced in documentation for clarity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (9)
packages/libraries/linkable-specs/README.md (3)
9-11
: Grammar Correction in Usage DescriptionThe sentence "This library can be used to make a custom features for GraphQL schemas backed by Federation's" contains a grammatical error due to the use of the singular article "a" before the plural noun "features." Consider revising it to either "make custom features" (if plural is intended) or "make a custom feature" (if singular is intended).
🧰 Tools
🪛 LanguageTool
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...(VB_A_JJ_NNS)
36-63
: TypeScript Example: Usage Clarity and CompletenessThe TypeScript sample clearly illustrates how to create and configure a
LinkableSpec
instance, resolve a base directive name (e.g.,@example
), and extract metadata via traversing type definitions. As this snippet is intended for documentation purposes, consider adding import statements or comments indicating where functions (such asvisit
,parse
) and types (DocumentNode
,StringValueNode
) are sourced from. This can help users better adapt the example into a production context.
65-67
: Concluding Remarks and ConsistencyThe concluding section effectively communicates that the
LinkableSpec
is unopinionated regarding implementation while recommending consistency across all linked specs (e.g., always returning a yoga plugin). For enhanced clarity and in alignment with internal documentation styles, consider reviewing the phrasing (for example, verifying the use of "I.e." or "i.e.," as per your copy standards).packages/libraries/linkable-specs/src/link-url.ts (4)
1-10
: Consider tightening version constraints.The version regex pattern is quite permissive, allowing major versions up to 99 and minor versions up to 9999. Consider adding numeric range validation to ensure versions stay within reasonable bounds for federation links.
-const VERSION_MATCH = /v(\d{1,2})\.(\d{1,4})/i; +const VERSION_MATCH = /v(\d{1,2})\.(\d{1,3})/i; function parseVersion(version: string | null): [number, number] { const versionParts = version?.match(VERSION_MATCH); if (versionParts?.length) { const [_full, major, minor] = versionParts; + const majorNum = Number(major); + const minorNum = Number(minor); + if (majorNum > 20 || minorNum > 999) { + return [-1, -1]; + } - return [Number(major), Number(minor)]; + return [majorNum, minorNum]; } return [-1, -1]; }
12-29
: Enhance class documentation.The class documentation could be more detailed about the parameters and their purpose.
/** * A wrapper around the `@link` url -- this parses all necessary data to identify the link * and determine which version is most appropriate to use. + * + * @param identity - The base URL or identifier of the link + * @param name - Optional name of the link specification + * @param version - Optional version string in the format 'vX.Y' */
53-75
: Improve error message specificity.The error message for unsupported version arguments could be more helpful by indicating the expected types.
- throw new Error(`Unsupported version argument: ${args}.`); + throw new Error( + `Unsupported version argument: ${args}. Expected a version string (e.g., 'v1.0'), ` + + `version numbers (major, minor), or FederatedLinkUrl instance.` + );
77-85
: Document version compatibility rules.The version compatibility logic, especially the special handling of v0.x versions, should be documented for clarity.
+ /** + * Checks if this version is compatible with the given version. + * + * Version compatibility rules: + * - For v0.x: Versions must match exactly (no backward compatibility) + * - For v1.x and above: Compatible if major versions match and current minor version >= given minor version + */ private isCompatibleVersion(major: number, minor: number): boolean {packages/libraries/linkable-specs/src/link.ts (2)
42-50
: Add JSDoc documentation and input validation.The utility function would benefit from proper documentation and input validation.
+/** + * Prefixes a name with a namespace if provided. + * @param namespace - The namespace to prefix the name with + * @param name - The name to be namespaced + * @returns The namespaced name or the original name if no namespace is provided + * @throws {Error} If name is empty or contains invalid characters + */ function namespaced(namespace: string | null, name: string) { + if (!name || typeof name !== 'string') { + throw new Error('Name must be a non-empty string'); + } + if (namespace?.length) { if (name.startsWith('@')) { return `@${namespace}__${name.substring(1)}`; } return `${namespace}__${name}`; } return name; }
120-130
: Simplify resolveImportName logic and improve error handling.The method contains complex string manipulation and could benefit from clearer logic separation.
resolveImportName(elementName: string): string { + if (!elementName) { + throw new Error('Element name must be provided'); + } + + // Handle default link import case if (this.url.name && elementName === `@${this.url.name}`) { - // @note: default is a directive... So remove the `@` - return this.defaultImport!.substring(1); + const defaultImport = this.defaultImport; + if (!defaultImport) { + throw new Error('Default import not available'); + } + return defaultImport.substring(1); } + + // Find explicit import const imported = this.imports.find(i => i.name === elementName); - let resolvedName = imported?.as ?? imported?.name ?? namespaced(this.namespace, elementName); - // Strip the `@` prefix for directives because in all implementations of mapping or visiting a schema, - // directive names are not prefixed with `@`. The `@` is only for SDL. + const resolvedName = imported?.as ?? imported?.name ?? namespaced(this.namespace, elementName); + + // Remove @ prefix for directives as they're not used in schema visitors return resolvedName.startsWith('@') ? resolvedName.substring(1) : resolvedName; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
packages/libraries/linkable-specs/README.md
(1 hunks)packages/libraries/linkable-specs/src/link-url.ts
(1 hunks)packages/libraries/linkable-specs/src/link.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
packages/libraries/linkable-specs/README.md (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/linkable-specs/src/link-url.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/linkable-specs/src/link.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
📓 Learnings (2)
📓 Common learnings
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
packages/libraries/linkable-specs/README.md (1)
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
🪛 LanguageTool
packages/libraries/linkable-specs/README.md
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...
(VB_A_JJ_NNS)
⏰ Context from checks skipped due to timeout of 90000ms (12)
- GitHub Check: alpha / npm / snapshot
- GitHub Check: alpha / cli-artifacts
- GitHub Check: test / unit
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: db-types / diff
- GitHub Check: test / db-migrations
- GitHub Check: SonarCloud
🔇 Additional comments (6)
packages/libraries/linkable-specs/README.md (3)
1-8
: Introduction and Overview Section ReviewThe introductory section clearly presents the package and its purpose. The title and accompanying description effectively introduce "GraphQL Hive - linkable-specs" and set the context for the utility library.
13-18
: Features List ClarityThe features list is well-structured and clearly highlights the package’s functionalities, including link version support, import
as
/namespacing based on the link spec, and the minimal dependency ongraphql
.
19-34
: GraphQL Code Snippet ValidationThe provided GraphQL code snippet is syntactically correct and effectively demonstrates how to declare a directive and extend the schema using the
@link
directive. The inclusion of relevant hyperlinks enhances clarity and offers users an avenue for further exploration of the concept.packages/libraries/linkable-specs/src/link-url.ts (1)
31-33
: LGTM!The toString implementation correctly handles both versioned and unversioned URLs.
packages/libraries/linkable-specs/src/link.ts (2)
5-40
: Improve type validation and return type.The function's type validation and return type could be improved for better type safety and clarity.
Consider these improvements:
- Add explicit type validation before using values
- Make the return type more explicit
- Add input validation for required fields
-function linkFromArgs(args: readonly ConstArgumentNode[]): FederatedLink | undefined { +function linkFromArgs(args: readonly ConstArgumentNode[]): FederatedLink | null { let url: FederatedLinkUrl | undefined, imports: FederatedLinkImport[] = [], as: string | null = null; + + // Validate required arguments + const urlArg = args.find(arg => arg.name.value === 'url'); + if (!urlArg) { + throw new Error('Missing required "url" argument in @link directive'); + } + for (const arg of args) { switch (arg.name.value) { case 'url': { - if (arg.value.kind === Kind.STRING) { - url = FederatedLinkUrl.fromUrl(arg.value.value); - } else { - console.warn(`Unexpected kind, ${arg.value.kind}, for argument "url" in @link.`); + if (arg.value.kind !== Kind.STRING) { + throw new Error(`Unexpected kind ${arg.value.kind} for argument "url" in @link directive. Expected ${Kind.STRING}.`); } + url = FederatedLinkUrl.fromUrl(arg.value.value); break; } // ... similar changes for 'as' argument } } if (url !== undefined) { return new FederatedLink(url, as, imports); } - return; + return null; }
53-53
: Address the TODO comment about import names.The TODO comment raises an important architectural question about import name handling.
Could you clarify if import names are needed for every feature or just the namespace? This decision could impact the implementation's flexibility and performance.
} | ||
`; | ||
|
||
const metaSpec = new LinkableSpec('https://specs.graphql-hive.com/metadata', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC the given URL here is conforming to the URL spec value in @link
, and upon being passed, it is used in conjunction with the given SDL to find the @link
ed instance (instances plural possible?). Is that right?
Something that wasn't clear to me from reading the spec https://specs.apollo.dev/link/v1.0/ was what is name
and version
when not explicitly specified in the URL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when not specified, they are null. You can see examples in packages/libraries/federation-link-utils/src/tests/link-url.spec.ts:4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, given a linked schema has 4 versions, but the given url to it doesn't specify when one, after null
, what happens then? Like, would an entry of null
in the versions record of your class constructor arguments be used? Or...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (13)
packages/libraries/federation-link-utils/src/link-url.ts (1)
1-10
: Consider supporting patch versions or alternative version formats.
This approach correctly extracts major and minor versions using a concise regex. However, if federated links ever adopt full semantic versioning (including patch versions or more digits), you may need to adjust the regex or your approach.packages/libraries/federation-link-utils/src/link.ts (1)
52-132
: Potential improvement: incorporate stronger validations or error handling.
WhileFederatedLink.fromTypedefs
collects links effectively, you might consider validating the resulting links (e.g., ensuring they have valid URLs, checking for conflicts) before returning them. This could prevent issues later in the pipeline.packages/libraries/federation-link-utils/src/__tests__/linkable-spec.spec.ts (1)
5-19
: Enhance test coverage with additional test cases.While the current test verifies basic version compatibility, consider adding test cases for:
- Edge cases (no matching version)
- Warning message when version is unsupported
- Multiple links in the schema
- Invalid URLs
- Version compatibility edge cases (v0.x handling)
Example test cases to add:
test('warns when no supporting version is found', () => { const spec = new LinkableSpec('https://specs.graphql-hive.com/example', { 'v1.0': _resolveImportName => 'Version 1.0 used.', }); const sdl = ` extend schema @link(url: "https://specs.graphql-hive.com/example/v2.0") `; const consoleSpy = jest.spyOn(console, 'warn'); const links = FederatedLink.fromTypedefs(parse(sdl)); const specImpl = spec.detectImplementation(links); expect(specImpl).toBeUndefined(); expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Cannot apply @link')); }); test('handles multiple links in schema', () => { const spec = new LinkableSpec('https://specs.graphql-hive.com/example', { 'v2.0': _resolveImportName => 'Version 2.0 used.', 'v1.0': _resolveImportName => 'Version 1.0 used.', }); const sdl = ` extend schema @link(url: "https://specs.graphql-hive.com/other/v1.0") @link(url: "https://specs.graphql-hive.com/example/v1.1") `; const links = FederatedLink.fromTypedefs(parse(sdl)); const specImpl = spec.detectImplementation(links); expect(specImpl).toBe('Version 1.0 used.'); });packages/libraries/federation-link-utils/src/link-import.ts (1)
13-47
: Enhance error handling and type safety.Consider the following improvements:
- Add validation for empty name
- Use type guards for better type safety
- Make error messages more descriptive by including the actual value
Apply this diff to improve the implementation:
static fromTypedefs(node: ConstValueNode): FederatedLinkImport[] { if (node.kind == Kind.LIST) { const imports = node.values.map(v => { if (v.kind === Kind.STRING) { + if (!v.value.trim()) { + throw new Error('Empty string is not allowed as @link import name'); + } return new FederatedLinkImport(v.value, null); } if (v.kind === Kind.OBJECT) { let name: string = ''; let as: string | null = null; v.fields.forEach(f => { if (f.name.value === 'name') { if (f.value.kind !== Kind.STRING) { throw new Error( - `Expected string value for @link "name" field but got "${f.value.kind}"`, + `Expected string value for @link "name" field but got "${f.value.kind}" (${JSON.stringify(f.value)})`, ); } + if (!f.value.value.trim()) { + throw new Error('Empty string is not allowed as @link import name'); + } name = f.value.value; } else if (f.name.value === 'as') { if (f.value.kind !== Kind.STRING) { throw new Error( - `Expected string value for @link "as" field but got "${f.value.kind}"`, + `Expected string value for @link "as" field but got "${f.value.kind}" (${JSON.stringify(f.value)})`, ); } + if (!f.value.value.trim()) { + throw new Error('Empty string is not allowed as @link import alias'); + } as = f.value.value; } }); + if (!name) { + throw new Error('Missing required "name" field in @link import'); + } return new FederatedLinkImport(name, as); } - throw new Error(`Unexpected value kind "${v.kind}" in @link import declaration`); + throw new Error(`Unexpected value kind "${v.kind}" in @link import declaration (${JSON.stringify(v)})`); }); return imports; } - throw new Error(`Expected a list of @link imports but got "${node.kind}"`); + throw new Error(`Expected a list of @link imports but got "${node.kind}" (${JSON.stringify(node)})`); }packages/libraries/federation-link-utils/src/linkable-spec.ts (3)
15-19
: Improve version comparison logic.The current version comparison assumes a simple major.minor format. Consider:
- Adding validation for version format
- Handling pre-release versions
- Supporting patch versions if needed
this.sortedVersionKeys = Object.keys(versions).sort((a, b) => { + const versionRegex = /^v(\d+)\.(\d+)(?:\.(\d+))?(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/; + const matchA = a.match(versionRegex); + const matchB = b.match(versionRegex); + if (!matchA || !matchB) { + throw new Error(`Invalid version format: ${!matchA ? a : b}`); + } - const [aMajor, aMinor] = a.split('.').map(Number); - const [bMajor, bMinor] = b.split('.').map(Number); + const [, aMajor, aMinor] = matchA.map(Number); + const [, bMajor, bMinor] = matchB.map(Number); return bMajor !== aMajor ? bMajor - aMajor : bMinor - aMinor; });
47-50
: Fix typo in warning message.The warning message contains a duplicate word "compatible".
- `Available versions: ${this.sortedVersionKeys.join(', ')} and any version these are compatible compatible with.`, + `Available versions: ${this.sortedVersionKeys.join(', ')} and any version these are compatible with.`,
39-52
: Add JSDoc for public method.The
detectImplementation
method would benefit from more detailed documentation.+ /** + * Detects and returns an implementation based on the provided links. + * + * @param links - Array of FederatedLink instances to search through + * @returns The implementation for the highest compatible version found, + * or undefined if no compatible version is found + * @throws {Error} If the version format is invalid + * @example + * ```typescript + * const spec = new LinkableSpec('https://example.com', { + * 'v2.0': resolveImportName => new Implementation(resolveImportName), + * }); + * const links = FederatedLink.fromTypedefs(parse(sdl)); + * const impl = spec.detectImplementation(links); + * ``` + */ public detectImplementation(links: FederatedLink[]): T | undefined {packages/libraries/federation-link-utils/src/__tests__/link-url.spec.ts (1)
4-25
: Improve test descriptions and add error cases.While the test coverage is good, consider:
- Making test descriptions more descriptive
- Adding error cases for invalid URLs
- Adding test cases for malformed versions
test.each([ { description: 'parses URL with schema name and version in path', url: 'https://spec.example.com/a/b/mySchema/v1.0/', expected: { identity: 'https://spec.example.com/a/b/mySchema', name: 'mySchema', version: 'v1.0' } }, // ... existing test cases ... ])('fromUrl $description', ({ url, expected }) => { const spec = FederatedLinkUrl.fromUrl(url); expect(spec.identity).toBe(expected.identity); expect(spec.name).toBe(expected.name); expect(spec.version).toBe(expected.version); }); test.each([ ['invalid://url', 'Invalid URL protocol'], ['https://spec.example.com/mySchema/invalid-version', 'Invalid version format'], ])('fromUrl throws error for invalid input: %s', (url, expectedError) => { expect(() => FederatedLinkUrl.fromUrl(url)).toThrow(expectedError); });packages/libraries/federation-link-utils/README.md (2)
9-11
: Fix grammar in the introduction.The article "a" should not be used before the plural noun "features".
-This library can be used to make a custom features for GraphQL schemas backed by Federation's +This library can be used to make custom features for GraphQL schemas backed by Federation's🧰 Tools
🪛 LanguageTool
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...(VB_A_JJ_NNS)
13-67
: Consider enhancing the documentation.While the documentation provides a good overview and usage example, consider adding the following sections to make it more comprehensive:
- Installation instructions
- API reference
- Contributing guidelines
- License information
packages/libraries/federation-link-utils/src/__tests__/link.spec.ts (2)
12-37
: Consider adding negative test cases.The
fromTypedefs
test suite only covers successful scenarios. Consider adding test cases for:
- Invalid SDL syntax
- Missing or malformed @link directives
- Empty import arrays
39-71
: Add test descriptions for better readability.The test cases in
resolveImportName
would benefit from descriptive titles usingtest.each
or separatetest
blocks for each scenario.- test('resolveImportName', () => { + describe('resolveImportName', () => { + test('resolves aliased imports correctly', () => { // Test aliased imports + }); + test('resolves unimported directives with namespace', () => { // Test unimported directives + }); + // ... more test cases });packages/libraries/federation-link-utils/src/__tests__/index.spec.ts (1)
31-43
: Simplify type assertions using optional chaining.The nested type assertions and null checks can be simplified using optional chaining.
-metaData['name'] = - ( - meta.arguments?.find(a => a.name.value === 'name')?.value as - | StringValueNode - | undefined - )?.value ?? '??'; +metaData['name'] = (meta.arguments?.find(a => a.name.value === 'name')?.value as StringValueNode)?.value ?? '??';
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
packages/libraries/federation-link-utils/README.md
(1 hunks)packages/libraries/federation-link-utils/package.json
(1 hunks)packages/libraries/federation-link-utils/src/__tests__/index.spec.ts
(1 hunks)packages/libraries/federation-link-utils/src/__tests__/link-url.spec.ts
(1 hunks)packages/libraries/federation-link-utils/src/__tests__/link.spec.ts
(1 hunks)packages/libraries/federation-link-utils/src/__tests__/linkable-spec.spec.ts
(1 hunks)packages/libraries/federation-link-utils/src/index.ts
(1 hunks)packages/libraries/federation-link-utils/src/link-import.ts
(1 hunks)packages/libraries/federation-link-utils/src/link-url.ts
(1 hunks)packages/libraries/federation-link-utils/src/link.ts
(1 hunks)packages/libraries/federation-link-utils/src/linkable-spec.ts
(1 hunks)packages/libraries/federation-link-utils/src/version.ts
(1 hunks)packages/libraries/federation-link-utils/tsconfig.json
(1 hunks)
✅ Files skipped from review due to trivial changes (3)
- packages/libraries/federation-link-utils/src/version.ts
- packages/libraries/federation-link-utils/package.json
- packages/libraries/federation-link-utils/tsconfig.json
🧰 Additional context used
📓 Path-based instructions (10)
packages/libraries/federation-link-utils/src/__tests__/link-url.spec.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/src/index.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/src/__tests__/index.spec.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/src/link-import.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/src/__tests__/linkable-spec.spec.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/src/linkable-spec.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/src/__tests__/link.spec.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/README.md (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/src/link-url.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/src/link.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
📓 Learnings (3)
packages/libraries/federation-link-utils/src/__tests__/index.spec.ts (1)
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
packages/libraries/federation-link-utils/src/__tests__/linkable-spec.spec.ts (1)
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
packages/libraries/federation-link-utils/README.md (1)
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
🪛 LanguageTool
packages/libraries/federation-link-utils/README.md
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...
(VB_A_JJ_NNS)
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: SonarCloud
🔇 Additional comments (6)
packages/libraries/federation-link-utils/src/link-url.ts (3)
21-29
: Constructor usage looks sound.
Storing both the parsed major/minor and the original version string effectively supports flexible version checks while preserving raw data.
35-51
: Handle invalid or malformed URLs more gracefully.
Currently, ifnew URL(urlSource)
receives an invalid URL, it will throw an exception. Consider wrapping it in a try/catch and logging or handling the error to avoid unexpected crashes.
53-85
: Version compatibility logic is appropriate.
The current rules for version handling (exact match for major=0, otherwisethis.minor >= minor
) is consistent with the stated requirements. This ensures backward compatibility of minor versions while forcing exact matches for v0.x.packages/libraries/federation-link-utils/src/link.ts (2)
5-40
: Validate unknown argument handling.
InlinkFromArgs
, unrecognized arguments are silently ignored. Ensure that ignoring these arguments aligns with desired behavior, or add warnings for unexpected parameters if needed.
42-50
: Utility function is straightforward.
Thenamespaced
function is straightforward and well-documented. It correctly separates directives from normal types by adjusting the "@" prefix.packages/libraries/federation-link-utils/src/index.ts (1)
10-20
: Function design is clear and modular.
detectLinkedImplementations
provides a simple, modular approach to link detection. It neatly delegates link parsing toFederatedLink.fromTypedefs
and leverages eachsupportedSpec
to detect potential matches, keeping concerns well-separated.
test('LinkableSpec and detectLinkedImplementations can be used to easily implement linked schema functionality', () => { | ||
const sdl = ` | ||
directive @meta(name: String!, content: String!) on SCHEMA | FIELD | ||
directive @metadata__example(eg: String!) on FIELD | ||
extend schema | ||
@link(url: "https://specs.apollo.dev/federation/v2.3") | ||
@link(url: "https://specs.graphql-hive.com/metadata/v0.1", import: ["@meta"]) | ||
|
||
type Query { | ||
ping: String @meta(name: "owner", content: "hive-console-team") | ||
pong: String @metadata__example(eg: "1...2...3... Pong") | ||
} | ||
`; | ||
|
||
const metaSpec = new LinkableSpec('https://specs.graphql-hive.com/metadata', { | ||
// The return value could be used to map sdl, collect information, or create a graphql yoga plugin. | ||
// In this test, it's used to collect metadata information from the schema. | ||
'v0.1': resolveImportName => (typeDefs: DocumentNode) => { | ||
const collectedMeta: Record<string, Record<string, string>> = {}; | ||
const metaName = resolveImportName('@meta'); | ||
const exampleName = resolveImportName('@example'); | ||
visit(typeDefs, { | ||
FieldDefinition: node => { | ||
let metaData: Record<string, string> = {}; | ||
const fieldName = node.name.value; | ||
const meta = node.directives?.find(d => d.name.value === metaName); | ||
if (meta) { | ||
metaData['name'] = | ||
( | ||
meta.arguments?.find(a => a.name.value === 'name')?.value as | ||
| StringValueNode | ||
| undefined | ||
)?.value ?? '??'; | ||
metaData['content'] = | ||
( | ||
meta.arguments?.find(a => a.name.value === 'content')?.value as | ||
| StringValueNode | ||
| undefined | ||
)?.value ?? '??'; | ||
} | ||
|
||
const example = node.directives?.find(d => d.name.value === exampleName); | ||
if (example) { | ||
metaData['eg'] = | ||
( | ||
example.arguments?.find(a => a.name.value === 'eg')?.value as | ||
| StringValueNode | ||
| undefined | ||
)?.value ?? '??'; | ||
} | ||
if (Object.keys(metaData).length) { | ||
collectedMeta[fieldName] ??= {}; | ||
collectedMeta[fieldName] = Object.assign(collectedMeta[fieldName], metaData); | ||
} | ||
return; | ||
}, | ||
}); | ||
// collect metadata | ||
return `running on v0.1.\nFound metadata: ${JSON.stringify(collectedMeta)}}`; | ||
}, | ||
'v0.2': _resolveImportName => (_typeDefs: DocumentNode) => { | ||
// collect metadata | ||
return `running on v0.2...`; | ||
}, | ||
}); | ||
const typeDefs = parse(sdl); | ||
const linked = detectLinkedImplementations(typeDefs, [metaSpec]); | ||
expect(linked.map(link => link(typeDefs))).toMatchInlineSnapshot(` | ||
[ | ||
running on v0.1. | ||
Found metadata: {"ping":{"name":"owner","content":"hive-console-team"},"pong":{"eg":"1...2...3... Pong"}}}, | ||
] | ||
`); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling test cases.
The test suite should include cases for error scenarios:
- Invalid SDL
- Unsupported spec versions
- Missing required directive arguments
packages/libraries/federation-link-utils/src/__tests__/index.spec.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/libraries/federation-link-utils/src/link.ts (3)
5-40
: Consider more robust error or fallback handling for missing or invalid arguments.
Currently, ifurl
is not a valid string, the function returnsundefined
, silently skipping link creation. You might consider either throwing an error or returning a diagnostic result to make the behavior explicit for callers.
42-50
: Function name clarity.
The functionnamespaced
is concise and descriptive, but it may be clearer to name it something likeaddNamespacePrefix
to communicate exactly what it does.
52-131
: Use a configurable logger or error mechanism instead ofconsole.warn
.
Usingconsole.warn
(lines 15, 27) directly in a library can be noisy for consumers. A configurable logger or custom error-handling mechanism might give library users more control over log output.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/libraries/federation-link-utils/src/index.ts
(1 hunks)packages/libraries/federation-link-utils/src/link.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
packages/libraries/federation-link-utils/src/index.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/src/link.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
⏰ Context from checks skipped due to timeout of 90000ms (10)
- GitHub Check: test / unit
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: test / db-migrations
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: alpha / cli-artifacts
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: SonarCloud
🔇 Additional comments (3)
packages/libraries/federation-link-utils/src/link.ts (1)
1-4
: Looks well-structured and provides clear imports.
No issues found in these lines.packages/libraries/federation-link-utils/src/index.ts (2)
1-9
: Import and export declarations look good.
They cleanly expose the library’s capabilities.
10-21
: Verify error handling for partial or invalid spec detection.
If adetectImplementation
call throws an exception or returns a partial result, it might be beneficial to handle or log that scenario.Would you like to run a codebase analysis script to identify places where
detectImplementation
might fail or return unexpected values?
🐋 This PR was built and pushed to the following Docker images: Targets: Platforms: Image Tag: Docker Bake metadata{
"app": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/api/health",
"build-arg:IMAGE_DESCRIPTION": "The app of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/app",
"build-arg:PORT": "3000",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/app",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/3bnur9x0ke9trkuk2kwnxw42z",
"containerimage.config.digest": "sha256:0d529c386bc54e4ac355e80d6786ee17b4532b9284dfd1383e5f51f3801f7f9c",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:f39def69bc93ea03ab079052b961bd4d3621a1220b2fef952c241047fbe5c234",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:f39def69bc93ea03ab079052b961bd4d3621a1220b2fef952c241047fbe5c234",
"image.name": "ghcr.io/graphql-hive/app:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/app:linkable_spec_lib-amd64"
},
"buildx.build.warnings": [
{
"vertex": "sha256:de891251bb1d4820b99510bd3289c67536b36a6c33af561986668cb50a73a400",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIwKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 20
},
"end": {
"line": 20
}
}
]
},
{
"vertex": "sha256:cb204f3d9b40827e6f9e8d9d2647a25f41dafc6b802807b43d51752b96de515c",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDExKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 11
},
"end": {
"line": 11
}
}
]
},
{
"vertex": "sha256:de891251bb1d4820b99510bd3289c67536b36a6c33af561986668cb50a73a400",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIyKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 22
},
"end": {
"line": 22
}
}
]
},
{
"vertex": "sha256:cb204f3d9b40827e6f9e8d9d2647a25f41dafc6b802807b43d51752b96de515c",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDEwKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 10
},
"end": {
"line": 10
}
}
]
},
{
"vertex": "sha256:de891251bb1d4820b99510bd3289c67536b36a6c33af561986668cb50a73a400",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIxKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 21
},
"end": {
"line": 21
}
}
]
},
{
"vertex": "sha256:de891251bb1d4820b99510bd3289c67536b36a6c33af561986668cb50a73a400",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRQT1JUJyAobGluZSAyMik=",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 22
},
"end": {
"line": 22
}
}
]
},
{
"vertex": "sha256:cb204f3d9b40827e6f9e8d9d2647a25f41dafc6b802807b43d51752b96de515c",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9USVRMRScgKGxpbmUgMTUp",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 15
},
"end": {
"line": 15
}
}
]
},
{
"vertex": "sha256:cb204f3d9b40827e6f9e8d9d2647a25f41dafc6b802807b43d51752b96de515c",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9ERVNDUklQVElPTicgKGxpbmUgMTcp",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 17
},
"end": {
"line": 17
}
}
]
},
{
"vertex": "sha256:de891251bb1d4820b99510bd3289c67536b36a6c33af561986668cb50a73a400",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAyMSk=",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 21
},
"end": {
"line": 21
}
}
]
},
{
"vertex": "sha256:cb204f3d9b40827e6f9e8d9d2647a25f41dafc6b802807b43d51752b96de515c",
"level": 1,
"short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDEyKQ==",
"detail": [
"TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
],
"url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 12
},
"end": {
"line": 12
}
}
]
},
{
"vertex": "sha256:de891251bb1d4820b99510bd3289c67536b36a6c33af561986668cb50a73a400",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9ERVNDUklQVElPTicgKGxpbmUgMTQp",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 14
},
"end": {
"line": 14
}
}
]
},
{
"vertex": "sha256:cb204f3d9b40827e6f9e8d9d2647a25f41dafc6b802807b43d51752b96de515c",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAxMik=",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "migrations.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 12
},
"end": {
"line": 12
}
}
]
},
{
"vertex": "sha256:de891251bb1d4820b99510bd3289c67536b36a6c33af561986668cb50a73a400",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9USVRMRScgKGxpbmUgMTIp",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 12
},
"end": {
"line": 12
}
}
]
},
{
"vertex": "sha256:de891251bb1d4820b99510bd3289c67536b36a6c33af561986668cb50a73a400",
"level": 1,
"short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAxMyk=",
"detail": [
"VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
],
"url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
"sourceInfo": {
"filename": "services.dockerfile",
"data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
"language": "Dockerfile"
},
"range": [
{
"start": {
"line": 13
},
"end": {
"line": 13
}
}
]
}
],
"composition-federation-2": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "Federation 2 Composition Service for GraphQL Hive.",
"build-arg:IMAGE_TITLE": "graphql-hive/composition-federation-2",
"build-arg:PORT": "3069",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/external-composition",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/k953xvmpspli37zslmbadd91t",
"containerimage.config.digest": "sha256:310b88248e505fd535c44a56c78d1931fdcab8fadf3f58bdf8f7988502f468f8",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:42b43c5ecca2556853b417ac7f8a9f8485fbfc0ef31b8dab3edcebc4f93ce457",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:42b43c5ecca2556853b417ac7f8a9f8485fbfc0ef31b8dab3edcebc4f93ce457",
"image.name": "ghcr.io/graphql-hive/composition-federation-2:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/composition-federation-2:linkable_spec_lib-amd64"
},
"emails": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The emails service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/emails",
"build-arg:PORT": "3006",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/emails",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/48m12qhsg34pf3ebmotmx3i6n",
"containerimage.config.digest": "sha256:a7d5134aa32f967875c0deb4fd7136bf1dbc54de4e465fa444c3881e8bfda1c0",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:4466de47d110b2441e1f1ffe07efddfa6edde08a583de48ac712cec5c123eaca",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:4466de47d110b2441e1f1ffe07efddfa6edde08a583de48ac712cec5c123eaca",
"image.name": "ghcr.io/graphql-hive/emails:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/emails:linkable_spec_lib-amd64"
},
"policy": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The policy service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/policy",
"build-arg:PORT": "3012",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/policy",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/pj704gups8ie1ct14vb85q3jk",
"containerimage.config.digest": "sha256:f066a4fa649a8a8bf2f59e2f644b018dd6b77a31f5e6d7c1d058f1cf8592bc9b",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:ab1b08baa50f6349a73c594434109ec65ee2c104d96e7c30476530507717e563",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:ab1b08baa50f6349a73c594434109ec65ee2c104d96e7c30476530507717e563",
"image.name": "ghcr.io/graphql-hive/policy:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/policy:linkable_spec_lib-amd64"
},
"rate-limit": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The rate limit service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/rate-limit",
"build-arg:PORT": "3009",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/rate-limit",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/nofeomdv89eh50cx6ypzab11k",
"containerimage.config.digest": "sha256:6313ecb9ad0cd53d0aacba6538ac12499b71d9749649c74a064fe71a430f9c34",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:bf125cbe15afa56cbde94cf40863fbd31297602821c92bd70e192391b0eb759e",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:bf125cbe15afa56cbde94cf40863fbd31297602821c92bd70e192391b0eb759e",
"image.name": "ghcr.io/graphql-hive/rate-limit:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/rate-limit:linkable_spec_lib-amd64"
},
"schema": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The schema service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/schema",
"build-arg:PORT": "3002",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/schema",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/naklc23mef7kes1cxiyba07ae",
"containerimage.config.digest": "sha256:5fb6664d68eee949e1c9ebab868a2681c5bc90161801434d4eceafb25490bc51",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:c39ff270c8e2ae13c6ea0c9f3ca89806383199b0a574a470152fcdad28fe7b4a",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:c39ff270c8e2ae13c6ea0c9f3ca89806383199b0a574a470152fcdad28fe7b4a",
"image.name": "ghcr.io/graphql-hive/schema:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/schema:linkable_spec_lib-amd64"
},
"server": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The server service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/server",
"build-arg:PORT": "3001",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/server",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/olfjsnioonch06an59huexxk1",
"containerimage.config.digest": "sha256:06eadd55703427f92f3803ec9e055b4f3da5bbe66a4a4d24f1a486e2f5c91e2e",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:6beb5978e96779693fcb42ae0186de22c2c0d0dd42ba2fe5b50358cb76656aea",
"size": 2076,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:6beb5978e96779693fcb42ae0186de22c2c0d0dd42ba2fe5b50358cb76656aea",
"image.name": "ghcr.io/graphql-hive/server:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/server:linkable_spec_lib-amd64"
},
"storage": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "migrations.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:IMAGE_DESCRIPTION": "The migrations service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/storage",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/yl66fh69xiaq0wabpfflo5ia2",
"containerimage.config.digest": "sha256:552db8fcf3b0bfec90f1ef8fc3195693535fcc8a4ae3a40a2a7eaa34c2210ea0",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:81ba73802b786cacde9db6df7231afd565f84ea3a91770ec9f2cf27f1f291f31",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:81ba73802b786cacde9db6df7231afd565f84ea3a91770ec9f2cf27f1f291f31",
"image.name": "ghcr.io/graphql-hive/storage:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/storage:linkable_spec_lib-amd64"
},
"stripe-billing": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The stripe billing service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/stripe-billing",
"build-arg:PORT": "3010",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/stripe-billing",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/mg1ts04kdfp9m9t58qoud9ys0",
"containerimage.config.digest": "sha256:f9230c5a6ff5c3ebae214c1ed7233efa4d31837c0c97117651c9c55c04bcf37d",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:4f5a2eddaf110538fa8ee7eb3a78957e85cda7e49449077639549aa63b740cb0",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:4f5a2eddaf110538fa8ee7eb3a78957e85cda7e49449077639549aa63b740cb0",
"image.name": "ghcr.io/graphql-hive/stripe-billing:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/stripe-billing:linkable_spec_lib-amd64"
},
"tokens": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The tokens service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/tokens",
"build-arg:PORT": "3003",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/tokens",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/w7rfw80869dt85wb0eju1djdn",
"containerimage.config.digest": "sha256:0dc2321662aa531e4effcd4fd6008cd7d0fe9495dc4cb70ef04be0757f777e51",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:6bedcf383cf6349fa6c2bd1bceb9ecd10c9bd93c806c3bbd70af0756b6759265",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:6bedcf383cf6349fa6c2bd1bceb9ecd10c9bd93c806c3bbd70af0756b6759265",
"image.name": "ghcr.io/graphql-hive/tokens:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/tokens:linkable_spec_lib-amd64"
},
"usage": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The usage ingestor service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/usage",
"build-arg:PORT": "3006",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/usage",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/wmtxj2or59nga8it50o5bhy96",
"containerimage.config.digest": "sha256:9c5f743d2b291ec2e7afee59cc03c4c4542278f0e35fdd8adbfed8422d5a5160",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:9f7f5a8c0d952708af0dd032ad58cf7c175aade77d096e4410fcbc86a5005040",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:9f7f5a8c0d952708af0dd032ad58cf7c175aade77d096e4410fcbc86a5005040",
"image.name": "ghcr.io/graphql-hive/usage:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/usage:linkable_spec_lib-amd64"
},
"usage-estimator": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The usage estimator service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/usage-estimator",
"build-arg:PORT": "3008",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/usage-estimator",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/4l3h2hpwnqvmwi7lktx48p39k",
"containerimage.config.digest": "sha256:404ebb9b5a6453e4d2ec7650348c4131fff9ba463f9a9e40e8f97ac637f5388a",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:df80fac3f3e35f35bfe0297cb2cd5fc7719a95e8d0bea775098f9f13f8bdca46",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:df80fac3f3e35f35bfe0297cb2cd5fc7719a95e8d0bea775098f9f13f8bdca46",
"image.name": "ghcr.io/graphql-hive/usage-estimator:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/usage-estimator:linkable_spec_lib-amd64"
},
"usage-ingestor": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The usage ingestor service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/usage-ingestor",
"build-arg:PORT": "3007",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/usage-ingestor",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/p8oacrfc7qka8d18w330otx0y",
"containerimage.config.digest": "sha256:1aa9d03b7e45d7970f1ef91edad84367a2f89121e76547edfd51b2552fc25870",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:62638380cf8c544a4a5c7928db49f9ce264dcbf92f8aed29646b1efcaa95fb87",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:62638380cf8c544a4a5c7928db49f9ce264dcbf92f8aed29646b1efcaa95fb87",
"image.name": "ghcr.io/graphql-hive/usage-ingestor:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/usage-ingestor:linkable_spec_lib-amd64"
},
"webhooks": {
"buildx.build.provenance": {
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/[email protected]?platform=linux%2Famd64",
"digest": {
"sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "services.dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {
"build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
"build-arg:IMAGE_DESCRIPTION": "The webhooks ingestor service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/webhooks",
"build-arg:PORT": "3005",
"build-arg:RELEASE": "b009d102eb95d325839674fa7f154ef0bb3872a0",
"build-arg:SERVICE_DIR_NAME": "@hive/webhooks",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:dockerfile": "q8yd272t0nohoqmvuapwee526",
"local-sessionid:shared": "q8yd272t0nohoqmvuapwee526"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/amd64"
}
}
},
"buildx.build.ref": "builder-af7cf860-98cb-4e2b-abcb-b4a8048bd034/builder-af7cf860-98cb-4e2b-abcb-b4a8048bd0340/pc0b5lowhth8nfsesvisp6glz",
"containerimage.config.digest": "sha256:867560b99b81ef5adae83d85267bf9b2a81e239ac76e36259c01e70acca197f8",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:ae1becf1b16e86a34b9a84152f45e810da20918dbbaf92354b7df542fe7d54c8",
"size": 2075,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
"containerimage.digest": "sha256:ae1becf1b16e86a34b9a84152f45e810da20918dbbaf92354b7df542fe7d54c8",
"image.name": "ghcr.io/graphql-hive/webhooks:b009d102eb95d325839674fa7f154ef0bb3872a0-amd64,ghcr.io/graphql-hive/webhooks:linkable_spec_lib-amd64"
}
} |
Is supporting Federation 1 out of the scope of this? E.g. we support Thinking about this, I would like to see this library being used on something like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/libraries/federation-link-utils/README.md (2)
9-12
: Correct Grammar in the DescriptionThere is a minor grammatical error on line 9: the phrase "make a custom features" should be revised for correctness. Consider rephrasing it to "create custom features" or "make custom features" for clarity.
-This library can be used to make a custom features for GraphQL schemas backed by Federation's +This library can be used to create custom features for GraphQL schemas backed by Federation's🧰 Tools
🪛 LanguageTool
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...(VB_A_JJ_NNS)
66-68
: Clarify Final Notes on LinkableSpec ImplementationThe concluding explanation regarding
LinkableSpec
is helpful, but it could benefit from additional context. A brief note or a reference link explaining what it means to "always return a yoga plugin" would add clarity for users who might not be familiar with that convention.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/libraries/federation-link-utils/README.md
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
packages/libraries/federation-link-utils/README.md (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
📓 Learnings (1)
packages/libraries/federation-link-utils/README.md (1)
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
🪛 LanguageTool
packages/libraries/federation-link-utils/README.md
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...
(VB_A_JJ_NNS)
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: test / unit
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: alpha / cli-artifacts
🔇 Additional comments (6)
packages/libraries/federation-link-utils/README.md (6)
1-2
: Descriptive Title and OverviewThe file title "GraphQL Hive - federation-link-utils" is clear and descriptive. Consider adding a brief tagline that summarizes the library’s purpose to further orient new users.
3-6
: Clear Introduction ProvidedThe introduction effectively explains what GraphQL Hive offers and provides useful links for more information. Please ensure that the external links remain up-to-date as the project evolves.
7-8
: Well-Placed Section SeparatorThe horizontal rule is appropriately used to separate the introductory content from the rest of the document.
13-18
: Feature List is Clear and ConciseThe features section succinctly lists the library’s core capabilities. In future iterations, you might consider providing additional details or examples for each feature to enhance the user’s understanding.
19-35
: Usage Example for GraphQL Schema is InformativeThe provided GraphQL schema example clearly demonstrates how to extend a schema using the
@link
directive. This example is valuable for users looking to grasp the practical application of the library.
36-64
: Enhance Code Snippet Clarity with Required ImportsThe TypeScript snippet effectively demonstrates how to create a
LinkableSpec
and utilizedetectLinkedImplementations
. However, to improve clarity for developers integrating this code, consider explicitly adding the necessary imports (e.g.,visit
,parse
,DocumentNode
, andStringValueNode
) from the appropriate modules.+// Ensure to import required dependencies from 'graphql' +import { DocumentNode, StringValueNode, visit, parse } from 'graphql';
The |
142969f
to
484e969
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/libraries/federation-link-utils/README.md (1)
66-68
: Clarify the “yoga plugin” RecommendationThe final note suggests always returning a “yoga plugin” without any further explanation. To improve clarity for users who might not be familiar with this term, consider adding a brief explanation or a link to relevant documentation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (14)
packages/libraries/federation-link-utils/README.md
(1 hunks)packages/libraries/federation-link-utils/package.json
(1 hunks)packages/libraries/federation-link-utils/src/__tests__/index.spec.ts
(1 hunks)packages/libraries/federation-link-utils/src/__tests__/link-url.spec.ts
(1 hunks)packages/libraries/federation-link-utils/src/__tests__/link.spec.ts
(1 hunks)packages/libraries/federation-link-utils/src/__tests__/linkable-spec.spec.ts
(1 hunks)packages/libraries/federation-link-utils/src/index.ts
(1 hunks)packages/libraries/federation-link-utils/src/link-import.ts
(1 hunks)packages/libraries/federation-link-utils/src/link-url.ts
(1 hunks)packages/libraries/federation-link-utils/src/link.ts
(1 hunks)packages/libraries/federation-link-utils/src/linkable-spec.ts
(1 hunks)packages/libraries/federation-link-utils/src/version.ts
(1 hunks)packages/libraries/federation-link-utils/tsconfig.json
(1 hunks)tsconfig.json
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (13)
- packages/libraries/federation-link-utils/src/version.ts
- tsconfig.json
- packages/libraries/federation-link-utils/src/index.ts
- packages/libraries/federation-link-utils/src/tests/link-url.spec.ts
- packages/libraries/federation-link-utils/tsconfig.json
- packages/libraries/federation-link-utils/package.json
- packages/libraries/federation-link-utils/src/tests/linkable-spec.spec.ts
- packages/libraries/federation-link-utils/src/tests/link.spec.ts
- packages/libraries/federation-link-utils/src/tests/index.spec.ts
- packages/libraries/federation-link-utils/src/link-import.ts
- packages/libraries/federation-link-utils/src/linkable-spec.ts
- packages/libraries/federation-link-utils/src/link-url.ts
- packages/libraries/federation-link-utils/src/link.ts
🧰 Additional context used
📓 Path-based instructions (1)
packages/libraries/federation-link-utils/README.md (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
📓 Learnings (1)
packages/libraries/federation-link-utils/README.md (1)
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
🪛 LanguageTool
packages/libraries/federation-link-utils/README.md
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...
(VB_A_JJ_NNS)
⏰ Context from checks skipped due to timeout of 90000ms (11)
- GitHub Check: alpha / npm / snapshot
- GitHub Check: test / unit
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: db-types / diff
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: alpha / cli-artifacts
- GitHub Check: SonarCloud
🔇 Additional comments (4)
packages/libraries/federation-link-utils/README.md (4)
1-8
: Clear and Informative IntroductionThe header and opening paragraphs clearly introduce the library and its context within GraphQL Hive. The title, description, and horizontal rule effectively set the stage for the rest of the document.
13-18
: Solid Features SectionThe “Features” list is concise and well organized. It clearly shows the key capabilities of the library such as link version support and import namespacing while keeping external dependencies to a minimum.
19-34
: Effective GraphQL Usage ExampleThe GraphQL snippet effectively demonstrates how to use the custom directive with the
@link
directive. The example is clear and provides a good reference for users.
36-64
: Enhance TypeScript Example with Complete Import GuidanceThe TypeScript snippet thoroughly illustrates how to create and use a
LinkableSpec
. However, functions and types such asvisit
,parse
,DocumentNode
, andStringValueNode
appear in the example without corresponding import statements. Although these omissions might be for brevity, providing clarity on the source of these symbols would help users integrate the snippet more readily.// specs.ts -import { detectLinkedImplementations, LinkableSpec } from '@graphql-hive/federation-link-utils' +import { detectLinkedImplementations, LinkableSpec } from '@graphql-hive/federation-link-utils' +import { visit, parse } from 'graphql'; // Consider adding this import if using the GraphQL library +import type { DocumentNode, StringValueNode } from 'graphql'; // Add proper type imports
This library can be used to make a custom features for GraphQL schemas backed by Federation's | ||
[`@link`](https://www.apollographql.com/docs/graphos/reference/federation/directives#the-link-directive) | ||
directive. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix Grammar in Library Description
There is a grammatical issue with the phrase “a custom features.” It would be clearer to remove the singular article and use a verb that better suits the plural noun. Consider the following adjustment:
-This library can be used to make a custom features for GraphQL schemas backed by Federation's
+This library can be used to create custom features for GraphQL schemas backed by Federation's
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
This library can be used to make a custom features for GraphQL schemas backed by Federation's | |
[`@link`](https://www.apollographql.com/docs/graphos/reference/federation/directives#the-link-directive) | |
directive. | |
This library can be used to create custom features for GraphQL schemas backed by Federation's | |
[`@link`](https://www.apollographql.com/docs/graphos/reference/federation/directives#the-link-directive) | |
directive. |
🧰 Tools
🪛 LanguageTool
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...
(VB_A_JJ_NNS)
I've added a way to support federation 1. However, I'd like to work on refactoring the tag extraction logic in a separate PR to avoid this change getting any larger. If we end up being unhappy with this library, we can iterate in that change or revert this change. Does that sound reasonable? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
packages/libraries/federation-link-utils/src/index.ts (1)
12-32
: Consider adding JSDoc documentation for the function.While the function implementation looks good, adding JSDoc documentation would help users understand:
- The purpose of the function
- The expected format of input parameters
- The structure of the return value
- Example usage
+/** + * Detects and returns implementations from a list of supported specifications based on the links defined in the schema. + * @param typeDefs - The GraphQL schema as a DocumentNode + * @param supportedSpecs - Array of LinkableSpec instances to detect implementations for + * @returns Array of detected implementations + * @example + * ```ts + * const typeDefs = parse(sdl); + * const specs = [new LinkableSpec(...)]; + * const implementations = detectLinkedImplementations(typeDefs, specs); + * ``` + */ export function detectLinkedImplementations<T>( typeDefs: DocumentNode, supportedSpecs: LinkableSpec<T>[], ): T[] {packages/libraries/federation-link-utils/src/linkable-spec.ts (1)
50-53
: Consider using a structured logging solution.Instead of using console.warn directly, consider using a structured logging solution that can be configured based on the environment and allows for better error tracking.
- console.warn( - `Cannot apply @link due to unsupported version found for "${this.identity}". ` + - `Available versions: ${this.sortedVersionKeys.join(', ')} and any version these are compatible compatible with.`, - ); + const message = `Cannot apply @link due to unsupported version found for "${this.identity}". ` + + `Available versions: ${this.sortedVersionKeys.join(', ')} and any version these are compatible with.`; + this.logger?.warn?.(message) ?? console.warn(message);Also, there's a typo in the message: "compatible" is repeated twice.
packages/libraries/federation-link-utils/README.md (1)
40-76
: Enhance the TypeScript example.The example code could be improved in several ways:
- Add type annotations for the
sdl
variable- Show error handling for the
apply
function- Document the expected shape of the return value
// specs.ts import { detectLinkedImplementations, FEDERATION_V1, - LinkableSpec + LinkableSpec, + DocumentNode } from '@graphql-hive/federation-link-utils' +// Define the shape of your implementation +type ExampleImpl = Record<string, string>; + +// Your SDL as a string +const sdl = `...`; + const exampleSpec = new LinkableSpec('https://specs.graphql-hive.com/example', { [FEDERATION_V1]: resolveImportName => (typeDefs: DocumentNode) => { // option to support federation 1 schemas. Be extremely cautious here because versioning // cannot be done safely. }, 'v0.1': resolveImportName => (typeDefs: DocumentNode) => { const examples: Record<string, string> = {} // ... rest of the implementation return examples } }) const typeDefs = parse(sdl) const linkedSpecs = detectLinkedImplementations(typeDefs, [exampleSpec]) -const result = linkedSpecs.map(apply => apply(typeDefs)) +const result = linkedSpecs.map(apply => { + try { + return apply(typeDefs) as ExampleImpl; + } catch (error) { + console.error('Failed to apply spec:', error); + return {}; + } +});
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
packages/libraries/federation-link-utils/README.md
(1 hunks)packages/libraries/federation-link-utils/src/__tests__/index.spec.ts
(1 hunks)packages/libraries/federation-link-utils/src/index.ts
(1 hunks)packages/libraries/federation-link-utils/src/link.ts
(1 hunks)packages/libraries/federation-link-utils/src/linkable-spec.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/libraries/federation-link-utils/src/tests/index.spec.ts
- packages/libraries/federation-link-utils/src/link.ts
🧰 Additional context used
📓 Path-based instructions (3)
packages/libraries/federation-link-utils/src/linkable-spec.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/src/index.ts (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
packages/libraries/federation-link-utils/README.md (1)
Pattern packages/libraries/**
: Most of the dirs here are NPM packages that provides our customers an integration library, in order to get/fetch data from Hive Console API or Hive CDN.
📓 Learnings (1)
packages/libraries/federation-link-utils/README.md (1)
Learnt from: jdolle
PR: graphql-hive/console#6452
File: packages/libraries/linkable-specs/src/__tests__/index.spec.ts:25-25
Timestamp: 2025-02-03T03:41:50.270Z
Learning: The @graphql-hive/linkable-specs package handles directive namespacing automatically through its resolveImportName function. Users should use base directive names (e.g., '@example') rather than fully qualified names (e.g., '@metadata_example') as the package manages the namespace transformation internally.
🪛 LanguageTool
packages/libraries/federation-link-utils/README.md
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...
(VB_A_JJ_NNS)
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: alpha / publish_docker / Build CLI Docker Image
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: alpha / cli-artifacts
🔇 Additional comments (2)
packages/libraries/federation-link-utils/src/index.ts (1)
5-8
: LGTM! Clean and well-organized exports.The exports are properly organized and provide a clear public API for the library.
packages/libraries/federation-link-utils/README.md (1)
9-11
: Fix grammar in library description.There is a grammatical issue in the description.
-This library can be used to make a custom features for GraphQL schemas backed by Federation's +This library can be used to create custom features for GraphQL schemas backed by Federation's🧰 Tools
🪛 LanguageTool
[grammar] ~9-~9: Do not use the singular ‘a’ before the plural noun ‘features’.
Context: ... --- This library can be used to make a custom features for GraphQL schemas backed by Federatio...(VB_A_JJ_NNS)
this.sortedVersionKeys = Object.keys(versions).sort((a, b) => { | ||
const [aMajor, aMinor] = a.split('.').map(Number); | ||
const [bMajor, bMinor] = b.split('.').map(Number); | ||
return bMajor !== aMajor ? bMajor - aMajor : bMinor - aMinor; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Invalid Version Format Handling Required
The current version sorting logic assumes that all version keys strictly follow a valid "major.minor" format. There is no validation (e.g., checking for NaN values or ensuring exactly two numeric parts) to safeguard against invalid version strings, which could lead to unpredictable behavior.
- Location:
packages/libraries/federation-link-utils/src/linkable-spec.ts
(inside the constructor, wheresortedVersionKeys
is initialized) - Issue: No validation or error handling is applied when splitting and converting version strings.
- Recommendation: Add validation logic (or error handling) to check the version string format before performing the sort.
🔗 Analysis chain
Consider handling invalid version formats.
The version sorting logic assumes valid version strings in the format "major.minor". Consider adding validation or error handling for invalid version formats.
I'll run new scripts to inspect the file and look for any error handling or validation related to the version sorting logic. This will help us determine whether we need to validate version formats.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for any non-standard version formats in the codebase
rg -g '*.{ts,js,graphql}' -A 2 '@link\(.*version:'
Length of output: 52
Script:
#!/bin/bash
# 1. Display context for the version sorting logic to see if any validation exists.
rg -C 10 "sortedVersionKeys" packages/libraries/federation-link-utils/src/linkable-spec.ts
# 2. Check for use of isNaN, which might indicate any runtime validation.
rg -n "isNaN" packages/libraries/federation-link-utils/src/linkable-spec.ts
# 3. Search for any warning or error logging (e.g., console.warn) related to version parsing.
rg -n "console.warn" packages/libraries/federation-link-utils/src/linkable-spec.ts
Length of output: 2350
Background
This arose from the desire to add a directive for collecting metadata.
Currently there is no great way to ensure you are following the
@link
spec's defined versioning scheme, and it is very difficult to keep differences between versions straight.Description
This utility can be used to apply changes to a schema, or collect metadata from a schema. It's very flexible.