@soda-gql/builder 0.11.10 → 0.11.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-support.mjs","names":[],"sources":["../src/plugin/errors.ts","../src/plugin/shared-state.ts","../src/plugin/session.ts","../src/plugin/utils/canonical-id.ts"],"sourcesContent":["/**\n * Error types and formatters for plugin-babel.\n * Simplified from plugin-shared to include only types actually used by the Babel transformer.\n */\n\nimport type { CanonicalId } from \"@soda-gql/common\";\nimport type { BuilderError } from \"../types\";\n\ntype OptionsInvalidBuilderConfig = { readonly code: \"INVALID_BUILDER_CONFIG\"; readonly message: string };\ntype OptionsMissingBuilderConfig = { readonly code: \"MISSING_BUILDER_CONFIG\"; readonly message: string };\ntype OptionsConfigLoadFailed = { readonly code: \"CONFIG_LOAD_FAILED\"; readonly message: string };\n\ntype BuilderEntryNotFound = Extract<BuilderError, { code: \"ENTRY_NOT_FOUND\" }>;\ntype BuilderDocDuplicate = Extract<BuilderError, { code: \"DOC_DUPLICATE\" }>;\ntype BuilderCircularDependency = Extract<BuilderError, { code: \"GRAPH_CIRCULAR_DEPENDENCY\" }>;\ntype BuilderModuleEvaluationFailed = Extract<BuilderError, { code: \"RUNTIME_MODULE_LOAD_FAILED\" }>;\ntype BuilderWriteFailed = Extract<BuilderError, { code: \"WRITE_FAILED\" }>;\n\ntype AnalysisMetadataMissingCause = { readonly filename: string };\ntype AnalysisArtifactMissingCause = { readonly filename: string; readonly canonicalId: CanonicalId };\ntype AnalysisUnsupportedArtifactTypeCause = {\n readonly filename: string;\n readonly canonicalId: CanonicalId;\n readonly artifactType: string;\n};\n\ntype PluginErrorBase<Code extends string, Cause> = {\n readonly type: \"PluginError\";\n readonly code: Code;\n readonly message: string;\n readonly cause: Cause;\n};\n\nexport type PluginOptionsInvalidBuilderConfigError = PluginErrorBase<\n \"OPTIONS_INVALID_BUILDER_CONFIG\",\n OptionsInvalidBuilderConfig | OptionsMissingBuilderConfig | OptionsConfigLoadFailed\n> & { readonly stage: \"normalize-options\" };\n\nexport type PluginBuilderEntryNotFoundError = PluginErrorBase<\"SODA_GQL_BUILDER_ENTRY_NOT_FOUND\", BuilderEntryNotFound> & {\n readonly stage: \"builder\";\n readonly entry: string;\n};\n\nexport type PluginBuilderDocDuplicateError = PluginErrorBase<\"SODA_GQL_BUILDER_DOC_DUPLICATE\", BuilderDocDuplicate> & {\n readonly stage: \"builder\";\n readonly name: string;\n readonly sources: readonly string[];\n};\n\nexport type PluginBuilderCircularDependencyError = PluginErrorBase<\n \"SODA_GQL_BUILDER_CIRCULAR_DEPENDENCY\",\n BuilderCircularDependency\n> & { readonly stage: \"builder\"; readonly chain: readonly string[] };\n\nexport type PluginBuilderModuleEvaluationFailedError = PluginErrorBase<\n \"SODA_GQL_BUILDER_MODULE_EVALUATION_FAILED\",\n BuilderModuleEvaluationFailed\n> & { readonly stage: \"builder\"; readonly filePath: string; readonly astPath: string };\n\nexport type PluginBuilderWriteFailedError = PluginErrorBase<\"SODA_GQL_BUILDER_WRITE_FAILED\", BuilderWriteFailed> & {\n readonly stage: \"builder\";\n readonly outPath: string;\n};\n\nexport type PluginBuilderUnexpectedError = PluginErrorBase<\"SODA_GQL_BUILDER_UNEXPECTED\", unknown> & {\n readonly stage: \"builder\";\n};\n\nexport type PluginAnalysisMetadataMissingError = PluginErrorBase<\"SODA_GQL_METADATA_NOT_FOUND\", AnalysisMetadataMissingCause> & {\n readonly stage: \"analysis\";\n readonly filename: string;\n};\n\nexport type PluginAnalysisArtifactMissingError = PluginErrorBase<\n \"SODA_GQL_ANALYSIS_ARTIFACT_NOT_FOUND\",\n AnalysisArtifactMissingCause\n> & { readonly stage: \"analysis\"; readonly filename: string; readonly canonicalId: CanonicalId };\n\nexport type PluginAnalysisUnsupportedArtifactTypeError = PluginErrorBase<\n \"SODA_GQL_UNSUPPORTED_ARTIFACT_TYPE\",\n AnalysisUnsupportedArtifactTypeCause\n> & {\n readonly stage: \"analysis\";\n readonly filename: string;\n readonly canonicalId: CanonicalId;\n readonly artifactType: string;\n};\n\ntype TransformMissingBuilderArgCause = { readonly filename: string; readonly builderType: string; readonly argName: string };\ntype TransformUnsupportedValueTypeCause = { readonly valueType: string };\ntype TransformAstVisitorFailedCause = { readonly filename: string; readonly reason: string };\n\nexport type PluginTransformMissingBuilderArgError = PluginErrorBase<\n \"SODA_GQL_TRANSFORM_MISSING_BUILDER_ARG\",\n TransformMissingBuilderArgCause\n> & {\n readonly stage: \"transform\";\n readonly filename: string;\n readonly builderType: string;\n readonly argName: string;\n};\n\nexport type PluginTransformUnsupportedValueTypeError = PluginErrorBase<\n \"SODA_GQL_TRANSFORM_UNSUPPORTED_VALUE_TYPE\",\n TransformUnsupportedValueTypeCause\n> & { readonly stage: \"transform\"; readonly valueType: string };\n\nexport type PluginTransformAstVisitorFailedError = PluginErrorBase<\n \"SODA_GQL_TRANSFORM_AST_VISITOR_FAILED\",\n TransformAstVisitorFailedCause\n> & { readonly stage: \"transform\"; readonly filename: string; readonly reason: string };\n\n/**\n * Union of all plugin error types.\n */\nexport type PluginError =\n | PluginOptionsInvalidBuilderConfigError\n | PluginBuilderEntryNotFoundError\n | PluginBuilderDocDuplicateError\n | PluginBuilderCircularDependencyError\n | PluginBuilderModuleEvaluationFailedError\n | PluginBuilderWriteFailedError\n | PluginBuilderUnexpectedError\n | PluginAnalysisMetadataMissingError\n | PluginAnalysisArtifactMissingError\n | PluginAnalysisUnsupportedArtifactTypeError\n | PluginTransformMissingBuilderArgError\n | PluginTransformUnsupportedValueTypeError\n | PluginTransformAstVisitorFailedError;\n\n/**\n * Format a PluginError into a human-readable message.\n */\nexport const formatPluginError = (error: PluginError): string => {\n const codePrefix = `[${error.code}]`;\n const stageInfo = \"stage\" in error ? ` (${error.stage})` : \"\";\n return `${codePrefix}${stageInfo} ${error.message}`;\n};\n\n/**\n * Type guard for PluginError.\n */\nexport const isPluginError = (value: unknown): value is PluginError => {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"type\" in value &&\n value.type === \"PluginError\" &&\n \"code\" in value &&\n \"message\" in value\n );\n};\n\n/**\n * Assertion helper for unreachable code paths.\n * This is the ONLY acceptable throw in plugin code.\n */\nexport const assertUnreachable = (value: never, context?: string): never => {\n throw new Error(`[INTERNAL] Unreachable code path${context ? ` in ${context}` : \"\"}: received ${JSON.stringify(value)}`);\n};\n","import type { BuilderArtifact } from \"../artifact/types\";\nimport type { BuilderService } from \"../service\";\nimport type { PluginSession } from \"./session\";\n\n/**\n * Transformer type for code transformation.\n * - 'babel': Use Babel plugin (default, wider compatibility)\n * - 'swc': Use SWC transformer (faster, requires @soda-gql/swc)\n */\nexport type TransformerType = \"babel\" | \"swc\";\n\n/**\n * Minimal interface for SWC transformer.\n * Matches the Transformer interface from @soda-gql/swc.\n */\nexport interface SwcTransformerInterface {\n transform(input: { sourceCode: string; sourcePath: string; inputSourceMap?: string }): {\n transformed: boolean;\n sourceCode: string;\n sourceMap?: string;\n };\n}\n\n/**\n * Shared state between bundler plugins and loaders.\n * Enables efficient artifact sharing across build pipeline stages.\n */\nexport type SharedState = {\n pluginSession: PluginSession | null;\n currentArtifact: BuilderArtifact | null;\n moduleAdjacency: Map<string, Set<string>>;\n generation: number;\n swcTransformer: SwcTransformerInterface | null;\n transformerType: TransformerType | null;\n builderService: BuilderService | null;\n};\n\n// Global state for sharing between plugin and loader\nconst sharedStates = new Map<string, SharedState>();\n\n/**\n * Get shared state for a given project (identified by config path or cwd).\n */\nexport const getSharedState = (key: string): SharedState => {\n let state = sharedStates.get(key);\n if (!state) {\n state = {\n pluginSession: null,\n currentArtifact: null,\n moduleAdjacency: new Map(),\n generation: 0,\n swcTransformer: null,\n transformerType: null,\n builderService: null,\n };\n sharedStates.set(key, state);\n }\n return state;\n};\n\n/**\n * Update shared artifact.\n */\nexport const setSharedArtifact = (\n key: string,\n artifact: BuilderArtifact | null,\n moduleAdjacency?: Map<string, Set<string>>,\n): void => {\n const state = getSharedState(key);\n state.currentArtifact = artifact;\n if (moduleAdjacency) {\n state.moduleAdjacency = moduleAdjacency;\n }\n state.generation++;\n};\n\n/**\n * Get shared artifact.\n */\nexport const getSharedArtifact = (key: string): BuilderArtifact | null => {\n return getSharedState(key).currentArtifact;\n};\n\n/**\n * Get shared plugin session.\n */\nexport const getSharedPluginSession = (key: string): PluginSession | null => {\n return getSharedState(key).pluginSession;\n};\n\n/**\n * Set shared plugin session.\n */\nexport const setSharedPluginSession = (key: string, session: PluginSession | null): void => {\n getSharedState(key).pluginSession = session;\n};\n\n/**\n * Get the state key from config path or cwd.\n */\nexport const getStateKey = (configPath?: string): string => {\n return configPath ?? process.cwd();\n};\n\n/**\n * Set shared SWC transformer.\n */\nexport const setSharedSwcTransformer = (key: string, transformer: SwcTransformerInterface | null): void => {\n getSharedState(key).swcTransformer = transformer;\n};\n\n/**\n * Get shared SWC transformer.\n */\nexport const getSharedSwcTransformer = (key: string): SwcTransformerInterface | null => {\n return getSharedState(key).swcTransformer;\n};\n\n/**\n * Set shared transformer type.\n */\nexport const setSharedTransformerType = (key: string, transformerType: TransformerType | null): void => {\n getSharedState(key).transformerType = transformerType;\n};\n\n/**\n * Get shared transformer type.\n */\nexport const getSharedTransformerType = (key: string): TransformerType | null => {\n return getSharedState(key).transformerType;\n};\n\n/**\n * Get shared BuilderService.\n */\nexport const getSharedBuilderService = (key: string): BuilderService | null => {\n return getSharedState(key).builderService;\n};\n\n/**\n * Set shared BuilderService.\n */\nexport const setSharedBuilderService = (key: string, service: BuilderService | null): void => {\n getSharedState(key).builderService = service;\n};\n","/**\n * Plugin session management for all plugins.\n * Unified from plugin-babel and plugin-swc implementations.\n */\n\nimport { loadConfig, type ResolvedSodaGqlConfig } from \"@soda-gql/config\";\nimport { loadArtifactSync } from \"../artifact/loader\";\nimport type { BuilderArtifact } from \"../artifact/types\";\nimport { formatBuilderErrorForCLI } from \"../errors/formatter\";\nimport type { BuilderService } from \"../service\";\nimport { createBuilderService } from \"../service\";\nimport { getSharedBuilderService, getStateKey, setSharedBuilderService } from \"./shared-state\";\n\n/**\n * Plugin options shared across all plugins.\n */\nexport type PluginOptions = {\n readonly configPath?: string;\n readonly enabled?: boolean;\n /**\n * Whether to fail the build on error.\n * When true (default), throws an error that fails the bundler build.\n * When false, logs the error and continues (graceful degradation).\n */\n readonly failOnError?: boolean;\n};\n\n/**\n * Plugin session containing builder service and configuration.\n */\nexport type PluginSession = {\n readonly config: ResolvedSodaGqlConfig;\n readonly getArtifact: () => BuilderArtifact | null;\n readonly getArtifactAsync: () => Promise<BuilderArtifact | null>;\n /**\n * Whether the session is using a pre-built artifact.\n * When true, artifacts are loaded from a file instead of built dynamically.\n */\n readonly isPrebuiltMode: boolean;\n};\n\n/**\n * Create plugin session by loading config and creating cached builder service.\n * Returns null if disabled or config load fails.\n *\n * @param options - Plugin options\n * @param pluginName - Name of the plugin for error messages\n * @throws Error if failOnError is true and config load fails\n */\nexport const createPluginSession = (options: PluginOptions, pluginName: string): PluginSession | null => {\n const enabled = options.enabled ?? true;\n const failOnError = options.failOnError ?? true;\n\n if (!enabled) {\n return null;\n }\n\n const configResult = loadConfig(options.configPath);\n if (configResult.isErr()) {\n const errorMsg = `[${pluginName}] Failed to load config: ${configResult.error.message}`;\n console.error(errorMsg, {\n code: configResult.error.code,\n filePath: configResult.error.filePath,\n cause: configResult.error.cause,\n });\n if (failOnError) {\n throw new Error(errorMsg);\n }\n return null;\n }\n\n const config = configResult.value;\n\n // Check if pre-built artifact mode is enabled\n if (config.artifact?.path) {\n const artifactResult = loadArtifactSync(config.artifact.path);\n\n if (artifactResult.isErr()) {\n const errorMsg = `[${pluginName}] Failed to load pre-built artifact: ${artifactResult.error.message}`;\n console.error(errorMsg, {\n code: artifactResult.error.code,\n filePath: artifactResult.error.filePath,\n });\n if (failOnError) {\n throw new Error(errorMsg);\n }\n return null;\n }\n\n const prebuiltArtifact = artifactResult.value;\n console.log(`[${pluginName}] Using pre-built artifact: ${config.artifact.path}`);\n\n return {\n config,\n getArtifact: () => prebuiltArtifact,\n getArtifactAsync: async () => prebuiltArtifact,\n isPrebuiltMode: true,\n };\n }\n\n // Dynamic build mode\n const stateKey = getStateKey(options.configPath);\n\n // Use global BuilderService cache to share FileTracker state across plugin instances\n const ensureBuilderService = (): BuilderService => {\n const existing = getSharedBuilderService(stateKey);\n if (existing) {\n return existing;\n }\n\n const service = createBuilderService({ config });\n setSharedBuilderService(stateKey, service);\n return service;\n };\n\n /**\n * Build artifact on every invocation (like tsc-plugin).\n * This ensures the artifact is always up-to-date with the latest source files.\n *\n * @throws Error if failOnError is true and build fails\n */\n const getArtifact = (): BuilderArtifact | null => {\n const builderService = ensureBuilderService();\n const buildResult = builderService.build();\n if (buildResult.isErr()) {\n const formattedError = formatBuilderErrorForCLI(buildResult.error);\n console.error(`[${pluginName}] Build failed:\\n${formattedError}`);\n if (failOnError) {\n throw new Error(`[${pluginName}] ${buildResult.error.message}`);\n }\n return null;\n }\n return buildResult.value;\n };\n\n /**\n * Async version of getArtifact.\n * Supports async metadata factories and parallel element evaluation.\n *\n * @throws Error if failOnError is true and build fails\n */\n const getArtifactAsync = async (): Promise<BuilderArtifact | null> => {\n const builderService = ensureBuilderService();\n const buildResult = await builderService.buildAsync();\n if (buildResult.isErr()) {\n const formattedError = formatBuilderErrorForCLI(buildResult.error);\n console.error(`[${pluginName}] Build failed:\\n${formattedError}`);\n if (failOnError) {\n throw new Error(`[${pluginName}] ${buildResult.error.message}`);\n }\n return null;\n }\n return buildResult.value;\n };\n\n return {\n config,\n getArtifact,\n getArtifactAsync,\n isPrebuiltMode: false,\n };\n};\n","/**\n * Utility for working with canonical IDs.\n */\n\nimport { resolve } from \"node:path\";\nimport { type CanonicalId, createCanonicalId } from \"@soda-gql/common\";\n\n/**\n * Resolve a canonical ID from a filename and AST path.\n */\nexport const resolveCanonicalId = (filename: string, astPath: string): CanonicalId =>\n createCanonicalId(resolve(filename), astPath);\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugin-support.mjs","names":[],"sources":["../src/plugin/errors.ts","../src/plugin/shared-state.ts","../src/plugin/session.ts","../src/plugin/utils/canonical-id.ts"],"sourcesContent":["/**\n * Error types and formatters for plugin-babel.\n * Simplified from plugin-shared to include only types actually used by the Babel transformer.\n */\n\nimport type { CanonicalId } from \"@soda-gql/common\";\nimport type { BuilderError } from \"../types\";\n\ntype OptionsInvalidBuilderConfig = { readonly code: \"INVALID_BUILDER_CONFIG\"; readonly message: string };\ntype OptionsMissingBuilderConfig = { readonly code: \"MISSING_BUILDER_CONFIG\"; readonly message: string };\ntype OptionsConfigLoadFailed = { readonly code: \"CONFIG_LOAD_FAILED\"; readonly message: string };\n\ntype BuilderEntryNotFound = Extract<BuilderError, { code: \"ENTRY_NOT_FOUND\" }>;\ntype BuilderDocDuplicate = Extract<BuilderError, { code: \"DOC_DUPLICATE\" }>;\ntype BuilderCircularDependency = Extract<BuilderError, { code: \"GRAPH_CIRCULAR_DEPENDENCY\" }>;\ntype BuilderModuleEvaluationFailed = Extract<BuilderError, { code: \"RUNTIME_MODULE_LOAD_FAILED\" }>;\ntype BuilderWriteFailed = Extract<BuilderError, { code: \"WRITE_FAILED\" }>;\n\ntype AnalysisMetadataMissingCause = { readonly filename: string };\ntype AnalysisArtifactMissingCause = { readonly filename: string; readonly canonicalId: CanonicalId };\ntype AnalysisUnsupportedArtifactTypeCause = {\n readonly filename: string;\n readonly canonicalId: CanonicalId;\n readonly artifactType: string;\n};\n\ntype PluginErrorBase<Code extends string, Cause> = {\n readonly type: \"PluginError\";\n readonly code: Code;\n readonly message: string;\n readonly cause: Cause;\n};\n\nexport type PluginOptionsInvalidBuilderConfigError = PluginErrorBase<\n \"OPTIONS_INVALID_BUILDER_CONFIG\",\n OptionsInvalidBuilderConfig | OptionsMissingBuilderConfig | OptionsConfigLoadFailed\n> & { readonly stage: \"normalize-options\" };\n\nexport type PluginBuilderEntryNotFoundError = PluginErrorBase<\"SODA_GQL_BUILDER_ENTRY_NOT_FOUND\", BuilderEntryNotFound> & {\n readonly stage: \"builder\";\n readonly entry: string;\n};\n\nexport type PluginBuilderDocDuplicateError = PluginErrorBase<\"SODA_GQL_BUILDER_DOC_DUPLICATE\", BuilderDocDuplicate> & {\n readonly stage: \"builder\";\n readonly name: string;\n readonly sources: readonly string[];\n};\n\nexport type PluginBuilderCircularDependencyError = PluginErrorBase<\n \"SODA_GQL_BUILDER_CIRCULAR_DEPENDENCY\",\n BuilderCircularDependency\n> & { readonly stage: \"builder\"; readonly chain: readonly string[] };\n\nexport type PluginBuilderModuleEvaluationFailedError = PluginErrorBase<\n \"SODA_GQL_BUILDER_MODULE_EVALUATION_FAILED\",\n BuilderModuleEvaluationFailed\n> & { readonly stage: \"builder\"; readonly filePath: string; readonly astPath: string };\n\nexport type PluginBuilderWriteFailedError = PluginErrorBase<\"SODA_GQL_BUILDER_WRITE_FAILED\", BuilderWriteFailed> & {\n readonly stage: \"builder\";\n readonly outPath: string;\n};\n\nexport type PluginBuilderUnexpectedError = PluginErrorBase<\"SODA_GQL_BUILDER_UNEXPECTED\", unknown> & {\n readonly stage: \"builder\";\n};\n\nexport type PluginAnalysisMetadataMissingError = PluginErrorBase<\"SODA_GQL_METADATA_NOT_FOUND\", AnalysisMetadataMissingCause> & {\n readonly stage: \"analysis\";\n readonly filename: string;\n};\n\nexport type PluginAnalysisArtifactMissingError = PluginErrorBase<\n \"SODA_GQL_ANALYSIS_ARTIFACT_NOT_FOUND\",\n AnalysisArtifactMissingCause\n> & { readonly stage: \"analysis\"; readonly filename: string; readonly canonicalId: CanonicalId };\n\nexport type PluginAnalysisUnsupportedArtifactTypeError = PluginErrorBase<\n \"SODA_GQL_UNSUPPORTED_ARTIFACT_TYPE\",\n AnalysisUnsupportedArtifactTypeCause\n> & {\n readonly stage: \"analysis\";\n readonly filename: string;\n readonly canonicalId: CanonicalId;\n readonly artifactType: string;\n};\n\ntype TransformMissingBuilderArgCause = { readonly filename: string; readonly builderType: string; readonly argName: string };\ntype TransformUnsupportedValueTypeCause = { readonly valueType: string };\ntype TransformAstVisitorFailedCause = { readonly filename: string; readonly reason: string };\n\nexport type PluginTransformMissingBuilderArgError = PluginErrorBase<\n \"SODA_GQL_TRANSFORM_MISSING_BUILDER_ARG\",\n TransformMissingBuilderArgCause\n> & {\n readonly stage: \"transform\";\n readonly filename: string;\n readonly builderType: string;\n readonly argName: string;\n};\n\nexport type PluginTransformUnsupportedValueTypeError = PluginErrorBase<\n \"SODA_GQL_TRANSFORM_UNSUPPORTED_VALUE_TYPE\",\n TransformUnsupportedValueTypeCause\n> & { readonly stage: \"transform\"; readonly valueType: string };\n\nexport type PluginTransformAstVisitorFailedError = PluginErrorBase<\n \"SODA_GQL_TRANSFORM_AST_VISITOR_FAILED\",\n TransformAstVisitorFailedCause\n> & { readonly stage: \"transform\"; readonly filename: string; readonly reason: string };\n\n/**\n * Union of all plugin error types.\n */\nexport type PluginError =\n | PluginOptionsInvalidBuilderConfigError\n | PluginBuilderEntryNotFoundError\n | PluginBuilderDocDuplicateError\n | PluginBuilderCircularDependencyError\n | PluginBuilderModuleEvaluationFailedError\n | PluginBuilderWriteFailedError\n | PluginBuilderUnexpectedError\n | PluginAnalysisMetadataMissingError\n | PluginAnalysisArtifactMissingError\n | PluginAnalysisUnsupportedArtifactTypeError\n | PluginTransformMissingBuilderArgError\n | PluginTransformUnsupportedValueTypeError\n | PluginTransformAstVisitorFailedError;\n\n/**\n * Format a PluginError into a human-readable message.\n */\nexport const formatPluginError = (error: PluginError): string => {\n const codePrefix = `[${error.code}]`;\n const stageInfo = \"stage\" in error ? ` (${error.stage})` : \"\";\n return `${codePrefix}${stageInfo} ${error.message}`;\n};\n\n/**\n * Type guard for PluginError.\n */\nexport const isPluginError = (value: unknown): value is PluginError => {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"type\" in value &&\n value.type === \"PluginError\" &&\n \"code\" in value &&\n \"message\" in value\n );\n};\n\n/**\n * Assertion helper for unreachable code paths.\n * This is the ONLY acceptable throw in plugin code.\n */\nexport const assertUnreachable = (value: never, context?: string): never => {\n throw new Error(`[INTERNAL] Unreachable code path${context ? ` in ${context}` : \"\"}: received ${JSON.stringify(value)}`);\n};\n","import type { BuilderArtifact } from \"../artifact/types\";\nimport type { BuilderService } from \"../service\";\nimport type { PluginSession } from \"./session\";\n\n/**\n * Transformer type for code transformation.\n * - 'babel': Use Babel plugin (default, wider compatibility)\n * - 'swc': Use SWC transformer (faster, requires @soda-gql/swc)\n */\nexport type TransformerType = \"babel\" | \"swc\";\n\n/**\n * Minimal interface for SWC transformer.\n * Matches the Transformer interface from @soda-gql/swc.\n */\nexport interface SwcTransformerInterface {\n transform(input: { sourceCode: string; sourcePath: string; inputSourceMap?: string }): {\n transformed: boolean;\n sourceCode: string;\n sourceMap?: string;\n };\n}\n\n/**\n * Shared state between bundler plugins and loaders.\n * Enables efficient artifact sharing across build pipeline stages.\n */\nexport type SharedState = {\n pluginSession: PluginSession | null;\n currentArtifact: BuilderArtifact | null;\n moduleAdjacency: Map<string, Set<string>>;\n generation: number;\n swcTransformer: SwcTransformerInterface | null;\n transformerType: TransformerType | null;\n builderService: BuilderService | null;\n};\n\n// Global state for sharing between plugin and loader\nconst sharedStates = new Map<string, SharedState>();\n\n/**\n * Get shared state for a given project (identified by config path or cwd).\n */\nexport const getSharedState = (key: string): SharedState => {\n let state = sharedStates.get(key);\n if (!state) {\n state = {\n pluginSession: null,\n currentArtifact: null,\n moduleAdjacency: new Map(),\n generation: 0,\n swcTransformer: null,\n transformerType: null,\n builderService: null,\n };\n sharedStates.set(key, state);\n }\n return state;\n};\n\n/**\n * Update shared artifact.\n */\nexport const setSharedArtifact = (\n key: string,\n artifact: BuilderArtifact | null,\n moduleAdjacency?: Map<string, Set<string>>,\n): void => {\n const state = getSharedState(key);\n state.currentArtifact = artifact;\n if (moduleAdjacency) {\n state.moduleAdjacency = moduleAdjacency;\n }\n state.generation++;\n};\n\n/**\n * Get shared artifact.\n */\nexport const getSharedArtifact = (key: string): BuilderArtifact | null => {\n return getSharedState(key).currentArtifact;\n};\n\n/**\n * Get shared plugin session.\n */\nexport const getSharedPluginSession = (key: string): PluginSession | null => {\n return getSharedState(key).pluginSession;\n};\n\n/**\n * Set shared plugin session.\n */\nexport const setSharedPluginSession = (key: string, session: PluginSession | null): void => {\n getSharedState(key).pluginSession = session;\n};\n\n/**\n * Get the state key from config path or cwd.\n */\nexport const getStateKey = (configPath?: string): string => {\n return configPath ?? process.cwd();\n};\n\n/**\n * Set shared SWC transformer.\n */\nexport const setSharedSwcTransformer = (key: string, transformer: SwcTransformerInterface | null): void => {\n getSharedState(key).swcTransformer = transformer;\n};\n\n/**\n * Get shared SWC transformer.\n */\nexport const getSharedSwcTransformer = (key: string): SwcTransformerInterface | null => {\n return getSharedState(key).swcTransformer;\n};\n\n/**\n * Set shared transformer type.\n */\nexport const setSharedTransformerType = (key: string, transformerType: TransformerType | null): void => {\n getSharedState(key).transformerType = transformerType;\n};\n\n/**\n * Get shared transformer type.\n */\nexport const getSharedTransformerType = (key: string): TransformerType | null => {\n return getSharedState(key).transformerType;\n};\n\n/**\n * Get shared BuilderService.\n */\nexport const getSharedBuilderService = (key: string): BuilderService | null => {\n return getSharedState(key).builderService;\n};\n\n/**\n * Set shared BuilderService.\n */\nexport const setSharedBuilderService = (key: string, service: BuilderService | null): void => {\n getSharedState(key).builderService = service;\n};\n","/**\n * Plugin session management for all plugins.\n * Unified from plugin-babel and plugin-swc implementations.\n */\n\nimport { loadConfig, type ResolvedSodaGqlConfig } from \"@soda-gql/config\";\nimport { loadArtifactSync } from \"../artifact/loader\";\nimport type { BuilderArtifact } from \"../artifact/types\";\nimport { formatBuilderErrorForCLI } from \"../errors/formatter\";\nimport type { BuilderService } from \"../service\";\nimport { createBuilderService } from \"../service\";\nimport { getSharedBuilderService, getStateKey, setSharedBuilderService } from \"./shared-state\";\n\n/**\n * Plugin options shared across all plugins.\n */\nexport type PluginOptions = {\n readonly configPath?: string;\n readonly enabled?: boolean;\n /**\n * Whether to fail the build on error.\n * When true (default), throws an error that fails the bundler build.\n * When false, logs the error and continues (graceful degradation).\n */\n readonly failOnError?: boolean;\n};\n\n/**\n * Plugin session containing builder service and configuration.\n */\nexport type PluginSession = {\n readonly config: ResolvedSodaGqlConfig;\n readonly getArtifact: () => BuilderArtifact | null;\n readonly getArtifactAsync: () => Promise<BuilderArtifact | null>;\n /**\n * Whether the session is using a pre-built artifact.\n * When true, artifacts are loaded from a file instead of built dynamically.\n */\n readonly isPrebuiltMode: boolean;\n};\n\n/**\n * Create plugin session by loading config and creating cached builder service.\n * Returns null if disabled or config load fails.\n *\n * @param options - Plugin options\n * @param pluginName - Name of the plugin for error messages\n * @throws Error if failOnError is true and config load fails\n */\nexport const createPluginSession = (options: PluginOptions, pluginName: string): PluginSession | null => {\n const enabled = options.enabled ?? true;\n const failOnError = options.failOnError ?? true;\n\n if (!enabled) {\n return null;\n }\n\n const configResult = loadConfig(options.configPath);\n if (configResult.isErr()) {\n const errorMsg = `[${pluginName}] Failed to load config: ${configResult.error.message}`;\n console.error(errorMsg, {\n code: configResult.error.code,\n filePath: configResult.error.filePath,\n cause: configResult.error.cause,\n });\n if (failOnError) {\n throw new Error(errorMsg);\n }\n return null;\n }\n\n const config = configResult.value;\n\n // Check if pre-built artifact mode is enabled\n if (config.artifact?.path) {\n const artifactResult = loadArtifactSync(config.artifact.path);\n\n if (artifactResult.isErr()) {\n const errorMsg = `[${pluginName}] Failed to load pre-built artifact: ${artifactResult.error.message}`;\n console.error(errorMsg, {\n code: artifactResult.error.code,\n filePath: artifactResult.error.filePath,\n });\n if (failOnError) {\n throw new Error(errorMsg);\n }\n return null;\n }\n\n const prebuiltArtifact = artifactResult.value;\n console.log(`[${pluginName}] Using pre-built artifact: ${config.artifact.path}`);\n\n return {\n config,\n getArtifact: () => prebuiltArtifact,\n getArtifactAsync: async () => prebuiltArtifact,\n isPrebuiltMode: true,\n };\n }\n\n // Dynamic build mode\n const stateKey = getStateKey(options.configPath);\n\n // Use global BuilderService cache to share FileTracker state across plugin instances\n const ensureBuilderService = (): BuilderService => {\n const existing = getSharedBuilderService(stateKey);\n if (existing) {\n return existing;\n }\n\n const service = createBuilderService({ config });\n setSharedBuilderService(stateKey, service);\n return service;\n };\n\n /**\n * Build artifact on every invocation (like tsc-plugin).\n * This ensures the artifact is always up-to-date with the latest source files.\n *\n * @throws Error if failOnError is true and build fails\n */\n const getArtifact = (): BuilderArtifact | null => {\n const builderService = ensureBuilderService();\n const buildResult = builderService.build();\n if (buildResult.isErr()) {\n const formattedError = formatBuilderErrorForCLI(buildResult.error);\n console.error(`[${pluginName}] Build failed:\\n${formattedError}`);\n if (failOnError) {\n throw new Error(`[${pluginName}] ${buildResult.error.message}`);\n }\n return null;\n }\n return buildResult.value;\n };\n\n /**\n * Async version of getArtifact.\n * Supports async metadata factories and parallel element evaluation.\n *\n * @throws Error if failOnError is true and build fails\n */\n const getArtifactAsync = async (): Promise<BuilderArtifact | null> => {\n const builderService = ensureBuilderService();\n const buildResult = await builderService.buildAsync();\n if (buildResult.isErr()) {\n const formattedError = formatBuilderErrorForCLI(buildResult.error);\n console.error(`[${pluginName}] Build failed:\\n${formattedError}`);\n if (failOnError) {\n throw new Error(`[${pluginName}] ${buildResult.error.message}`);\n }\n return null;\n }\n return buildResult.value;\n };\n\n return {\n config,\n getArtifact,\n getArtifactAsync,\n isPrebuiltMode: false,\n };\n};\n","/**\n * Utility for working with canonical IDs.\n */\n\nimport { resolve } from \"node:path\";\nimport { type CanonicalId, createCanonicalId } from \"@soda-gql/common\";\n\n/**\n * Options for resolving a canonical ID.\n */\nexport type ResolveCanonicalIdOptions = {\n /**\n * Base directory for relative path computation.\n * When provided, the canonical ID will use a path relative to this directory.\n */\n readonly baseDir?: string;\n};\n\n/**\n * Resolve a canonical ID from a filename and AST path.\n *\n * @param filename - The source file path (absolute or relative)\n * @param astPath - The AST path within the file\n * @param options - Optional settings including baseDir for relative paths\n * @returns A canonical ID in the format `{path}::{astPath}`\n */\nexport const resolveCanonicalId = (filename: string, astPath: string, options?: ResolveCanonicalIdOptions): CanonicalId => {\n const { baseDir } = options ?? {};\n if (baseDir) {\n return createCanonicalId(filename, astPath, { baseDir });\n }\n return createCanonicalId(resolve(filename), astPath);\n};\n"],"mappings":"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"}
@@ -1154,6 +1154,11 @@ const createIntermediateRegistry = ({ analyses } = {}) => {
1154
1154
  type: "operation",
1155
1155
  element
1156
1156
  };
