@soda-gql/webpack-plugin 0.4.0 → 0.4.2

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.
package/dist/index.cjs CHANGED
@@ -49,6 +49,15 @@ var SodaGqlWebpackPlugin = class SodaGqlWebpackPlugin {
49
49
  */
50
50
  async initialize() {
51
51
  if (this.pluginSession) return;
52
+ const existingSession = (0, __soda_gql_plugin_common.getSharedPluginSession)(this.stateKey);
53
+ if (existingSession) {
54
+ this.pluginSession = existingSession;
55
+ this.currentArtifact = await this.pluginSession.getArtifactAsync();
56
+ (0, __soda_gql_plugin_common.setSharedArtifact)(this.stateKey, this.currentArtifact);
57
+ await this.initializeSwcTransformer();
58
+ this.log(`Reusing session: ${Object.keys(this.currentArtifact?.elements ?? {}).length} elements`);
59
+ return;
60
+ }
52
61
  this.pluginSession = (0, __soda_gql_plugin_common.createPluginSession)(this.options, SodaGqlWebpackPlugin.pluginName);
53
62
  if (!this.pluginSession) {
54
63
  this.log("Plugin disabled or config load failed");
@@ -211,6 +220,18 @@ Object.defineProperty(exports, 'getSharedArtifact', {
211
220
  return __soda_gql_plugin_common.getSharedArtifact;
212
221
  }
213
222
  });
223
+ Object.defineProperty(exports, 'getSharedBuilderService', {
224
+ enumerable: true,
225
+ get: function () {
226
+ return __soda_gql_plugin_common.getSharedBuilderService;
227
+ }
228
+ });
229
+ Object.defineProperty(exports, 'getSharedPluginSession', {
230
+ enumerable: true,
231
+ get: function () {
232
+ return __soda_gql_plugin_common.getSharedPluginSession;
233
+ }
234
+ });
214
235
  Object.defineProperty(exports, 'getSharedState', {
215
236
  enumerable: true,
216
237
  get: function () {
@@ -223,4 +244,16 @@ Object.defineProperty(exports, 'getStateKey', {
223
244
  return __soda_gql_plugin_common.getStateKey;
224
245
  }
225
246
  });
247
+ Object.defineProperty(exports, 'setSharedBuilderService', {
248
+ enumerable: true,
249
+ get: function () {
250
+ return __soda_gql_plugin_common.setSharedBuilderService;
251
+ }
252
+ });
253
+ Object.defineProperty(exports, 'setSharedPluginSession', {
254
+ enumerable: true,
255
+ get: function () {
256
+ return __soda_gql_plugin_common.setSharedPluginSession;
257
+ }
258
+ });
226
259
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type { BuilderArtifact, BuilderArtifactElement } from \"@soda-gql/builder\";\nimport { collectAffectedFiles } from \"@soda-gql/builder\";\nimport { normalizePath } from \"@soda-gql/common\";\nimport {\n createPluginSession,\n getSharedState,\n getStateKey,\n type PluginSession,\n type SwcTransformerInterface,\n setSharedArtifact,\n setSharedPluginSession,\n setSharedSwcTransformer,\n} from \"@soda-gql/plugin-common\";\nimport type { Compiler } from \"webpack\";\nimport type { WebpackPluginOptions } from \"./types\";\n\n/**\n * Webpack plugin for soda-gql that handles incremental rebuilds\n * when model files change during dev server execution.\n */\nexport class SodaGqlWebpackPlugin {\n static readonly pluginName = \"SodaGqlWebpackPlugin\";\n\n private readonly options: WebpackPluginOptions;\n private readonly stateKey: string;\n private pluginSession: PluginSession | null = null;\n private currentArtifact: BuilderArtifact | null = null;\n private previousArtifact: BuilderArtifact | null = null;\n private pendingInvalidations: Set<string> = new Set();\n private swcTransformer: SwcTransformerInterface | null = null;\n\n constructor(options: WebpackPluginOptions = {}) {\n this.options = options;\n this.stateKey = getStateKey(options.configPath);\n }\n\n apply(compiler: Compiler): void {\n // Initialize plugin session on first build\n compiler.hooks.beforeRun.tapAsync(SodaGqlWebpackPlugin.pluginName, async (_compiler, callback) => {\n try {\n await this.initialize();\n callback();\n } catch (error) {\n callback(error as Error);\n }\n });\n\n // Handle watch mode\n compiler.hooks.watchRun.tapAsync(SodaGqlWebpackPlugin.pluginName, async (_compiler, callback) => {\n try {\n await this.handleWatchRun();\n callback();\n } catch (error) {\n callback(error as Error);\n }\n });\n\n // Track file invalidations\n compiler.hooks.invalid.tap(SodaGqlWebpackPlugin.pluginName, (fileName, _changeTime) => {\n if (fileName) {\n this.handleFileInvalidation(fileName);\n }\n });\n\n // Cleanup on watch close\n compiler.hooks.watchClose.tap(SodaGqlWebpackPlugin.pluginName, () => {\n this.cleanup();\n });\n }\n\n /**\n * Initialize plugin session and build initial artifact.\n */\n private async initialize(): Promise<void> {\n if (this.pluginSession) return;\n\n this.pluginSession = createPluginSession(this.options, SodaGqlWebpackPlugin.pluginName);\n if (!this.pluginSession) {\n this.log(\"Plugin disabled or config load failed\");\n return;\n }\n\n // Share the plugin session with loader\n setSharedPluginSession(this.stateKey, this.pluginSession);\n\n // Initial artifact build\n this.currentArtifact = await this.pluginSession.getArtifactAsync();\n\n // Share artifact with loader\n setSharedArtifact(this.stateKey, this.currentArtifact);\n\n // Create SWC transformer if configured\n await this.initializeSwcTransformer();\n\n this.log(`Initial build complete: ${Object.keys(this.currentArtifact?.elements ?? {}).length} elements`);\n }\n\n /**\n * Handle watch mode run - rebuild artifact and compute affected files.\n */\n private async handleWatchRun(): Promise<void> {\n if (!this.pluginSession) {\n await this.initialize();\n }\n\n if (!this.pluginSession) return;\n\n // Store previous artifact for comparison\n this.previousArtifact = this.currentArtifact;\n\n // Rebuild artifact (BuilderService handles change detection internally)\n this.currentArtifact = await this.pluginSession.getArtifactAsync();\n\n // Share artifact with loader\n setSharedArtifact(this.stateKey, this.currentArtifact);\n\n // Reinitialize SWC transformer with new artifact\n await this.initializeSwcTransformer();\n\n if (!this.currentArtifact) {\n this.log(\"Failed to build artifact\");\n return;\n }\n\n // If we have a previous artifact, compute what changed\n if (this.previousArtifact && this.hasArtifactChanged()) {\n const changedFiles = this.getChangedSodaGqlFiles();\n const sharedState = getSharedState(this.stateKey);\n const affectedFiles = this.computeAffectedFiles(changedFiles, sharedState.moduleAdjacency);\n\n this.log(`Changed files: ${changedFiles.size}, Affected files: ${affectedFiles.size}`);\n\n // Store affected files for webpack to pick up\n for (const filePath of affectedFiles) {\n this.pendingInvalidations.add(filePath);\n }\n }\n }\n\n /**\n * Handle file invalidation event from webpack.\n */\n private handleFileInvalidation(fileName: string): void {\n const normalized = normalizePath(fileName);\n if (this.isSodaGqlFile(normalized)) {\n this.log(`soda-gql file changed: ${normalized}`);\n }\n }\n\n /**\n * Check if artifact has changed by comparing element counts and hashes.\n */\n private hasArtifactChanged(): boolean {\n if (!this.previousArtifact || !this.currentArtifact) return true;\n\n const prevCount = Object.keys(this.previousArtifact.elements).length;\n const newCount = Object.keys(this.currentArtifact.elements).length;\n if (prevCount !== newCount) return true;\n\n // Compare individual elements by their content hash\n const prevElements = this.previousArtifact.elements as Record<string, BuilderArtifactElement>;\n const currElements = this.currentArtifact.elements as Record<string, BuilderArtifactElement>;\n\n for (const [id, element] of Object.entries(currElements)) {\n const prevElement = prevElements[id];\n if (!prevElement) return true;\n // Compare using metadata\n if (element.metadata.contentHash !== prevElement.metadata.contentHash) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get files that changed between previous and current artifact.\n */\n private getChangedSodaGqlFiles(): Set<string> {\n const changed = new Set<string>();\n\n if (!this.previousArtifact || !this.currentArtifact) return changed;\n\n const prevElements = this.previousArtifact.elements as Record<string, BuilderArtifactElement>;\n const currElements = this.currentArtifact.elements as Record<string, BuilderArtifactElement>;\n\n // Compare elements by their source paths and content hashes\n for (const [id, element] of Object.entries(currElements)) {\n const prevElement = prevElements[id];\n const sourcePath = element.metadata.sourcePath;\n\n if (!prevElement || prevElement.metadata.contentHash !== element.metadata.contentHash) {\n changed.add(normalizePath(sourcePath));\n }\n }\n\n // Check for removed elements\n for (const [id, element] of Object.entries(prevElements)) {\n if (!currElements[id]) {\n const sourcePath = element.metadata.sourcePath;\n changed.add(normalizePath(sourcePath));\n }\n }\n\n return changed;\n }\n\n /**\n * Compute all files affected by the changed files using module adjacency.\n */\n private computeAffectedFiles(changedFiles: Set<string>, moduleAdjacency: Map<string, Set<string>>): Set<string> {\n // Use the existing collectAffectedFiles from builder\n return collectAffectedFiles({\n changedFiles,\n removedFiles: new Set(),\n previousModuleAdjacency: moduleAdjacency,\n });\n }\n\n /**\n * Check if a file path corresponds to a soda-gql source file.\n */\n private isSodaGqlFile(filePath: string): boolean {\n if (!this.currentArtifact) return false;\n\n const normalized = normalizePath(filePath);\n for (const element of Object.values(this.currentArtifact.elements)) {\n if (normalizePath(element.metadata.sourcePath) === normalized) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Get pending invalidations and clear the set.\n */\n getPendingInvalidations(): Set<string> {\n const invalidations = new Set(this.pendingInvalidations);\n this.pendingInvalidations.clear();\n return invalidations;\n }\n\n /**\n * Initialize SWC transformer if configured.\n * Creates a new transformer instance with the current artifact.\n */\n private async initializeSwcTransformer(): Promise<void> {\n if (this.options.transformer !== \"swc\") {\n return;\n }\n\n if (!this.currentArtifact || !this.pluginSession) {\n this.swcTransformer = null;\n setSharedSwcTransformer(this.stateKey, null);\n return;\n }\n\n try {\n const { createTransformer } = await import(\"@soda-gql/swc-transformer\");\n this.swcTransformer = await createTransformer({\n config: this.pluginSession.config,\n artifact: this.currentArtifact,\n sourceMap: true,\n });\n setSharedSwcTransformer(this.stateKey, this.swcTransformer);\n this.log(\"SWC transformer initialized\");\n } catch (error) {\n console.warn(\n `[@soda-gql/webpack-plugin] Failed to initialize SWC transformer: ${error}. ` +\n \"Make sure @soda-gql/swc-transformer is installed.\",\n );\n this.swcTransformer = null;\n setSharedSwcTransformer(this.stateKey, null);\n }\n }\n\n /**\n * Cleanup resources.\n */\n private cleanup(): void {\n this.pluginSession = null;\n this.currentArtifact = null;\n this.previousArtifact = null;\n this.pendingInvalidations.clear();\n this.swcTransformer = null;\n setSharedPluginSession(this.stateKey, null);\n setSharedArtifact(this.stateKey, null);\n setSharedSwcTransformer(this.stateKey, null);\n }\n\n /**\n * Log a message if debug mode is enabled.\n */\n private log(message: string): void {\n if (this.options.debug) {\n console.log(`[${SodaGqlWebpackPlugin.pluginName}] ${message}`);\n }\n }\n\n /**\n * Get the current artifact (for use by loader).\n */\n getArtifact(): BuilderArtifact | null {\n return this.currentArtifact;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type { BuilderArtifact, BuilderArtifactElement } from \"@soda-gql/builder\";\nimport { collectAffectedFiles } from \"@soda-gql/builder\";\nimport { normalizePath } from \"@soda-gql/common\";\nimport {\n createPluginSession,\n getSharedPluginSession,\n getSharedState,\n getStateKey,\n type PluginSession,\n type SwcTransformerInterface,\n setSharedArtifact,\n setSharedPluginSession,\n setSharedSwcTransformer,\n} from \"@soda-gql/plugin-common\";\nimport type { Compiler } from \"webpack\";\nimport type { WebpackPluginOptions } from \"./types\";\n\n/**\n * Webpack plugin for soda-gql that handles incremental rebuilds\n * when model files change during dev server execution.\n */\nexport class SodaGqlWebpackPlugin {\n static readonly pluginName = \"SodaGqlWebpackPlugin\";\n\n private readonly options: WebpackPluginOptions;\n private readonly stateKey: string;\n private pluginSession: PluginSession | null = null;\n private currentArtifact: BuilderArtifact | null = null;\n private previousArtifact: BuilderArtifact | null = null;\n private pendingInvalidations: Set<string> = new Set();\n private swcTransformer: SwcTransformerInterface | null = null;\n\n constructor(options: WebpackPluginOptions = {}) {\n this.options = options;\n this.stateKey = getStateKey(options.configPath);\n }\n\n apply(compiler: Compiler): void {\n // Initialize plugin session on first build\n compiler.hooks.beforeRun.tapAsync(SodaGqlWebpackPlugin.pluginName, async (_compiler, callback) => {\n try {\n await this.initialize();\n callback();\n } catch (error) {\n callback(error as Error);\n }\n });\n\n // Handle watch mode\n compiler.hooks.watchRun.tapAsync(SodaGqlWebpackPlugin.pluginName, async (_compiler, callback) => {\n try {\n await this.handleWatchRun();\n callback();\n } catch (error) {\n callback(error as Error);\n }\n });\n\n // Track file invalidations\n compiler.hooks.invalid.tap(SodaGqlWebpackPlugin.pluginName, (fileName, _changeTime) => {\n if (fileName) {\n this.handleFileInvalidation(fileName);\n }\n });\n\n // Cleanup on watch close\n compiler.hooks.watchClose.tap(SodaGqlWebpackPlugin.pluginName, () => {\n this.cleanup();\n });\n }\n\n /**\n * Initialize plugin session and build initial artifact.\n */\n private async initialize(): Promise<void> {\n if (this.pluginSession) return;\n\n // Try to reuse existing shared session (e.g., from client compilation in Next.js)\n const existingSession = getSharedPluginSession(this.stateKey);\n if (existingSession) {\n this.pluginSession = existingSession;\n\n // Still need to build artifact for this compilation\n this.currentArtifact = await this.pluginSession.getArtifactAsync();\n\n // Update shared artifact\n setSharedArtifact(this.stateKey, this.currentArtifact);\n\n // Initialize SWC transformer if configured\n await this.initializeSwcTransformer();\n\n this.log(`Reusing session: ${Object.keys(this.currentArtifact?.elements ?? {}).length} elements`);\n return;\n }\n\n // Fall back to creating new session (first plugin instance)\n this.pluginSession = createPluginSession(this.options, SodaGqlWebpackPlugin.pluginName);\n if (!this.pluginSession) {\n this.log(\"Plugin disabled or config load failed\");\n return;\n }\n\n // Share the plugin session with loader and other plugin instances\n setSharedPluginSession(this.stateKey, this.pluginSession);\n\n // Initial artifact build\n this.currentArtifact = await this.pluginSession.getArtifactAsync();\n\n // Share artifact with loader\n setSharedArtifact(this.stateKey, this.currentArtifact);\n\n // Create SWC transformer if configured\n await this.initializeSwcTransformer();\n\n this.log(`Initial build complete: ${Object.keys(this.currentArtifact?.elements ?? {}).length} elements`);\n }\n\n /**\n * Handle watch mode run - rebuild artifact and compute affected files.\n */\n private async handleWatchRun(): Promise<void> {\n if (!this.pluginSession) {\n await this.initialize();\n }\n\n if (!this.pluginSession) return;\n\n // Store previous artifact for comparison\n this.previousArtifact = this.currentArtifact;\n\n // Rebuild artifact (BuilderService handles change detection internally)\n this.currentArtifact = await this.pluginSession.getArtifactAsync();\n\n // Share artifact with loader\n setSharedArtifact(this.stateKey, this.currentArtifact);\n\n // Reinitialize SWC transformer with new artifact\n await this.initializeSwcTransformer();\n\n if (!this.currentArtifact) {\n this.log(\"Failed to build artifact\");\n return;\n }\n\n // If we have a previous artifact, compute what changed\n if (this.previousArtifact && this.hasArtifactChanged()) {\n const changedFiles = this.getChangedSodaGqlFiles();\n const sharedState = getSharedState(this.stateKey);\n const affectedFiles = this.computeAffectedFiles(changedFiles, sharedState.moduleAdjacency);\n\n this.log(`Changed files: ${changedFiles.size}, Affected files: ${affectedFiles.size}`);\n\n // Store affected files for webpack to pick up\n for (const filePath of affectedFiles) {\n this.pendingInvalidations.add(filePath);\n }\n }\n }\n\n /**\n * Handle file invalidation event from webpack.\n */\n private handleFileInvalidation(fileName: string): void {\n const normalized = normalizePath(fileName);\n if (this.isSodaGqlFile(normalized)) {\n this.log(`soda-gql file changed: ${normalized}`);\n }\n }\n\n /**\n * Check if artifact has changed by comparing element counts and hashes.\n */\n private hasArtifactChanged(): boolean {\n if (!this.previousArtifact || !this.currentArtifact) return true;\n\n const prevCount = Object.keys(this.previousArtifact.elements).length;\n const newCount = Object.keys(this.currentArtifact.elements).length;\n if (prevCount !== newCount) return true;\n\n // Compare individual elements by their content hash\n const prevElements = this.previousArtifact.elements as Record<string, BuilderArtifactElement>;\n const currElements = this.currentArtifact.elements as Record<string, BuilderArtifactElement>;\n\n for (const [id, element] of Object.entries(currElements)) {\n const prevElement = prevElements[id];\n if (!prevElement) return true;\n // Compare using metadata\n if (element.metadata.contentHash !== prevElement.metadata.contentHash) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get files that changed between previous and current artifact.\n */\n private getChangedSodaGqlFiles(): Set<string> {\n const changed = new Set<string>();\n\n if (!this.previousArtifact || !this.currentArtifact) return changed;\n\n const prevElements = this.previousArtifact.elements as Record<string, BuilderArtifactElement>;\n const currElements = this.currentArtifact.elements as Record<string, BuilderArtifactElement>;\n\n // Compare elements by their source paths and content hashes\n for (const [id, element] of Object.entries(currElements)) {\n const prevElement = prevElements[id];\n const sourcePath = element.metadata.sourcePath;\n\n if (!prevElement || prevElement.metadata.contentHash !== element.metadata.contentHash) {\n changed.add(normalizePath(sourcePath));\n }\n }\n\n // Check for removed elements\n for (const [id, element] of Object.entries(prevElements)) {\n if (!currElements[id]) {\n const sourcePath = element.metadata.sourcePath;\n changed.add(normalizePath(sourcePath));\n }\n }\n\n return changed;\n }\n\n /**\n * Compute all files affected by the changed files using module adjacency.\n */\n private computeAffectedFiles(changedFiles: Set<string>, moduleAdjacency: Map<string, Set<string>>): Set<string> {\n // Use the existing collectAffectedFiles from builder\n return collectAffectedFiles({\n changedFiles,\n removedFiles: new Set(),\n previousModuleAdjacency: moduleAdjacency,\n });\n }\n\n /**\n * Check if a file path corresponds to a soda-gql source file.\n */\n private isSodaGqlFile(filePath: string): boolean {\n if (!this.currentArtifact) return false;\n\n const normalized = normalizePath(filePath);\n for (const element of Object.values(this.currentArtifact.elements)) {\n if (normalizePath(element.metadata.sourcePath) === normalized) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Get pending invalidations and clear the set.\n */\n getPendingInvalidations(): Set<string> {\n const invalidations = new Set(this.pendingInvalidations);\n this.pendingInvalidations.clear();\n return invalidations;\n }\n\n /**\n * Initialize SWC transformer if configured.\n * Creates a new transformer instance with the current artifact.\n */\n private async initializeSwcTransformer(): Promise<void> {\n if (this.options.transformer !== \"swc\") {\n return;\n }\n\n if (!this.currentArtifact || !this.pluginSession) {\n this.swcTransformer = null;\n setSharedSwcTransformer(this.stateKey, null);\n return;\n }\n\n try {\n const { createTransformer } = await import(\"@soda-gql/swc-transformer\");\n this.swcTransformer = await createTransformer({\n config: this.pluginSession.config,\n artifact: this.currentArtifact,\n sourceMap: true,\n });\n setSharedSwcTransformer(this.stateKey, this.swcTransformer);\n this.log(\"SWC transformer initialized\");\n } catch (error) {\n console.warn(\n `[@soda-gql/webpack-plugin] Failed to initialize SWC transformer: ${error}. ` +\n \"Make sure @soda-gql/swc-transformer is installed.\",\n );\n this.swcTransformer = null;\n setSharedSwcTransformer(this.stateKey, null);\n }\n }\n\n /**\n * Cleanup resources.\n */\n private cleanup(): void {\n this.pluginSession = null;\n this.currentArtifact = null;\n this.previousArtifact = null;\n this.pendingInvalidations.clear();\n this.swcTransformer = null;\n setSharedPluginSession(this.stateKey, null);\n setSharedArtifact(this.stateKey, null);\n setSharedSwcTransformer(this.stateKey, null);\n }\n\n /**\n * Log a message if debug mode is enabled.\n */\n private log(message: string): void {\n if (this.options.debug) {\n console.log(`[${SodaGqlWebpackPlugin.pluginName}] ${message}`);\n }\n }\n\n /**\n * Get the current artifact (for use by loader).\n */\n getArtifact(): BuilderArtifact | null {\n return this.currentArtifact;\n }\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as WebpackLoaderOptions, r as WebpackPluginOptions, t as TransformerType } from "./types-BJUU2U2w.cjs";
2
- import { getSharedArtifact, getSharedState, getStateKey } from "@soda-gql/plugin-common";
2
+ import { getSharedArtifact, getSharedBuilderService, getSharedPluginSession, getSharedState, getStateKey, setSharedBuilderService, setSharedPluginSession } from "@soda-gql/plugin-common";
3
3
  import { BuilderArtifact } from "@soda-gql/builder";
4
4
  import { Compiler } from "webpack";
5
5
 
@@ -71,5 +71,5 @@ declare class SodaGqlWebpackPlugin {
71
71
  getArtifact(): BuilderArtifact | null;
72
72
  }
73
73
  //#endregion
74
- export { SodaGqlWebpackPlugin, type TransformerType, type WebpackLoaderOptions, type WebpackPluginOptions, getSharedArtifact, getSharedState, getStateKey };
74
+ export { SodaGqlWebpackPlugin, type TransformerType, type WebpackLoaderOptions, type WebpackPluginOptions, getSharedArtifact, getSharedBuilderService, getSharedPluginSession, getSharedState, getStateKey, setSharedBuilderService, setSharedPluginSession };
75
75
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/plugin.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAoBA;AAWuB,cAXV,oBAAA,CAWU;EAKL,gBAAA,UAAA,GAAA,sBAAA;EAyMW,iBAAA,OAAA;EAkEZ,iBAAA,QAAA;EAAe,QAAA,aAAA;;;;;wBAhRT;kBAKL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAyMW;;;;;;;;;;;;;;;;;iBAkEZ"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/plugin.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAqBA;AAWuB,cAXV,oBAAA,CAWU;EAKL,gBAAA,UAAA,GAAA,sBAAA;EA4NW,iBAAA,OAAA;EAkEZ,iBAAA,QAAA;EAAe,QAAA,aAAA;;;;;wBAnST;kBAKL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BA4NW;;;;;;;;;;;;;;;;;iBAkEZ"}
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as WebpackLoaderOptions, r as WebpackPluginOptions, t as TransformerType } from "./types-DxhQ4VI-.mjs";
2
- import { getSharedArtifact, getSharedState, getStateKey } from "@soda-gql/plugin-common";
2
+ import { getSharedArtifact, getSharedBuilderService, getSharedPluginSession, getSharedState, getStateKey, setSharedBuilderService, setSharedPluginSession } from "@soda-gql/plugin-common";
3
3
  import { BuilderArtifact } from "@soda-gql/builder";
4
4
  import { Compiler } from "webpack";
5
5
 
@@ -71,5 +71,5 @@ declare class SodaGqlWebpackPlugin {
71
71
  getArtifact(): BuilderArtifact | null;
72
72
  }
73
73
  //#endregion
74
- export { SodaGqlWebpackPlugin, type TransformerType, type WebpackLoaderOptions, type WebpackPluginOptions, getSharedArtifact, getSharedState, getStateKey };
74
+ export { SodaGqlWebpackPlugin, type TransformerType, type WebpackLoaderOptions, type WebpackPluginOptions, getSharedArtifact, getSharedBuilderService, getSharedPluginSession, getSharedState, getStateKey, setSharedBuilderService, setSharedPluginSession };
75
75
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/plugin.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAoBA;AAWuB,cAXV,oBAAA,CAWU;EAKL,gBAAA,UAAA,GAAA,sBAAA;EAyMW,iBAAA,OAAA;EAkEZ,iBAAA,QAAA;EAAe,QAAA,aAAA;;;;;wBAhRT;kBAKL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAyMW;;;;;;;;;;;;;;;;;iBAkEZ"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/plugin.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAqBA;AAWuB,cAXV,oBAAA,CAWU;EAKL,gBAAA,UAAA,GAAA,sBAAA;EA4NW,iBAAA,OAAA;EAkEZ,iBAAA,QAAA;EAAe,QAAA,aAAA;;;;;wBAnST;kBAKL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BA4NW;;;;;;;;;;;;;;;;;iBAkEZ"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { createPluginSession, getSharedArtifact, getSharedState, getSharedState as getSharedState$1, getStateKey, getStateKey as getStateKey$1, setSharedArtifact, setSharedPluginSession, setSharedSwcTransformer } from "@soda-gql/plugin-common";
1
+ import { createPluginSession, getSharedArtifact, getSharedBuilderService, getSharedPluginSession, getSharedPluginSession as getSharedPluginSession$1, getSharedState, getSharedState as getSharedState$1, getStateKey, getStateKey as getStateKey$1, setSharedArtifact, setSharedBuilderService, setSharedPluginSession, setSharedPluginSession as setSharedPluginSession$1, setSharedSwcTransformer } from "@soda-gql/plugin-common";
2
2
  import { collectAffectedFiles } from "@soda-gql/builder";
3
3
  import { normalizePath } from "@soda-gql/common";
4
4
 
@@ -49,12 +49,21 @@ var SodaGqlWebpackPlugin = class SodaGqlWebpackPlugin {
49
49
  */
50
50
  async initialize() {
51
51
  if (this.pluginSession) return;
52
+ const existingSession = getSharedPluginSession$1(this.stateKey);
53
+ if (existingSession) {
54
+ this.pluginSession = existingSession;
55
+ this.currentArtifact = await this.pluginSession.getArtifactAsync();
56
+ setSharedArtifact(this.stateKey, this.currentArtifact);
57
+ await this.initializeSwcTransformer();
58
+ this.log(`Reusing session: ${Object.keys(this.currentArtifact?.elements ?? {}).length} elements`);
59
+ return;
60
+ }
52
61
  this.pluginSession = createPluginSession(this.options, SodaGqlWebpackPlugin.pluginName);
53
62
  if (!this.pluginSession) {
54
63
  this.log("Plugin disabled or config load failed");
55
64
  return;
56
65
  }
57
- setSharedPluginSession(this.stateKey, this.pluginSession);
66
+ setSharedPluginSession$1(this.stateKey, this.pluginSession);
58
67
  this.currentArtifact = await this.pluginSession.getArtifactAsync();
59
68
  setSharedArtifact(this.stateKey, this.currentArtifact);
60
69
  await this.initializeSwcTransformer();
@@ -185,7 +194,7 @@ var SodaGqlWebpackPlugin = class SodaGqlWebpackPlugin {
185
194
  this.previousArtifact = null;
186
195
  this.pendingInvalidations.clear();
187
196
  this.swcTransformer = null;
188
- setSharedPluginSession(this.stateKey, null);
197
+ setSharedPluginSession$1(this.stateKey, null);
189
198
  setSharedArtifact(this.stateKey, null);
190
199
  setSharedSwcTransformer(this.stateKey, null);
191
200
  }
@@ -204,5 +213,5 @@ var SodaGqlWebpackPlugin = class SodaGqlWebpackPlugin {
204
213
  };
205
214
 
206
215
  //#endregion
207
- export { SodaGqlWebpackPlugin, getSharedArtifact, getSharedState, getStateKey };
216
+ export { SodaGqlWebpackPlugin, getSharedArtifact, getSharedBuilderService, getSharedPluginSession, getSharedState, getStateKey, setSharedBuilderService, setSharedPluginSession };
208
217
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["getStateKey","getSharedState"],"sources":["../src/plugin.ts"],"sourcesContent":["import type { BuilderArtifact, BuilderArtifactElement } from \"@soda-gql/builder\";\nimport { collectAffectedFiles } from \"@soda-gql/builder\";\nimport { normalizePath } from \"@soda-gql/common\";\nimport {\n createPluginSession,\n getSharedState,\n getStateKey,\n type PluginSession,\n type SwcTransformerInterface,\n setSharedArtifact,\n setSharedPluginSession,\n setSharedSwcTransformer,\n} from \"@soda-gql/plugin-common\";\nimport type { Compiler } from \"webpack\";\nimport type { WebpackPluginOptions } from \"./types\";\n\n/**\n * Webpack plugin for soda-gql that handles incremental rebuilds\n * when model files change during dev server execution.\n */\nexport class SodaGqlWebpackPlugin {\n static readonly pluginName = \"SodaGqlWebpackPlugin\";\n\n private readonly options: WebpackPluginOptions;\n private readonly stateKey: string;\n private pluginSession: PluginSession | null = null;\n private currentArtifact: BuilderArtifact | null = null;\n private previousArtifact: BuilderArtifact | null = null;\n private pendingInvalidations: Set<string> = new Set();\n private swcTransformer: SwcTransformerInterface | null = null;\n\n constructor(options: WebpackPluginOptions = {}) {\n this.options = options;\n this.stateKey = getStateKey(options.configPath);\n }\n\n apply(compiler: Compiler): void {\n // Initialize plugin session on first build\n compiler.hooks.beforeRun.tapAsync(SodaGqlWebpackPlugin.pluginName, async (_compiler, callback) => {\n try {\n await this.initialize();\n callback();\n } catch (error) {\n callback(error as Error);\n }\n });\n\n // Handle watch mode\n compiler.hooks.watchRun.tapAsync(SodaGqlWebpackPlugin.pluginName, async (_compiler, callback) => {\n try {\n await this.handleWatchRun();\n callback();\n } catch (error) {\n callback(error as Error);\n }\n });\n\n // Track file invalidations\n compiler.hooks.invalid.tap(SodaGqlWebpackPlugin.pluginName, (fileName, _changeTime) => {\n if (fileName) {\n this.handleFileInvalidation(fileName);\n }\n });\n\n // Cleanup on watch close\n compiler.hooks.watchClose.tap(SodaGqlWebpackPlugin.pluginName, () => {\n this.cleanup();\n });\n }\n\n /**\n * Initialize plugin session and build initial artifact.\n */\n private async initialize(): Promise<void> {\n if (this.pluginSession) return;\n\n this.pluginSession = createPluginSession(this.options, SodaGqlWebpackPlugin.pluginName);\n if (!this.pluginSession) {\n this.log(\"Plugin disabled or config load failed\");\n return;\n }\n\n // Share the plugin session with loader\n setSharedPluginSession(this.stateKey, this.pluginSession);\n\n // Initial artifact build\n this.currentArtifact = await this.pluginSession.getArtifactAsync();\n\n // Share artifact with loader\n setSharedArtifact(this.stateKey, this.currentArtifact);\n\n // Create SWC transformer if configured\n await this.initializeSwcTransformer();\n\n this.log(`Initial build complete: ${Object.keys(this.currentArtifact?.elements ?? {}).length} elements`);\n }\n\n /**\n * Handle watch mode run - rebuild artifact and compute affected files.\n */\n private async handleWatchRun(): Promise<void> {\n if (!this.pluginSession) {\n await this.initialize();\n }\n\n if (!this.pluginSession) return;\n\n // Store previous artifact for comparison\n this.previousArtifact = this.currentArtifact;\n\n // Rebuild artifact (BuilderService handles change detection internally)\n this.currentArtifact = await this.pluginSession.getArtifactAsync();\n\n // Share artifact with loader\n setSharedArtifact(this.stateKey, this.currentArtifact);\n\n // Reinitialize SWC transformer with new artifact\n await this.initializeSwcTransformer();\n\n if (!this.currentArtifact) {\n this.log(\"Failed to build artifact\");\n return;\n }\n\n // If we have a previous artifact, compute what changed\n if (this.previousArtifact && this.hasArtifactChanged()) {\n const changedFiles = this.getChangedSodaGqlFiles();\n const sharedState = getSharedState(this.stateKey);\n const affectedFiles = this.computeAffectedFiles(changedFiles, sharedState.moduleAdjacency);\n\n this.log(`Changed files: ${changedFiles.size}, Affected files: ${affectedFiles.size}`);\n\n // Store affected files for webpack to pick up\n for (const filePath of affectedFiles) {\n this.pendingInvalidations.add(filePath);\n }\n }\n }\n\n /**\n * Handle file invalidation event from webpack.\n */\n private handleFileInvalidation(fileName: string): void {\n const normalized = normalizePath(fileName);\n if (this.isSodaGqlFile(normalized)) {\n this.log(`soda-gql file changed: ${normalized}`);\n }\n }\n\n /**\n * Check if artifact has changed by comparing element counts and hashes.\n */\n private hasArtifactChanged(): boolean {\n if (!this.previousArtifact || !this.currentArtifact) return true;\n\n const prevCount = Object.keys(this.previousArtifact.elements).length;\n const newCount = Object.keys(this.currentArtifact.elements).length;\n if (prevCount !== newCount) return true;\n\n // Compare individual elements by their content hash\n const prevElements = this.previousArtifact.elements as Record<string, BuilderArtifactElement>;\n const currElements = this.currentArtifact.elements as Record<string, BuilderArtifactElement>;\n\n for (const [id, element] of Object.entries(currElements)) {\n const prevElement = prevElements[id];\n if (!prevElement) return true;\n // Compare using metadata\n if (element.metadata.contentHash !== prevElement.metadata.contentHash) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get files that changed between previous and current artifact.\n */\n private getChangedSodaGqlFiles(): Set<string> {\n const changed = new Set<string>();\n\n if (!this.previousArtifact || !this.currentArtifact) return changed;\n\n const prevElements = this.previousArtifact.elements as Record<string, BuilderArtifactElement>;\n const currElements = this.currentArtifact.elements as Record<string, BuilderArtifactElement>;\n\n // Compare elements by their source paths and content hashes\n for (const [id, element] of Object.entries(currElements)) {\n const prevElement = prevElements[id];\n const sourcePath = element.metadata.sourcePath;\n\n if (!prevElement || prevElement.metadata.contentHash !== element.metadata.contentHash) {\n changed.add(normalizePath(sourcePath));\n }\n }\n\n // Check for removed elements\n for (const [id, element] of Object.entries(prevElements)) {\n if (!currElements[id]) {\n const sourcePath = element.metadata.sourcePath;\n changed.add(normalizePath(sourcePath));\n }\n }\n\n return changed;\n }\n\n /**\n * Compute all files affected by the changed files using module adjacency.\n */\n private computeAffectedFiles(changedFiles: Set<string>, moduleAdjacency: Map<string, Set<string>>): Set<string> {\n // Use the existing collectAffectedFiles from builder\n return collectAffectedFiles({\n changedFiles,\n removedFiles: new Set(),\n previousModuleAdjacency: moduleAdjacency,\n });\n }\n\n /**\n * Check if a file path corresponds to a soda-gql source file.\n */\n private isSodaGqlFile(filePath: string): boolean {\n if (!this.currentArtifact) return false;\n\n const normalized = normalizePath(filePath);\n for (const element of Object.values(this.currentArtifact.elements)) {\n if (normalizePath(element.metadata.sourcePath) === normalized) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Get pending invalidations and clear the set.\n */\n getPendingInvalidations(): Set<string> {\n const invalidations = new Set(this.pendingInvalidations);\n this.pendingInvalidations.clear();\n return invalidations;\n }\n\n /**\n * Initialize SWC transformer if configured.\n * Creates a new transformer instance with the current artifact.\n */\n private async initializeSwcTransformer(): Promise<void> {\n if (this.options.transformer !== \"swc\") {\n return;\n }\n\n if (!this.currentArtifact || !this.pluginSession) {\n this.swcTransformer = null;\n setSharedSwcTransformer(this.stateKey, null);\n return;\n }\n\n try {\n const { createTransformer } = await import(\"@soda-gql/swc-transformer\");\n this.swcTransformer = await createTransformer({\n config: this.pluginSession.config,\n artifact: this.currentArtifact,\n sourceMap: true,\n });\n setSharedSwcTransformer(this.stateKey, this.swcTransformer);\n this.log(\"SWC transformer initialized\");\n } catch (error) {\n console.warn(\n `[@soda-gql/webpack-plugin] Failed to initialize SWC transformer: ${error}. ` +\n \"Make sure @soda-gql/swc-transformer is installed.\",\n );\n this.swcTransformer = null;\n setSharedSwcTransformer(this.stateKey, null);\n }\n }\n\n /**\n * Cleanup resources.\n */\n private cleanup(): void {\n this.pluginSession = null;\n this.currentArtifact = null;\n this.previousArtifact = null;\n this.pendingInvalidations.clear();\n this.swcTransformer = null;\n setSharedPluginSession(this.stateKey, null);\n setSharedArtifact(this.stateKey, null);\n setSharedSwcTransformer(this.stateKey, null);\n }\n\n /**\n * Log a message if debug mode is enabled.\n */\n private log(message: string): void {\n if (this.options.debug) {\n console.log(`[${SodaGqlWebpackPlugin.pluginName}] ${message}`);\n }\n }\n\n /**\n * Get the current artifact (for use by loader).\n */\n getArtifact(): BuilderArtifact | null {\n return this.currentArtifact;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["getStateKey","getSharedPluginSession","getSharedState"],"sources":["../src/plugin.ts"],"sourcesContent":["import type { BuilderArtifact, BuilderArtifactElement } from \"@soda-gql/builder\";\nimport { collectAffectedFiles } from \"@soda-gql/builder\";\nimport { normalizePath } from \"@soda-gql/common\";\nimport {\n createPluginSession,\n getSharedPluginSession,\n getSharedState,\n getStateKey,\n type PluginSession,\n type SwcTransformerInterface,\n setSharedArtifact,\n setSharedPluginSession,\n setSharedSwcTransformer,\n} from \"@soda-gql/plugin-common\";\nimport type { Compiler } from \"webpack\";\nimport type { WebpackPluginOptions } from \"./types\";\n\n/**\n * Webpack plugin for soda-gql that handles incremental rebuilds\n * when model files change during dev server execution.\n */\nexport class SodaGqlWebpackPlugin {\n static readonly pluginName = \"SodaGqlWebpackPlugin\";\n\n private readonly options: WebpackPluginOptions;\n private readonly stateKey: string;\n private pluginSession: PluginSession | null = null;\n private currentArtifact: BuilderArtifact | null = null;\n private previousArtifact: BuilderArtifact | null = null;\n private pendingInvalidations: Set<string> = new Set();\n private swcTransformer: SwcTransformerInterface | null = null;\n\n constructor(options: WebpackPluginOptions = {}) {\n this.options = options;\n this.stateKey = getStateKey(options.configPath);\n }\n\n apply(compiler: Compiler): void {\n // Initialize plugin session on first build\n compiler.hooks.beforeRun.tapAsync(SodaGqlWebpackPlugin.pluginName, async (_compiler, callback) => {\n try {\n await this.initialize();\n callback();\n } catch (error) {\n callback(error as Error);\n }\n });\n\n // Handle watch mode\n compiler.hooks.watchRun.tapAsync(SodaGqlWebpackPlugin.pluginName, async (_compiler, callback) => {\n try {\n await this.handleWatchRun();\n callback();\n } catch (error) {\n callback(error as Error);\n }\n });\n\n // Track file invalidations\n compiler.hooks.invalid.tap(SodaGqlWebpackPlugin.pluginName, (fileName, _changeTime) => {\n if (fileName) {\n this.handleFileInvalidation(fileName);\n }\n });\n\n // Cleanup on watch close\n compiler.hooks.watchClose.tap(SodaGqlWebpackPlugin.pluginName, () => {\n this.cleanup();\n });\n }\n\n /**\n * Initialize plugin session and build initial artifact.\n */\n private async initialize(): Promise<void> {\n if (this.pluginSession) return;\n\n // Try to reuse existing shared session (e.g., from client compilation in Next.js)\n const existingSession = getSharedPluginSession(this.stateKey);\n if (existingSession) {\n this.pluginSession = existingSession;\n\n // Still need to build artifact for this compilation\n this.currentArtifact = await this.pluginSession.getArtifactAsync();\n\n // Update shared artifact\n setSharedArtifact(this.stateKey, this.currentArtifact);\n\n // Initialize SWC transformer if configured\n await this.initializeSwcTransformer();\n\n this.log(`Reusing session: ${Object.keys(this.currentArtifact?.elements ?? {}).length} elements`);\n return;\n }\n\n // Fall back to creating new session (first plugin instance)\n this.pluginSession = createPluginSession(this.options, SodaGqlWebpackPlugin.pluginName);\n if (!this.pluginSession) {\n this.log(\"Plugin disabled or config load failed\");\n return;\n }\n\n // Share the plugin session with loader and other plugin instances\n setSharedPluginSession(this.stateKey, this.pluginSession);\n\n // Initial artifact build\n this.currentArtifact = await this.pluginSession.getArtifactAsync();\n\n // Share artifact with loader\n setSharedArtifact(this.stateKey, this.currentArtifact);\n\n // Create SWC transformer if configured\n await this.initializeSwcTransformer();\n\n this.log(`Initial build complete: ${Object.keys(this.currentArtifact?.elements ?? {}).length} elements`);\n }\n\n /**\n * Handle watch mode run - rebuild artifact and compute affected files.\n */\n private async handleWatchRun(): Promise<void> {\n if (!this.pluginSession) {\n await this.initialize();\n }\n\n if (!this.pluginSession) return;\n\n // Store previous artifact for comparison\n this.previousArtifact = this.currentArtifact;\n\n // Rebuild artifact (BuilderService handles change detection internally)\n this.currentArtifact = await this.pluginSession.getArtifactAsync();\n\n // Share artifact with loader\n setSharedArtifact(this.stateKey, this.currentArtifact);\n\n // Reinitialize SWC transformer with new artifact\n await this.initializeSwcTransformer();\n\n if (!this.currentArtifact) {\n this.log(\"Failed to build artifact\");\n return;\n }\n\n // If we have a previous artifact, compute what changed\n if (this.previousArtifact && this.hasArtifactChanged()) {\n const changedFiles = this.getChangedSodaGqlFiles();\n const sharedState = getSharedState(this.stateKey);\n const affectedFiles = this.computeAffectedFiles(changedFiles, sharedState.moduleAdjacency);\n\n this.log(`Changed files: ${changedFiles.size}, Affected files: ${affectedFiles.size}`);\n\n // Store affected files for webpack to pick up\n for (const filePath of affectedFiles) {\n this.pendingInvalidations.add(filePath);\n }\n }\n }\n\n /**\n * Handle file invalidation event from webpack.\n */\n private handleFileInvalidation(fileName: string): void {\n const normalized = normalizePath(fileName);\n if (this.isSodaGqlFile(normalized)) {\n this.log(`soda-gql file changed: ${normalized}`);\n }\n }\n\n /**\n * Check if artifact has changed by comparing element counts and hashes.\n */\n private hasArtifactChanged(): boolean {\n if (!this.previousArtifact || !this.currentArtifact) return true;\n\n const prevCount = Object.keys(this.previousArtifact.elements).length;\n const newCount = Object.keys(this.currentArtifact.elements).length;\n if (prevCount !== newCount) return true;\n\n // Compare individual elements by their content hash\n const prevElements = this.previousArtifact.elements as Record<string, BuilderArtifactElement>;\n const currElements = this.currentArtifact.elements as Record<string, BuilderArtifactElement>;\n\n for (const [id, element] of Object.entries(currElements)) {\n const prevElement = prevElements[id];\n if (!prevElement) return true;\n // Compare using metadata\n if (element.metadata.contentHash !== prevElement.metadata.contentHash) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get files that changed between previous and current artifact.\n */\n private getChangedSodaGqlFiles(): Set<string> {\n const changed = new Set<string>();\n\n if (!this.previousArtifact || !this.currentArtifact) return changed;\n\n const prevElements = this.previousArtifact.elements as Record<string, BuilderArtifactElement>;\n const currElements = this.currentArtifact.elements as Record<string, BuilderArtifactElement>;\n\n // Compare elements by their source paths and content hashes\n for (const [id, element] of Object.entries(currElements)) {\n const prevElement = prevElements[id];\n const sourcePath = element.metadata.sourcePath;\n\n if (!prevElement || prevElement.metadata.contentHash !== element.metadata.contentHash) {\n changed.add(normalizePath(sourcePath));\n }\n }\n\n // Check for removed elements\n for (const [id, element] of Object.entries(prevElements)) {\n if (!currElements[id]) {\n const sourcePath = element.metadata.sourcePath;\n changed.add(normalizePath(sourcePath));\n }\n }\n\n return changed;\n }\n\n /**\n * Compute all files affected by the changed files using module adjacency.\n */\n private computeAffectedFiles(changedFiles: Set<string>, moduleAdjacency: Map<string, Set<string>>): Set<string> {\n // Use the existing collectAffectedFiles from builder\n return collectAffectedFiles({\n changedFiles,\n removedFiles: new Set(),\n previousModuleAdjacency: moduleAdjacency,\n });\n }\n\n /**\n * Check if a file path corresponds to a soda-gql source file.\n */\n private isSodaGqlFile(filePath: string): boolean {\n if (!this.currentArtifact) return false;\n\n const normalized = normalizePath(filePath);\n for (const element of Object.values(this.currentArtifact.elements)) {\n if (normalizePath(element.metadata.sourcePath) === normalized) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Get pending invalidations and clear the set.\n */\n getPendingInvalidations(): Set<string> {\n const invalidations = new Set(this.pendingInvalidations);\n this.pendingInvalidations.clear();\n return invalidations;\n }\n\n /**\n * Initialize SWC transformer if configured.\n * Creates a new transformer instance with the current artifact.\n */\n private async initializeSwcTransformer(): Promise<void> {\n if (this.options.transformer !== \"swc\") {\n return;\n }\n\n if (!this.currentArtifact || !this.pluginSession) {\n this.swcTransformer = null;\n setSharedSwcTransformer(this.stateKey, null);\n return;\n }\n\n try {\n const { createTransformer } = await import(\"@soda-gql/swc-transformer\");\n this.swcTransformer = await createTransformer({\n config: this.pluginSession.config,\n artifact: this.currentArtifact,\n sourceMap: true,\n });\n setSharedSwcTransformer(this.stateKey, this.swcTransformer);\n this.log(\"SWC transformer initialized\");\n } catch (error) {\n console.warn(\n `[@soda-gql/webpack-plugin] Failed to initialize SWC transformer: ${error}. ` +\n \"Make sure @soda-gql/swc-transformer is installed.\",\n );\n this.swcTransformer = null;\n setSharedSwcTransformer(this.stateKey, null);\n }\n }\n\n /**\n * Cleanup resources.\n */\n private cleanup(): void {\n this.pluginSession = null;\n this.currentArtifact = null;\n this.previousArtifact = null;\n this.pendingInvalidations.clear();\n this.swcTransformer = null;\n setSharedPluginSession(this.stateKey, null);\n setSharedArtifact(this.stateKey, null);\n setSharedSwcTransformer(this.stateKey, null);\n }\n\n /**\n * Log a message if debug mode is enabled.\n */\n private log(message: string): void {\n if (this.options.debug) {\n console.log(`[${SodaGqlWebpackPlugin.pluginName}] ${message}`);\n }\n }\n\n /**\n * Get the current artifact (for use by loader).\n */\n getArtifact(): BuilderArtifact | null {\n return this.currentArtifact;\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soda-gql/webpack-plugin",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Webpack plugin for soda-gql with HMR support",
5
5
  "type": "module",
6
6
  "private": false,
@@ -55,18 +55,18 @@
55
55
  "./package.json": "./package.json"
56
56
  },
57
57
  "dependencies": {
58
- "@soda-gql/builder": "0.4.0",
59
- "@soda-gql/common": "0.4.0",
60
- "@soda-gql/config": "0.4.0",
61
- "@soda-gql/core": "0.4.0",
62
- "@soda-gql/plugin-common": "0.4.0",
63
- "@soda-gql/babel-transformer": "0.4.0"
58
+ "@soda-gql/builder": "0.4.2",
59
+ "@soda-gql/common": "0.4.2",
60
+ "@soda-gql/config": "0.4.2",
61
+ "@soda-gql/core": "0.4.2",
62
+ "@soda-gql/plugin-common": "0.4.2",
63
+ "@soda-gql/babel-transformer": "0.4.2"
64
64
  },
65
65
  "devDependencies": {
66
- "@soda-gql/swc-transformer": "0.4.0"
66
+ "@soda-gql/swc-transformer": "0.4.2"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "webpack": "^5.0.0",
70
- "@soda-gql/swc-transformer": "0.4.0"
70
+ "@soda-gql/swc-transformer": "0.4.2"
71
71
  }
72
72
  }