1157
+ } else if (element instanceof __soda_gql_core.GqlDefine) {
1158
+ artifacts[canonicalId] = {
1159
+ type: "define",
1160
+ element
1161
+ };
1157
1162
  }
1158
1163
  }
1159
1164
  return artifacts;
@@ -1509,35 +1514,69 @@ const createGraphqlSystemIdentifyHelper = (config) => {
1509
1514
  };
1510
1515
  };
1511
1516
 
1517
+ //#endregion
1518
+ //#region packages/builder/src/artifact/canonical-id-utils.ts
1519
+ /**
1520
+ * Parse a canonical ID with validation.
1521
+ * Returns a Result with parsed components or a BuilderError.
1522
+ *
1523
+ * @param canonicalId - The canonical ID to parse
1524
+ * @returns Result with {filePath, astPath} or BuilderError
1525
+ */
1526
+ const parseCanonicalIdSafe = (canonicalId) => {
1527
+ const validation = (0, __soda_gql_common.validateCanonicalId)(canonicalId);
1528
+ if (!validation.isValid) {
1529
+ return (0, neverthrow.err)(builderErrors.canonicalPathInvalid(canonicalId, validation.reason));
1530
+ }
1531
+ return (0, neverthrow.ok)((0, __soda_gql_common.parseCanonicalId)(canonicalId));
1532
+ };
1533
+ /**
1534
+ * Extract file path from canonical ID with validation.
1535
+ * Returns a Result with the file path or a BuilderError.
1536
+ *
1537
+ * @param canonicalId - The canonical ID to extract from
1538
+ * @returns Result with filePath or BuilderError
1539
+ */
1540
+ const extractFilePathSafe = (canonicalId) => {
1541
+ return parseCanonicalIdSafe(canonicalId).map(({ filePath }) => filePath);
1542
+ };
1543
+
1512
1544
  //#endregion
1513
1545
  //#region packages/builder/src/artifact/aggregate.ts
1514
- const canonicalToFilePath$1 = (canonicalId) => canonicalId.split("::")[0] ?? canonicalId;
1515
1546
  const computeContentHash = (prebuild) => {
1516
1547
  const hash = (0, node_crypto.createHash)("sha1");
1517
1548
  hash.update(JSON.stringify(prebuild));
1518
1549
  return hash.digest("hex");
1519
1550
  };
1520
- const emitRegistrationError = (definition, message) => ({
1551
+ const emitRegistrationError = (filePath, astPath, message) => ({
1521
1552
  code: "RUNTIME_MODULE_LOAD_FAILED",
1522
- filePath: canonicalToFilePath$1(definition.canonicalId),
1523
- astPath: definition.astPath,
1553
+ filePath,
1554
+ astPath,
1524
1555
  message
1525
1556
  });
1526
1557
  const aggregate = ({ analyses, elements }) => {
1527
1558
  const registry = new Map();
1528
1559
  for (const analysis of analyses.values()) {
1529
1560
  for (const definition of analysis.definitions) {
1561
+ const parsedResult = parseCanonicalIdSafe(definition.canonicalId);
1562
+ if (parsedResult.isErr()) {
1563
+ return (0, neverthrow.err)(parsedResult.error);
1564
+ }
1565
+ const { filePath, astPath } = parsedResult.value;
1530
1566
  const element = elements[definition.canonicalId];
1531
1567
  if (!element) {
1532
1568
  const availableIds = Object.keys(elements).join(", ");
1533
1569
  const message = `ARTIFACT_NOT_FOUND_IN_RUNTIME_MODULE: ${definition.canonicalId}\nAvailable: ${availableIds}`;
1534
- return (0, neverthrow.err)(emitRegistrationError(definition, message));
1570
+ return (0, neverthrow.err)(emitRegistrationError(filePath, astPath, message));
1571
+ }
1572
+ if (element.type === "define") {
1573
+ continue;
1535
1574
  }
1536
1575
  if (registry.has(definition.canonicalId)) {
1537
- return (0, neverthrow.err)(emitRegistrationError(definition, `ARTIFACT_ALREADY_REGISTERED`));
1576
+ return (0, neverthrow.err)(emitRegistrationError(filePath, astPath, `ARTIFACT_ALREADY_REGISTERED`));
1538
1577
  }
1539
1578
  const metadata = {
1540
- sourcePath: analysis.filePath ?? canonicalToFilePath$1(definition.canonicalId),
1579
+ sourcePath: filePath,
1541
1580
  contentHash: ""
1542
1581
  };
1543
1582
  if (element.type === "fragment") {
@@ -1577,7 +1616,7 @@ const aggregate = ({ analyses, elements }) => {
1577
1616
  });
1578
1617
  continue;
1579
1618
  }
1580
- return (0, neverthrow.err)(emitRegistrationError(definition, "UNKNOWN_ARTIFACT_KIND"));
1619
+ return (0, neverthrow.err)(emitRegistrationError(filePath, astPath, "UNKNOWN_ARTIFACT_KIND"));
1581
1620
  }
1582
1621
  }
1583
1622
  return (0, neverthrow.ok)(registry);
@@ -1585,7 +1624,6 @@ const aggregate = ({ analyses, elements }) => {
1585
1624
 
1586
1625
  //#endregion
1587
1626
  //#region packages/builder/src/artifact/issue-handler.ts
1588
- const canonicalToFilePath = (canonicalId) => canonicalId.split("::")[0] ?? canonicalId;
1589
1627
  const checkIssues = ({ elements }) => {
1590
1628
  const operationNames = new Set();
1591
1629
  for (const [canonicalId, { type, element }] of Object.entries(elements)) {
@@ -1593,7 +1631,11 @@ const checkIssues = ({ elements }) => {
1593
1631
  continue;
1594
1632
  }
1595
1633
  if (operationNames.has(element.operationName)) {
1596
- const sources = [canonicalToFilePath(canonicalId)];
1634
+ const filePathResult = extractFilePathSafe(canonicalId);
1635
+ if (filePathResult.isErr()) {
1636
+ return (0, neverthrow.err)(filePathResult.error);
1637
+ }
1638
+ const sources = [filePathResult.value];
1597
1639
  return (0, neverthrow.err)({
1598
1640
  code: "DOC_DUPLICATE",
1599
1641
  message: `Duplicate document name: ${element.operationName}`,
@@ -1879,7 +1921,7 @@ const unwrapMethodChains$1 = (identifiers, node) => {
1879
1921
  }
1880
1922
  return unwrapMethodChains$1(identifiers, callee.object);
1881
1923
  };
1882
- const collectAllDefinitions$1 = ({ module: module$1, gqlIdentifiers, imports: _imports, exports: exports$1, source }) => {
1924
+ const collectAllDefinitions$1 = ({ module: module$1, gqlIdentifiers, imports: _imports, exports: exports$1, source, baseDir }) => {
1883
1925
  const getPropertyName$1 = (property) => {
1884
1926
  if (!property) {
1885
1927
  return null;
@@ -1897,6 +1939,7 @@ const collectAllDefinitions$1 = ({ module: module$1, gqlIdentifiers, imports: _i
1897
1939
  const exportBindings = createExportBindingsMap(exports$1);
1898
1940
  const tracker = (0, __soda_gql_common.createCanonicalTracker)({
1899
1941
  filePath: module$1.__filePath,
1942
+ baseDir,
1900
1943
  getExportName: (localName) => exportBindings.get(localName)
1901
1944
  });
1902
1945
  const anonymousCounters = new Map();
@@ -2071,7 +2114,7 @@ const collectAllDefinitions$1 = ({ module: module$1, gqlIdentifiers, imports: _i
2071
2114
  visit(statement, []);
2072
2115
  });
2073
2116
  const definitions = pending.map((item) => ({
2074
- canonicalId: (0, __soda_gql_common.createCanonicalId)(module$1.__filePath, item.astPath),
2117
+ canonicalId: (0, __soda_gql_common.createCanonicalId)(module$1.__filePath, item.astPath, { baseDir }),
2075
2118
  astPath: item.astPath,
2076
2119
  isTopLevel: item.isTopLevel,
2077
2120
  isExported: item.isExported,
@@ -2333,7 +2376,8 @@ const swcAdapter = { analyze(input, helper) {
2333
2376
  gqlIdentifiers,
2334
2377
  imports,
2335
2378
  exports: exports$1,
2336
- source: input.source
2379
+ source: input.source,
2380
+ baseDir: input.baseDir
2337
2381
  });
2338
2382
  const diagnostics = [
2339
2383
  ...collectImportDiagnostics$1(swcModule, helper),
@@ -2546,12 +2590,13 @@ const getPropertyName = (name) => {
2546
2590
  /**
2547
2591
  * Collect all gql definitions (exported, non-exported, top-level, nested)
2548
2592
  */
2549
- const collectAllDefinitions = ({ sourceFile, identifiers, exports: exports$1 }) => {
2593
+ const collectAllDefinitions = ({ sourceFile, identifiers, exports: exports$1, baseDir }) => {
2550
2594
  const pending = [];
2551
2595
  const handledCalls = [];
2552
2596
  const exportBindings = createExportBindingsMap(exports$1);
2553
2597
  const tracker = (0, __soda_gql_common.createCanonicalTracker)({
2554
2598
  filePath: sourceFile.fileName,
2599
+ baseDir,
2555
2600
  getExportName: (localName) => exportBindings.get(localName)
2556
2601
  });
2557
2602
  const anonymousCounters = new Map();
@@ -2695,7 +2740,7 @@ const collectAllDefinitions = ({ sourceFile, identifiers, exports: exports$1 })
2695
2740
  visit(statement, []);
2696
2741
  });
2697
2742
  const definitions = pending.map((item) => ({
2698
- canonicalId: (0, __soda_gql_common.createCanonicalId)(sourceFile.fileName, item.astPath),
2743
+ canonicalId: (0, __soda_gql_common.createCanonicalId)(sourceFile.fileName, item.astPath, { baseDir }),
2699
2744
  astPath: item.astPath,
2700
2745
  isTopLevel: item.isTopLevel,
2701
2746
  isExported: item.isExported,
@@ -2899,7 +2944,8 @@ const typescriptAdapter = { analyze(input, helper) {
2899
2944
  const { definitions } = collectAllDefinitions({
2900
2945
  sourceFile,
2901
2946
  identifiers: gqlIdentifiers,
2902
- exports: exports$1
2947
+ exports: exports$1,
2948
+ baseDir: input.baseDir
2903
2949
  });
2904
2950
  const diagnostics = [
2905
2951
  ...collectImportDiagnostics(sourceFile, helper),
@@ -2950,13 +2996,17 @@ const analyzeModuleCore = (input, adapter, graphqlHelper) => {
2950
2996
 
2951
2997
  //#endregion
2952
2998
  //#region packages/builder/src/ast/index.ts
2953
- const createAstAnalyzer = ({ analyzer, graphqlHelper }) => {
2999
+ const createAstAnalyzer = ({ analyzer, graphqlHelper, baseDir }) => {
2954
3000
  const analyze = (input) => {
3001
+ const inputWithBaseDir = {
3002
+ ...input,
3003
+ baseDir
3004
+ };
2955
3005
  if (analyzer === "ts") {
2956
- return analyzeModuleCore(input, typescriptAdapter, graphqlHelper);
3006
+ return analyzeModuleCore(inputWithBaseDir, typescriptAdapter, graphqlHelper);
2957
3007
  }
2958
3008
  if (analyzer === "swc") {
2959
- return analyzeModuleCore(input, swcAdapter, graphqlHelper);
3009
+ return analyzeModuleCore(inputWithBaseDir, swcAdapter, graphqlHelper);
2960
3010
  }
2961
3011
  return assertUnreachable(analyzer, "createAstAnalyzer");
2962
3012
  };
@@ -3361,22 +3411,45 @@ const createDiscoveryCache = (options) => new JsonDiscoveryCache(options);
3361
3411
  /**
3362
3412
  * Extract all unique dependencies (relative + external) from the analysis.
3363
3413
  * Resolves local specifiers immediately so discovery only traverses once.
3414
+ *
3415
+ * Resolution order:
3416
+ * 1. Relative imports → resolveRelativeImportWithExistenceCheck
3417
+ * 2. Alias imports (if aliasResolver provided) → aliasResolver.resolve
3418
+ * 3. Otherwise → mark as external
3364
3419
  */
3365
- const extractModuleDependencies = (analysis) => {
3420
+ const extractModuleDependencies = ({ analysis, aliasResolver }) => {
3366
3421
  const dependencies = new Map();
3367
3422
  const addDependency = (specifier) => {
3368
3423
  if (dependencies.has(specifier)) {
3369
3424
  return;
3370
3425
  }
3371
- const isExternal = (0, __soda_gql_common.isExternalSpecifier)(specifier);
3372
- const resolvedPath = isExternal ? null : (0, __soda_gql_common.resolveRelativeImportWithExistenceCheck)({
3373
- filePath: analysis.filePath,
3374
- specifier
3375
- });
3426
+ if (!(0, __soda_gql_common.isExternalSpecifier)(specifier)) {
3427
+ const resolvedPath = (0, __soda_gql_common.resolveRelativeImportWithExistenceCheck)({
3428
+ filePath: analysis.filePath,
3429
+ specifier
3430
+ });
3431
+ dependencies.set(specifier, {
3432
+ specifier,
3433
+ resolvedPath,
3434
+ isExternal: false
3435
+ });
3436
+ return;
3437
+ }
3438
+ if (aliasResolver) {
3439
+ const resolvedPath = aliasResolver.resolve(specifier);
3440
+ if (resolvedPath) {
3441
+ dependencies.set(specifier, {
3442
+ specifier,
3443
+ resolvedPath,
3444
+ isExternal: false
3445
+ });
3446
+ return;
3447
+ }
3448
+ }
3376
3449
  dependencies.set(specifier, {
3377
3450
  specifier,
3378
- resolvedPath,
3379
- isExternal
3451
+ resolvedPath: null,
3452
+ isExternal: true
3380
3453
  });
3381
3454
  };
3382
3455
  for (const imp of analysis.imports) {
@@ -3530,10 +3603,28 @@ function clearFingerprintCache() {
3530
3603
  //#endregion
3531
3604
  //#region packages/builder/src/discovery/discoverer.ts
3532
3605
  /**
3606
+ * JavaScript file extensions that should be treated as empty modules.
3607
+ * These files are included in the dependency graph but not parsed for definitions.
3608
+ */
3609
+ const JS_FILE_EXTENSIONS = [
3610
+ ".js",
3611
+ ".mjs",
3612
+ ".cjs",
3613
+ ".jsx"
3614
+ ];
3615
+ /**
3616
+ * Check if a file path is a JavaScript file (not TypeScript).
3617
+ * Used to skip AST analysis for JS files that are resolved as fallbacks.
3618
+ */
3619
+ const isJsFile = (filePath) => {
3620
+ const ext = (0, node_path.extname)(filePath).toLowerCase();
3621
+ return JS_FILE_EXTENSIONS.includes(ext);
3622
+ };
3623
+ /**
3533
3624
  * Generator-based module discovery that yields effects for file I/O.
3534
3625
  * This allows the discovery process to be executed with either sync or async schedulers.
3535
3626
  */
3536
- function* discoverModulesGen({ entryPaths, astAnalyzer, incremental }) {
3627
+ function* discoverModulesGen({ entryPaths, astAnalyzer, aliasResolver, incremental }) {
3537
3628
  const snapshots = new Map();
3538
3629
  const stack = [...entryPaths];
3539
3630
  const changedFiles = incremental?.changedFiles ?? new Set();
@@ -3596,12 +3687,27 @@ function* discoverModulesGen({ entryPaths, astAnalyzer, incremental }) {
3596
3687
  continue;
3597
3688
  }
3598
3689
  const signature = createSourceHash(source);
3599
- const analysis = astAnalyzer.analyze({
3600
- filePath,
3601
- source
3602
- });
3690
+ let analysis;
3691
+ if (isJsFile(filePath)) {
3692
+ analysis = {
3693
+ filePath,
3694
+ signature,
3695
+ definitions: [],
3696
+ imports: [],
3697
+ exports: [],
3698
+ diagnostics: []
3699
+ };
3700
+ } else {
3701
+ analysis = astAnalyzer.analyze({
3702
+ filePath,
3703
+ source
3704
+ });
3705
+ }
3603
3706
  cacheMisses++;
3604
- const dependencies = extractModuleDependencies(analysis);
3707
+ const dependencies = extractModuleDependencies({
3708
+ analysis,
3709
+ aliasResolver
3710
+ });
3605
3711
  for (const dep of dependencies) {
3606
3712
  if (!dep.isExternal && dep.resolvedPath && !snapshots.has(dep.resolvedPath)) {
3607
3713
  stack.push(dep.resolvedPath);
@@ -3667,12 +3773,11 @@ const discoverModulesAsync = async (options) => {
3667
3773
  //#endregion
3668
3774
  //#region packages/builder/src/utils/glob.ts
3669
3775
  /**
3670
- * Cross-runtime glob pattern matching abstraction
3671
- * Provides a unified interface for glob operations across Bun and Node.js
3776
+ * Glob pattern matching using fast-glob
3672
3777
  */
3673
3778
  /**
3674
3779
  * Scan files matching glob patterns from the given directory.
3675
- * Supports negation patterns (e.g., "!**\/excluded.ts") when using fast-glob.
3780
+ * Supports negation patterns (e.g., "!**\/excluded.ts").
3676
3781
  *
3677
3782
  * @param patterns - Glob pattern(s). Can be a single pattern or array of patterns.
3678
3783
  * @param cwd - Working directory (defaults to process.cwd())
@@ -3680,18 +3785,6 @@ const discoverModulesAsync = async (options) => {
3680
3785
  */
3681
3786
  const scanGlob = (patterns, cwd = process.cwd()) => {
3682
3787
  const patternArray = Array.isArray(patterns) ? patterns : [patterns];
3683
- const hasNegation = patternArray.some((p) => p.startsWith("!"));
3684
- if (typeof Bun !== "undefined" && Bun.Glob && !hasNegation) {
3685
- const { Glob } = Bun;
3686
- const results = new Set();
3687
- for (const pattern of patternArray) {
3688
- const glob = new Glob(pattern);
3689
- for (const match of glob.scanSync(cwd)) {
3690
- results.add(match);
3691
- }
3692
- }
3693
- return Array.from(results);
3694
- }
3695
3788
  return fast_glob.default.sync(patternArray, {
3696
3789
  cwd,
3697
3790
  dot: true,
@@ -3986,7 +4079,8 @@ const createBuilderSession = (options) => {
3986
4079
  const graphqlHelper = createGraphqlSystemIdentifyHelper(config);
3987
4080
  const ensureAstAnalyzer = (0, __soda_gql_common.cachedFn)(() => createAstAnalyzer({
3988
4081
  analyzer: config.analyzer,
3989
- graphqlHelper
4082
+ graphqlHelper,
4083
+ baseDir: config.baseDir
3990
4084
  }));
3991
4085
  const ensureDiscoveryCache = (0, __soda_gql_common.cachedFn)(() => createDiscoveryCache({
3992
4086
  factory: cacheFactory,
@@ -4033,6 +4127,7 @@ const createBuilderSession = (options) => {
4033
4127
  input: {
4034
4128
  entryPaths,
4035
4129
  astAnalyzer: ensureAstAnalyzer(),
4130
+ aliasResolver: config.tsconfigPaths ? (0, __soda_gql_common.createAliasResolver)(config.tsconfigPaths) : undefined,
4036
4131
  discoveryCache: ensureDiscoveryCache(),
4037
4132
  changedFiles,
4038
4133
  removedFiles,
@@ -4155,7 +4250,7 @@ const prepare = (input) => {
4155
4250
  * This enables single scheduler control at the root level for both sync and async execution.
4156
4251
  */
4157
4252
  function* buildGen(input) {
4158
- const { entryPaths, astAnalyzer, discoveryCache, changedFiles, removedFiles, previousModuleAdjacency, previousIntermediateModules, graphqlSystemPath, graphqlHelper } = input;
4253
+ const { entryPaths, astAnalyzer, aliasResolver, discoveryCache, changedFiles, removedFiles, previousModuleAdjacency, previousIntermediateModules, graphqlSystemPath, graphqlHelper } = input;
4159
4254
  const affectedFiles = collectAffectedFiles({
4160
4255
  changedFiles,
4161
4256
  removedFiles,
@@ -4164,6 +4259,7 @@ function* buildGen(input) {
4164
4259
  const discoveryResult = yield* discoverModulesGen({
4165
4260
  entryPaths,
4166
4261
  astAnalyzer,
4262
+ aliasResolver,
4167
4263
  incremental: {
4168
4264
  cache: discoveryCache,
4169
4265
  changedFiles,
@@ -4392,4 +4488,4 @@ Object.defineProperty(exports, 'loadArtifactSync', {
4392
4488
  return loadArtifactSync;
4393
4489
  }
4394
4490
  });
4395
- //# sourceMappingURL=service-CKlB44r5.cjs.map
4491
+ //# sourceMappingURL=service-ByiDYWPX.cjs.map