@intlayer/engine 9.5.11 → 9.6.0

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.
Files changed (111) hide show
  1. package/dist/assets/installSkills/skills/bundle-optimization.md +123 -0
  2. package/dist/assets/installSkills/skills/cli.md +28 -1
  3. package/dist/assets/installSkills/skills/compat.md +1 -5
  4. package/dist/assets/installSkills/skills/content.md +8 -2
  5. package/dist/assets/installSkills/skills/dev-tools.md +8 -6
  6. package/dist/assets/installSkills/skills/next-js.md +2 -2
  7. package/dist/assets/installSkills/skills/usage.md +1 -1
  8. package/dist/cjs/build.cjs +5 -0
  9. package/dist/cjs/cli.cjs +3 -0
  10. package/dist/cjs/init/index.cjs +14 -14
  11. package/dist/cjs/init/index.cjs.map +1 -1
  12. package/dist/cjs/init/utils/backendPackages.cjs +15 -0
  13. package/dist/cjs/init/utils/backendPackages.cjs.map +1 -0
  14. package/dist/cjs/init/utils/index.cjs +2 -3
  15. package/dist/cjs/init/utils/packageManager.cjs +1 -1
  16. package/dist/cjs/init/utils/packageManager.cjs.map +1 -1
  17. package/dist/cjs/installMCP/installMCP.cjs +35 -25
  18. package/dist/cjs/installMCP/installMCP.cjs.map +1 -1
  19. package/dist/cjs/installSkills/index.cjs +28 -1
  20. package/dist/cjs/installSkills/index.cjs.map +1 -1
  21. package/dist/cjs/listGitFiles.cjs +3 -5
  22. package/dist/cjs/listGitFiles.cjs.map +1 -1
  23. package/dist/cjs/listProjects.cjs +1 -2
  24. package/dist/cjs/listProjects.cjs.map +1 -1
  25. package/dist/cjs/loadDictionaries/loadDictionaries.cjs +9 -8
  26. package/dist/cjs/loadDictionaries/loadDictionaries.cjs.map +1 -1
  27. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs +3 -5
  28. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs.map +1 -1
  29. package/dist/cjs/loadDictionaries/remoteDictionaryClient.cjs +18 -0
  30. package/dist/cjs/loadDictionaries/remoteDictionaryClient.cjs.map +1 -0
  31. package/dist/cjs/prepareIntlayerServer.cjs +132 -0
  32. package/dist/cjs/prepareIntlayerServer.cjs.map +1 -0
  33. package/dist/cjs/utils/getProcessChainCommands.cjs +117 -0
  34. package/dist/cjs/utils/getProcessChainCommands.cjs.map +1 -0
  35. package/dist/cjs/utils/index.cjs +2 -0
  36. package/dist/cjs/utils/startContentWatcher.cjs +99 -0
  37. package/dist/cjs/utils/startContentWatcher.cjs.map +1 -0
  38. package/dist/cjs/watcher.cjs +2 -2
  39. package/dist/cjs/watcher.cjs.map +1 -1
  40. package/dist/cjs/writeJsonIfChanged.cjs.map +1 -1
  41. package/dist/esm/build.mjs +2 -1
  42. package/dist/esm/cli.mjs +4 -4
  43. package/dist/esm/init/index.mjs +13 -13
  44. package/dist/esm/init/index.mjs.map +1 -1
  45. package/dist/esm/init/utils/backendPackages.mjs +14 -0
  46. package/dist/esm/init/utils/backendPackages.mjs.map +1 -0
  47. package/dist/esm/init/utils/index.mjs +2 -2
  48. package/dist/esm/init/utils/packageManager.mjs +1 -1
  49. package/dist/esm/init/utils/packageManager.mjs.map +1 -1
  50. package/dist/esm/installMCP/installMCP.mjs +35 -25
  51. package/dist/esm/installMCP/installMCP.mjs.map +1 -1
  52. package/dist/esm/installSkills/index.mjs +29 -3
  53. package/dist/esm/installSkills/index.mjs.map +1 -1
  54. package/dist/esm/listGitFiles.mjs +1 -1
  55. package/dist/esm/listGitFiles.mjs.map +1 -1
  56. package/dist/esm/listProjects.mjs +1 -1
  57. package/dist/esm/listProjects.mjs.map +1 -1
  58. package/dist/esm/loadDictionaries/loadDictionaries.mjs +9 -8
  59. package/dist/esm/loadDictionaries/loadDictionaries.mjs.map +1 -1
  60. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs +2 -4
  61. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs.map +1 -1
  62. package/dist/esm/loadDictionaries/remoteDictionaryClient.mjs +16 -0
  63. package/dist/esm/loadDictionaries/remoteDictionaryClient.mjs.map +1 -0
  64. package/dist/esm/prepareIntlayerServer.mjs +128 -0
  65. package/dist/esm/prepareIntlayerServer.mjs.map +1 -0
  66. package/dist/esm/utils/getProcessChainCommands.mjs +115 -0
  67. package/dist/esm/utils/getProcessChainCommands.mjs.map +1 -0
  68. package/dist/esm/utils/index.mjs +2 -1
  69. package/dist/esm/utils/runParallel/pidTree.mjs +3 -3
  70. package/dist/esm/utils/runParallel/pidTree.mjs.map +1 -1
  71. package/dist/esm/utils/runParallel/ps.mjs +2 -2
  72. package/dist/esm/utils/runParallel/ps.mjs.map +1 -1
  73. package/dist/esm/utils/runParallel/wmic.mjs +2 -2
  74. package/dist/esm/utils/runParallel/wmic.mjs.map +1 -1
  75. package/dist/esm/utils/startContentWatcher.mjs +98 -0
  76. package/dist/esm/utils/startContentWatcher.mjs.map +1 -0
  77. package/dist/esm/watcher.mjs +1 -1
  78. package/dist/esm/watcher.mjs.map +1 -1
  79. package/dist/esm/writeJsonIfChanged.mjs +1 -1
  80. package/dist/esm/writeJsonIfChanged.mjs.map +1 -1
  81. package/dist/types/build.d.ts +2 -1
  82. package/dist/types/cli.d.ts +4 -4
  83. package/dist/types/init/index.d.ts +1 -1
  84. package/dist/types/init/index.d.ts.map +1 -1
  85. package/dist/types/init/utils/backendPackages.d.ts +5 -0
  86. package/dist/types/init/utils/backendPackages.d.ts.map +1 -0
  87. package/dist/types/init/utils/index.d.ts +2 -2
  88. package/dist/types/init/utils/packageManager.d.ts +5 -0
  89. package/dist/types/init/utils/packageManager.d.ts.map +1 -1
  90. package/dist/types/installMCP/installMCP.d.ts +4 -0
  91. package/dist/types/installMCP/installMCP.d.ts.map +1 -1
  92. package/dist/types/installSkills/index.d.ts +7 -0
  93. package/dist/types/installSkills/index.d.ts.map +1 -1
  94. package/dist/types/loadDictionaries/loadRemoteDictionaries.d.ts.map +1 -1
  95. package/dist/types/loadDictionaries/remoteDictionaryClient.d.ts +14 -0
  96. package/dist/types/loadDictionaries/remoteDictionaryClient.d.ts.map +1 -0
  97. package/dist/types/prepareIntlayerServer.d.ts +67 -0
  98. package/dist/types/prepareIntlayerServer.d.ts.map +1 -0
  99. package/dist/types/utils/getProcessChainCommands.d.ts +35 -0
  100. package/dist/types/utils/getProcessChainCommands.d.ts.map +1 -0
  101. package/dist/types/utils/index.d.ts +2 -1
  102. package/dist/types/utils/startContentWatcher.d.ts +40 -0
  103. package/dist/types/utils/startContentWatcher.d.ts.map +1 -0
  104. package/dist/types/watcher.d.ts.map +1 -1
  105. package/package.json +9 -9
  106. package/dist/cjs/init/utils/devScript.cjs +0 -57
  107. package/dist/cjs/init/utils/devScript.cjs.map +0 -1
  108. package/dist/esm/init/utils/devScript.mjs +0 -55
  109. package/dist/esm/init/utils/devScript.mjs.map +0 -1
  110. package/dist/types/init/utils/devScript.d.ts +0 -48
  111. package/dist/types/init/utils/devScript.d.ts.map +0 -1
@@ -0,0 +1,98 @@
1
+ import { acquireContentWatcherLock, getCliContentWatcherLabel, getContentWatcherOwner, reportRedundantContentWatcher } from "./contentWatcherLock.mjs";
2
+ import { getAppLogger } from "@intlayer/config/logger";
3
+
4
+ //#region src/utils/startContentWatcher.ts
5
+ /**
6
+ * How often a process that lost the ownership race checks whether the owner is
7
+ * gone, so it can take over once that process stops (e.g. a short-lived config
8
+ * process, or a second dev server).
9
+ */
10
+ const TAKEOVER_POLL_INTERVAL_MS = 5e3;
11
+ /**
12
+ * Per-process state, kept on `globalThis` rather than in module scope: a process
13
+ * can load both the CJS and ESM builds of this package, and hot-reloading
14
+ * servers (`bun --hot`, Vite SSR) re-evaluate modules without restarting — each
15
+ * copy must still see the watcher the first one started.
16
+ */
17
+ const getContentWatcherState = () => {
18
+ const stateKey = Symbol.for("intlayer.contentWatcher");
19
+ const globalScope = globalThis;
20
+ globalScope[stateKey] ??= {
21
+ isWatching: false,
22
+ isClaimInFlight: false
23
+ };
24
+ return globalScope[stateKey];
25
+ };
26
+ const claimAndWatch = async (configuration, options) => {
27
+ const state = getContentWatcherState();
28
+ if (!await acquireContentWatcherLock(configuration, {
29
+ source: "bundler",
30
+ label: options.label
31
+ })) {
32
+ const owner = await getContentWatcherOwner(configuration);
33
+ if (owner?.source === "cli") {
34
+ reportRedundantContentWatcher(configuration, {
35
+ cliLabel: owner.label,
36
+ bundlerLabel: options.label
37
+ });
38
+ return;
39
+ }
40
+ setTimeout(() => {
41
+ startContentWatcher(configuration, options);
42
+ }, TAKEOVER_POLL_INTERVAL_MS).unref?.();
43
+ return;
44
+ }
45
+ state.isWatching = true;
46
+ try {
47
+ const { watch } = await import("../watcher.mjs");
48
+ await watch({ configuration });
49
+ } catch (error) {
50
+ state.isWatching = false;
51
+ getAppLogger(configuration)(["Failed to watch Intlayer content declarations:", error], { level: "error" });
52
+ }
53
+ };
54
+ /**
55
+ * Starts the content declaration watcher from an integration (bundler plugin or
56
+ * server middleware), making sure only one watcher rebuilds a project's
57
+ * dictionaries.
58
+ *
59
+ * - Idempotent within a process, across module copies and hot reloads.
60
+ * - Stands down, with an explanation, when `intlayer watch` already covers the
61
+ * project, whether it spawned this process (`--with`) or runs elsewhere.
62
+ * - Otherwise the first process to take the project lock watches; the others
63
+ * retry in the background to take over once it stops.
64
+ *
65
+ * Not awaitable on purpose: a dev server must not wait on the watcher to serve.
66
+ *
67
+ * @param configuration - The resolved Intlayer configuration.
68
+ * @param options - How the integration identifies itself.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * configureServer() {
73
+ * startContentWatcher(configuration, { label: 'vite-intlayer' });
74
+ * }
75
+ * ```
76
+ */
77
+ const startContentWatcher = (configuration, options) => {
78
+ const state = getContentWatcherState();
79
+ if (state.isWatching || state.isClaimInFlight) return;
80
+ if (!configuration.content.watch) return;
81
+ if (options.getShouldSkip?.()) return;
82
+ const cliWatcherLabel = getCliContentWatcherLabel();
83
+ if (cliWatcherLabel) {
84
+ reportRedundantContentWatcher(configuration, {
85
+ cliLabel: cliWatcherLabel,
86
+ bundlerLabel: options.label
87
+ });
88
+ return;
89
+ }
90
+ state.isClaimInFlight = true;
91
+ claimAndWatch(configuration, options).finally(() => {
92
+ state.isClaimInFlight = false;
93
+ });
94
+ };
95
+
96
+ //#endregion
97
+ export { startContentWatcher };
98
+ //# sourceMappingURL=startContentWatcher.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startContentWatcher.mjs","names":[],"sources":["../../../src/utils/startContentWatcher.ts"],"sourcesContent":["import { getAppLogger } from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport {\n acquireContentWatcherLock,\n getCliContentWatcherLabel,\n getContentWatcherOwner,\n reportRedundantContentWatcher,\n} from './contentWatcherLock';\n\n/**\n * How often a process that lost the ownership race checks whether the owner is\n * gone, so it can take over once that process stops (e.g. a short-lived config\n * process, or a second dev server).\n */\nconst TAKEOVER_POLL_INTERVAL_MS = 5000;\n\nexport type StartContentWatcherOptions = {\n /**\n * How the integration names itself in the lock and in messages, e.g.\n * `vite-intlayer`.\n */\n label: string;\n /**\n * Whether this process must never own the watcher, re-checked on every\n * attempt (e.g. a helper process that outlives the dev server).\n */\n getShouldSkip?: () => boolean;\n};\n\ntype ContentWatcherState = {\n /** Set once the watcher is running in this process. */\n isWatching: boolean;\n /**\n * Set while an ownership attempt is in flight: taking the lock is\n * asynchronous, and integrations re-enter on config reloads or server\n * restarts.\n */\n isClaimInFlight: boolean;\n};\n\n/**\n * Per-process state, kept on `globalThis` rather than in module scope: a process\n * can load both the CJS and ESM builds of this package, and hot-reloading\n * servers (`bun --hot`, Vite SSR) re-evaluate modules without restarting — each\n * copy must still see the watcher the first one started.\n */\nconst getContentWatcherState = (): ContentWatcherState => {\n const stateKey = Symbol.for('intlayer.contentWatcher');\n const globalScope = globalThis as typeof globalThis & {\n [key: symbol]: ContentWatcherState | undefined;\n };\n\n globalScope[stateKey] ??= { isWatching: false, isClaimInFlight: false };\n\n return globalScope[stateKey];\n};\n\nconst claimAndWatch = async (\n configuration: IntlayerConfig,\n options: StartContentWatcherOptions\n): Promise<void> => {\n const state = getContentWatcherState();\n\n const hasAcquiredLock = await acquireContentWatcherLock(configuration, {\n source: 'bundler',\n label: options.label,\n });\n\n if (!hasAcquiredLock) {\n const owner = await getContentWatcherOwner(configuration);\n\n // A CLI watcher started from another terminal is just as redundant as one\n // wrapping this command, and worth the same explanation.\n if (owner?.source === 'cli') {\n reportRedundantContentWatcher(configuration, {\n cliLabel: owner.label,\n bundlerLabel: options.label,\n });\n return;\n }\n\n // Another integration owns the watcher: retry in the background so this\n // process picks it up if that one stops first.\n const retryTimer = setTimeout(() => {\n startContentWatcher(configuration, options);\n }, TAKEOVER_POLL_INTERVAL_MS);\n\n // Unreferenced so a process whose only remaining work is this retry can\n // still exit.\n retryTimer.unref?.();\n\n return;\n }\n\n state.isWatching = true;\n\n try {\n // Imported lazily: the watcher pulls in `@parcel/watcher`, a native module\n // with no business being loaded during a production build.\n const { watch } = await import('../watcher');\n\n await watch({ configuration });\n } catch (error) {\n state.isWatching = false;\n\n getAppLogger(configuration)(\n ['Failed to watch Intlayer content declarations:', error],\n { level: 'error' }\n );\n }\n};\n\n/**\n * Starts the content declaration watcher from an integration (bundler plugin or\n * server middleware), making sure only one watcher rebuilds a project's\n * dictionaries.\n *\n * - Idempotent within a process, across module copies and hot reloads.\n * - Stands down, with an explanation, when `intlayer watch` already covers the\n * project, whether it spawned this process (`--with`) or runs elsewhere.\n * - Otherwise the first process to take the project lock watches; the others\n * retry in the background to take over once it stops.\n *\n * Not awaitable on purpose: a dev server must not wait on the watcher to serve.\n *\n * @param configuration - The resolved Intlayer configuration.\n * @param options - How the integration identifies itself.\n *\n * @example\n * ```ts\n * configureServer() {\n * startContentWatcher(configuration, { label: 'vite-intlayer' });\n * }\n * ```\n */\nexport const startContentWatcher = (\n configuration: IntlayerConfig,\n options: StartContentWatcherOptions\n): void => {\n const state = getContentWatcherState();\n\n if (state.isWatching || state.isClaimInFlight) return;\n if (!configuration.content.watch) return;\n if (options.getShouldSkip?.()) return;\n\n // Spawned by `intlayer watch --with`: the CLI watcher covers the project, and\n // this is known from the environment alone — no need to touch the lock.\n const cliWatcherLabel = getCliContentWatcherLabel();\n\n if (cliWatcherLabel) {\n reportRedundantContentWatcher(configuration, {\n cliLabel: cliWatcherLabel,\n bundlerLabel: options.label,\n });\n return;\n }\n\n state.isClaimInFlight = true;\n\n claimAndWatch(configuration, options).finally(() => {\n state.isClaimInFlight = false;\n });\n};\n"],"mappings":";;;;;;;;;AAcA,MAAM,4BAA4B;;;;;;;AAgClC,MAAM,+BAAoD;CACxD,MAAM,WAAW,OAAO,IAAI,yBAAyB;CACrD,MAAM,cAAc;CAIpB,YAAY,cAAc;EAAE,YAAY;EAAO,iBAAiB;CAAM;CAEtE,OAAO,YAAY;AACrB;AAEA,MAAM,gBAAgB,OACpB,eACA,YACkB;CAClB,MAAM,QAAQ,uBAAuB;CAOrC,IAAI,CAAC,MALyB,0BAA0B,eAAe;EACrE,QAAQ;EACR,OAAO,QAAQ;CACjB,CAAC,GAEqB;EACpB,MAAM,QAAQ,MAAM,uBAAuB,aAAa;EAIxD,IAAI,OAAO,WAAW,OAAO;GAC3B,8BAA8B,eAAe;IAC3C,UAAU,MAAM;IAChB,cAAc,QAAQ;GACxB,CAAC;GACD;EACF;EAUA,AANmB,iBAAiB;GAClC,oBAAoB,eAAe,OAAO;EAC5C,GAAG,yBAIM,CAAC,CAAC,QAAQ;EAEnB;CACF;CAEA,MAAM,aAAa;CAEnB,IAAI;EAGF,MAAM,EAAE,UAAU,MAAM,OAAO;EAE/B,MAAM,MAAM,EAAE,cAAc,CAAC;CAC/B,SAAS,OAAO;EACd,MAAM,aAAa;EAEnB,aAAa,aAAa,CAAC,CACzB,CAAC,kDAAkD,KAAK,GACxD,EAAE,OAAO,QAAQ,CACnB;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAa,uBACX,eACA,YACS;CACT,MAAM,QAAQ,uBAAuB;CAErC,IAAI,MAAM,cAAc,MAAM,iBAAiB;CAC/C,IAAI,CAAC,cAAc,QAAQ,OAAO;CAClC,IAAI,QAAQ,gBAAgB,GAAG;CAI/B,MAAM,kBAAkB,0BAA0B;CAElD,IAAI,iBAAiB;EACnB,8BAA8B,eAAe;GAC3C,UAAU;GACV,cAAc,QAAQ;EACxB,CAAC;EACD;CACF;CAEA,MAAM,kBAAkB;CAExB,cAAc,eAAe,OAAO,CAAC,CAAC,cAAc;EAClD,MAAM,kBAAkB;CAC1B,CAAC;AACH"}
@@ -2,7 +2,6 @@ import { formatPath } from "./utils/formatter.mjs";
2
2
  import { getFormatFromExtension } from "./utils/getFormatFromExtension.mjs";
3
3
  import { parseContentDeclarationFileName } from "./utils/parseContentDeclarationFileName.mjs";
4
4
  import { prepareIntlayer } from "./prepareIntlayer.mjs";
5
- import { writeContentDeclaration } from "./writeContentDeclaration/writeContentDeclaration.mjs";
6
5
  import { handleContentDeclarationFileChange } from "./handleContentDeclarationFileChange.mjs";
7
6
  import { handleAdditionalContentDeclarationFile } from "./handleAdditionalContentDeclarationFile.mjs";
8
7
  import { handleContentDeclarationFileMoved } from "./handleContentDeclarationFileMoved.mjs";
@@ -171,6 +170,7 @@ const watch = async (options) => {
171
170
  const { key, locale } = parseContentDeclarationFileName(filePath, configuration);
172
171
  const isMarkdown = getFormatFromExtension(extname(filePath)) === "md";
173
172
  const declaredLocale = locale ?? (isMarkdown ? configuration.internationalization.defaultLocale : void 0);
173
+ const { writeContentDeclaration } = await import("./writeContentDeclaration/index.mjs");
174
174
  await writeContentDeclaration({
175
175
  key,
176
176
  ...declaredLocale && { locale: declaredLocale },
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.mjs","names":["fsWatch"],"sources":["../../src/watcher.ts"],"sourcesContent":["import { existsSync, watch as fsWatch } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { basename, dirname, extname, resolve } from 'node:path';\nimport * as ANSIColor from '@intlayer/config/colors';\nimport { transpileTSToCJS } from '@intlayer/config/file';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n getConfigurationAndFilePath,\n} from '@intlayer/config/node';\nimport {\n clearAllCache,\n clearDiskCacheMemory,\n clearModuleCache,\n normalizePath,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { handleAdditionalContentDeclarationFile } from './handleAdditionalContentDeclarationFile';\nimport { handleContentDeclarationFileChange } from './handleContentDeclarationFileChange';\nimport { handleContentDeclarationFileMoved } from './handleContentDeclarationFileMoved';\nimport { handleUnlinkedContentDeclarationFile } from './handleUnlinkedContentDeclarationFile';\nimport { prepareIntlayer } from './prepareIntlayer';\nimport {\n formatPath,\n getFormatFromExtension,\n parseContentDeclarationFileName,\n} from './utils';\nimport { writeContentDeclaration } from './writeContentDeclaration';\n\n// Map to track files that were recently unlinked: oldPath -> { timer, timestamp }\nconst pendingUnlinks = new Map<\n string,\n { timer: NodeJS.Timeout; oldPath: string }\n>();\n\n// Array-based sequential task queue — no Promise chain accumulation, no race conditions\nconst taskQueue: (() => Promise<void>)[] = [];\nlet isProcessing = false;\n\nconst processQueue = async () => {\n if (isProcessing) return;\n isProcessing = true;\n while (taskQueue.length > 0) {\n const task = taskQueue.shift()!;\n try {\n await task();\n } catch (error) {\n console.error(error);\n }\n }\n isProcessing = false;\n};\n\nconst processEvent = (task: () => Promise<void>) => {\n taskQueue.push(task);\n processQueue();\n};\n\ntype WatchOptions = {\n configuration?: IntlayerConfig;\n configOptions?: GetConfigurationOptions;\n skipPrepare?: boolean;\n persistent?: boolean;\n};\n\n// awaitWriteFinish equivalent: debounce per path until the file is stable\nconst STABILITY_THRESHOLD = 1000;\n\nconst createStabilityDebounce = () => {\n const pending = new Map<string, NodeJS.Timeout>();\n return (path: string, handler: () => void) => {\n const existing = pending.get(path);\n if (existing) clearTimeout(existing);\n pending.set(\n path,\n setTimeout(() => {\n pending.delete(path);\n handler();\n }, STABILITY_THRESHOLD)\n );\n };\n};\n\n// Initialize @parcel/watcher (non-persistent until subscribed)\nexport const watch = async (options?: WatchOptions) => {\n const { subscribe } = await import('@parcel/watcher');\n\n const configResult = getConfigurationAndFilePath(options?.configOptions);\n const configurationFilePath = configResult.configurationFilePath;\n let configuration: IntlayerConfig =\n options?.configuration ?? configResult.configuration;\n const appLogger = getAppLogger(configuration);\n\n const {\n watch: isWatchMode,\n fileExtensions,\n contentDir,\n excludedPath,\n } = configuration.content;\n\n if (!configuration.content.watch) return;\n\n appLogger('Watching Intlayer content declarations');\n\n if (configuration.build.optimize === true) {\n appLogger(\n [\n `Build optimization is forced to ${colorize('true', ANSIColor.GREY)}, but watching is enabled too.`,\n 'It may lead to dev mode performance degradation as well as import errors.',\n 'Its recommended to keep the',\n colorize('`build.optimized`', ANSIColor.BLUE),\n 'option',\n colorize('undefined', ANSIColor.GREY),\n 'to get the best dev mode experience',\n ],\n {\n level: 'warn',\n }\n );\n }\n\n // Strip glob markers from excludedPath entries to get plain segments (e.g. 'node_modules')\n const excludedSegments = excludedPath.map((segment) =>\n segment.replace(/^\\*\\*\\//, '').replace(/\\/\\*\\*$/, '')\n );\n\n const normalizedConfigPath = configurationFilePath\n ? normalizePath(configurationFilePath)\n : null;\n\n const { mainDir, baseDir } = configuration.system;\n const normalizedMainDir = normalizePath(mainDir);\n const normalizedIntlayerDir = normalizePath(dirname(mainDir));\n\n const subscriptions: { unsubscribe: () => Promise<void> }[] = [];\n\n const scheduleStable = createStabilityDebounce();\n\n // ── mainDir watcher (depth 0) ──────────────────────────────────────────────\n // Detects broken or missing entry-point files inside .intlayer/main\n if (existsSync(mainDir)) {\n const mainDirSub = await subscribe(normalizedMainDir, (err, events) => {\n if (err || isProcessing) return;\n\n for (const event of events) {\n const eventPath = normalizePath(event.path);\n // depth-0 filter: only files directly inside mainDir\n const rel = eventPath.slice(normalizedMainDir.length + 1);\n if (!rel || rel.includes('/')) continue;\n // Temp files written by the bundler (write-then-rename) are build-internal;\n // their deletion must not trigger a clean rebuild.\n if (rel.endsWith('.tmp')) continue;\n\n if (event.type === 'update') {\n processEvent(async () => {\n try {\n // Validate that the regenerated entry point — and the relative\n // dictionary graph it imports — still resolves, by bundling it\n // in-memory with esbuild (via the shared, freshness-checked\n // transpile cache). This replaces a cache-busting dynamic\n // `import()`, which leaked a permanent record into Node's ESM\n // registry on every rebuild since that registry is never evicted.\n const entryCode = await readFile(event.path, 'utf-8');\n await transpileTSToCJS(entryCode, event.path);\n } catch {\n appLogger(\n `Entry point ${basename(event.path)} failed to load, running clean rebuild...`,\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n }\n });\n } else if (event.type === 'delete') {\n processEvent(async () => {\n appLogger(\n [\n 'Entry point',\n formatPath(basename(event.path)),\n 'was removed, running clean rebuild...',\n ],\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n });\n }\n }\n });\n subscriptions.push(mainDirSub);\n }\n\n // ── baseDir watcher (depth 0) — detect .intlayer directory removal ─────────\n // Native fs.watch is non-recursive and ideal for single-directory depth-0 detection.\n const intlayerDirName = basename(normalizedIntlayerDir);\n const fsDirWatcher = fsWatch(\n baseDir,\n { persistent: isWatchMode },\n (eventType, filename) => {\n if (isProcessing || !filename) return;\n if (filename !== intlayerDirName) return;\n\n const fullPath = normalizePath(resolve(baseDir, filename));\n if (fullPath !== normalizedIntlayerDir) return;\n\n if (eventType === 'rename' && !existsSync(normalizedIntlayerDir)) {\n appLogger([\n formatPath('.intlayer'),\n 'directory removed, running clean rebuild...',\n ]);\n processEvent(() =>\n prepareIntlayer(configuration, { clean: true, forceRun: true })\n );\n }\n }\n );\n subscriptions.push({\n unsubscribe: async () => {\n fsDirWatcher.close();\n },\n });\n\n // ── main content watcher ───────────────────────────────────────────────────\n // Ignore patterns for @parcel/watcher (micromatch globs)\n const ignorePatterns = excludedSegments.map((s) => `**/${s}/**`);\n\n // Strip trailing slashes so directory matching stays exact. A user-supplied\n const contentDirs = contentDir\n .map((dir) => normalizePath(dir).replace(/\\/+$/, ''))\n .filter(existsSync);\n\n // Collect unique directories to subscribe to (dirs only, not file paths)\n const dirsToWatch = new Set<string>(contentDirs);\n if (normalizedConfigPath) {\n dirsToWatch.add(normalizePath(dirname(normalizedConfigPath)));\n }\n\n const contentHandler = (\n err: Error | null,\n events: Array<{ type: string; path: string }>\n ) => {\n if (err) {\n appLogger(`Watcher error: ${err}`, { level: 'error' });\n appLogger('Restarting watcher');\n prepareIntlayer(configuration);\n return;\n }\n\n for (const event of events) {\n const filePath = event.path;\n const path = normalizePath(filePath);\n\n const isConfigFile =\n normalizedConfigPath && path === normalizedConfigPath;\n\n if (!isConfigFile) {\n // Must originate from a watched content directory\n const isInContentDir = contentDirs.some(\n (d) => path.startsWith(`${d}/`) || path === d\n );\n if (!isInContentDir) continue;\n\n if (excludedSegments.some((segment) => path.includes(`/${segment}`)))\n continue;\n\n if (!fileExtensions.some((extension) => path.endsWith(extension)))\n continue;\n }\n\n if (event.type === 'create') {\n const fileName = basename(filePath);\n\n // Move detection must happen synchronously before any debounce\n let isMove = false;\n let matchedOldPath: string | undefined;\n\n for (const [oldPath] of pendingUnlinks) {\n if (basename(oldPath) === fileName) {\n matchedOldPath = oldPath;\n break;\n }\n }\n\n if (!matchedOldPath && pendingUnlinks.size === 1) {\n matchedOldPath = pendingUnlinks.keys().next().value;\n }\n\n if (matchedOldPath) {\n const pending = pendingUnlinks.get(matchedOldPath);\n if (pending) {\n clearTimeout(pending.timer);\n pendingUnlinks.delete(matchedOldPath);\n }\n isMove = true;\n appLogger(`File moved from ${matchedOldPath} to ${filePath}`);\n }\n\n if (isMove && matchedOldPath) {\n processEvent(async () => {\n await handleContentDeclarationFileMoved(\n matchedOldPath!,\n filePath,\n configuration\n );\n });\n } else {\n // Debounce: wait for write to finish before reading the file\n scheduleStable(path, () => {\n processEvent(async () => {\n const fileContent = await readFile(filePath, 'utf-8');\n const isEmpty = fileContent === '';\n\n if (isEmpty) {\n const { key, locale } = parseContentDeclarationFileName(\n filePath,\n configuration\n );\n\n // A markdown declaration carries a single locale body, so it\n // must always state which locale it holds.\n const isMarkdown =\n getFormatFromExtension(extname(filePath)) === 'md';\n const declaredLocale =\n locale ??\n (isMarkdown\n ? configuration.internationalization.defaultLocale\n : undefined);\n\n await writeContentDeclaration(\n {\n key,\n ...(declaredLocale && { locale: declaredLocale }),\n content: {},\n filePath,\n },\n configuration\n );\n }\n\n await handleAdditionalContentDeclarationFile(\n filePath,\n configuration\n );\n });\n });\n }\n } else if (event.type === 'update') {\n scheduleStable(path, () => {\n processEvent(async () => {\n if (isConfigFile) {\n appLogger('Configuration file changed, repreparing Intlayer');\n\n clearModuleCache(filePath);\n clearAllCache();\n\n const { configuration: newConfiguration } =\n getConfigurationAndFilePath(options?.configOptions);\n\n configuration = options?.configuration ?? newConfiguration;\n\n await prepareIntlayer(configuration, { clean: false });\n } else {\n // Clear module cache for the changed file to avoid stale require() results\n clearModuleCache(filePath);\n // Evict in-memory caches so loadContentDeclaration picks up fresh content\n clearAllCache();\n clearDiskCacheMemory();\n await handleContentDeclarationFileChange(filePath, configuration);\n }\n });\n });\n } else if (event.type === 'delete') {\n // Delay unlink processing to see if an 'add' event occurs (indicating a move)\n const timer = setTimeout(async () => {\n // If timer fires, the file was genuinely removed\n pendingUnlinks.delete(filePath);\n processEvent(async () =>\n handleUnlinkedContentDeclarationFile(filePath, configuration)\n );\n }, 200); // 200ms window to catch the 'create' event\n\n pendingUnlinks.set(filePath, { timer, oldPath: filePath });\n }\n }\n };\n\n for (const dir of dirsToWatch) {\n const sub = await subscribe(dir, contentHandler, {\n ignore: ignorePatterns,\n });\n\n subscriptions.push(sub);\n }\n\n return subscriptions;\n};\n\nexport const buildAndWatchIntlayer = async (options?: WatchOptions) => {\n const { skipPrepare, ...rest } = options ?? {};\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n\n if (!skipPrepare) {\n await prepareIntlayer(configuration, { forceRun: true });\n }\n\n // Only enter watch mode when the caller explicitly opts in via `persistent`.\n // `configuration.content.watch` is the dev-mode signal consumed by bundler\n // plugins (e.g. vite-intlayer's `configureServer`); it must not coerce\n // `intlayer build` (which passes `persistent: false`) into a persistent\n // watcher, since that prevents the build command from ever exiting.\n if (options?.persistent) {\n await watch({ ...rest, configuration });\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"watcher.mjs","names":["fsWatch"],"sources":["../../src/watcher.ts"],"sourcesContent":["import { existsSync, watch as fsWatch } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { basename, dirname, extname, resolve } from 'node:path';\nimport * as ANSIColor from '@intlayer/config/colors';\nimport { transpileTSToCJS } from '@intlayer/config/file';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n getConfigurationAndFilePath,\n} from '@intlayer/config/node';\nimport {\n clearAllCache,\n clearDiskCacheMemory,\n clearModuleCache,\n normalizePath,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { handleAdditionalContentDeclarationFile } from './handleAdditionalContentDeclarationFile';\nimport { handleContentDeclarationFileChange } from './handleContentDeclarationFileChange';\nimport { handleContentDeclarationFileMoved } from './handleContentDeclarationFileMoved';\nimport { handleUnlinkedContentDeclarationFile } from './handleUnlinkedContentDeclarationFile';\nimport { prepareIntlayer } from './prepareIntlayer';\nimport {\n formatPath,\n getFormatFromExtension,\n parseContentDeclarationFileName,\n} from './utils';\n\n// Map to track files that were recently unlinked: oldPath -> { timer, timestamp }\nconst pendingUnlinks = new Map<\n string,\n { timer: NodeJS.Timeout; oldPath: string }\n>();\n\n// Array-based sequential task queue — no Promise chain accumulation, no race conditions\nconst taskQueue: (() => Promise<void>)[] = [];\nlet isProcessing = false;\n\nconst processQueue = async () => {\n if (isProcessing) return;\n isProcessing = true;\n while (taskQueue.length > 0) {\n const task = taskQueue.shift()!;\n try {\n await task();\n } catch (error) {\n console.error(error);\n }\n }\n isProcessing = false;\n};\n\nconst processEvent = (task: () => Promise<void>) => {\n taskQueue.push(task);\n processQueue();\n};\n\ntype WatchOptions = {\n configuration?: IntlayerConfig;\n configOptions?: GetConfigurationOptions;\n skipPrepare?: boolean;\n persistent?: boolean;\n};\n\n// awaitWriteFinish equivalent: debounce per path until the file is stable\nconst STABILITY_THRESHOLD = 1000;\n\nconst createStabilityDebounce = () => {\n const pending = new Map<string, NodeJS.Timeout>();\n return (path: string, handler: () => void) => {\n const existing = pending.get(path);\n if (existing) clearTimeout(existing);\n pending.set(\n path,\n setTimeout(() => {\n pending.delete(path);\n handler();\n }, STABILITY_THRESHOLD)\n );\n };\n};\n\n// Initialize @parcel/watcher (non-persistent until subscribed)\nexport const watch = async (options?: WatchOptions) => {\n const { subscribe } = await import('@parcel/watcher');\n\n const configResult = getConfigurationAndFilePath(options?.configOptions);\n const configurationFilePath = configResult.configurationFilePath;\n let configuration: IntlayerConfig =\n options?.configuration ?? configResult.configuration;\n const appLogger = getAppLogger(configuration);\n\n const {\n watch: isWatchMode,\n fileExtensions,\n contentDir,\n excludedPath,\n } = configuration.content;\n\n if (!configuration.content.watch) return;\n\n appLogger('Watching Intlayer content declarations');\n\n if (configuration.build.optimize === true) {\n appLogger(\n [\n `Build optimization is forced to ${colorize('true', ANSIColor.GREY)}, but watching is enabled too.`,\n 'It may lead to dev mode performance degradation as well as import errors.',\n 'Its recommended to keep the',\n colorize('`build.optimized`', ANSIColor.BLUE),\n 'option',\n colorize('undefined', ANSIColor.GREY),\n 'to get the best dev mode experience',\n ],\n {\n level: 'warn',\n }\n );\n }\n\n // Strip glob markers from excludedPath entries to get plain segments (e.g. 'node_modules')\n const excludedSegments = excludedPath.map((segment) =>\n segment.replace(/^\\*\\*\\//, '').replace(/\\/\\*\\*$/, '')\n );\n\n const normalizedConfigPath = configurationFilePath\n ? normalizePath(configurationFilePath)\n : null;\n\n const { mainDir, baseDir } = configuration.system;\n const normalizedMainDir = normalizePath(mainDir);\n const normalizedIntlayerDir = normalizePath(dirname(mainDir));\n\n const subscriptions: { unsubscribe: () => Promise<void> }[] = [];\n\n const scheduleStable = createStabilityDebounce();\n\n // ── mainDir watcher (depth 0) ──────────────────────────────────────────────\n // Detects broken or missing entry-point files inside .intlayer/main\n if (existsSync(mainDir)) {\n const mainDirSub = await subscribe(normalizedMainDir, (err, events) => {\n if (err || isProcessing) return;\n\n for (const event of events) {\n const eventPath = normalizePath(event.path);\n // depth-0 filter: only files directly inside mainDir\n const rel = eventPath.slice(normalizedMainDir.length + 1);\n if (!rel || rel.includes('/')) continue;\n // Temp files written by the bundler (write-then-rename) are build-internal;\n // their deletion must not trigger a clean rebuild.\n if (rel.endsWith('.tmp')) continue;\n\n if (event.type === 'update') {\n processEvent(async () => {\n try {\n // Validate that the regenerated entry point — and the relative\n // dictionary graph it imports — still resolves, by bundling it\n // in-memory with esbuild (via the shared, freshness-checked\n // transpile cache). This replaces a cache-busting dynamic\n // `import()`, which leaked a permanent record into Node's ESM\n // registry on every rebuild since that registry is never evicted.\n const entryCode = await readFile(event.path, 'utf-8');\n await transpileTSToCJS(entryCode, event.path);\n } catch {\n appLogger(\n `Entry point ${basename(event.path)} failed to load, running clean rebuild...`,\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n }\n });\n } else if (event.type === 'delete') {\n processEvent(async () => {\n appLogger(\n [\n 'Entry point',\n formatPath(basename(event.path)),\n 'was removed, running clean rebuild...',\n ],\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n });\n }\n }\n });\n subscriptions.push(mainDirSub);\n }\n\n // ── baseDir watcher (depth 0) — detect .intlayer directory removal ─────────\n // Native fs.watch is non-recursive and ideal for single-directory depth-0 detection.\n const intlayerDirName = basename(normalizedIntlayerDir);\n const fsDirWatcher = fsWatch(\n baseDir,\n { persistent: isWatchMode },\n (eventType, filename) => {\n if (isProcessing || !filename) return;\n if (filename !== intlayerDirName) return;\n\n const fullPath = normalizePath(resolve(baseDir, filename));\n if (fullPath !== normalizedIntlayerDir) return;\n\n if (eventType === 'rename' && !existsSync(normalizedIntlayerDir)) {\n appLogger([\n formatPath('.intlayer'),\n 'directory removed, running clean rebuild...',\n ]);\n processEvent(() =>\n prepareIntlayer(configuration, { clean: true, forceRun: true })\n );\n }\n }\n );\n subscriptions.push({\n unsubscribe: async () => {\n fsDirWatcher.close();\n },\n });\n\n // ── main content watcher ───────────────────────────────────────────────────\n // Ignore patterns for @parcel/watcher (micromatch globs)\n const ignorePatterns = excludedSegments.map((s) => `**/${s}/**`);\n\n // Strip trailing slashes so directory matching stays exact. A user-supplied\n const contentDirs = contentDir\n .map((dir) => normalizePath(dir).replace(/\\/+$/, ''))\n .filter(existsSync);\n\n // Collect unique directories to subscribe to (dirs only, not file paths)\n const dirsToWatch = new Set<string>(contentDirs);\n if (normalizedConfigPath) {\n dirsToWatch.add(normalizePath(dirname(normalizedConfigPath)));\n }\n\n const contentHandler = (\n err: Error | null,\n events: Array<{ type: string; path: string }>\n ) => {\n if (err) {\n appLogger(`Watcher error: ${err}`, { level: 'error' });\n appLogger('Restarting watcher');\n prepareIntlayer(configuration);\n return;\n }\n\n for (const event of events) {\n const filePath = event.path;\n const path = normalizePath(filePath);\n\n const isConfigFile =\n normalizedConfigPath && path === normalizedConfigPath;\n\n if (!isConfigFile) {\n // Must originate from a watched content directory\n const isInContentDir = contentDirs.some(\n (d) => path.startsWith(`${d}/`) || path === d\n );\n if (!isInContentDir) continue;\n\n if (excludedSegments.some((segment) => path.includes(`/${segment}`)))\n continue;\n\n if (!fileExtensions.some((extension) => path.endsWith(extension)))\n continue;\n }\n\n if (event.type === 'create') {\n const fileName = basename(filePath);\n\n // Move detection must happen synchronously before any debounce\n let isMove = false;\n let matchedOldPath: string | undefined;\n\n for (const [oldPath] of pendingUnlinks) {\n if (basename(oldPath) === fileName) {\n matchedOldPath = oldPath;\n break;\n }\n }\n\n if (!matchedOldPath && pendingUnlinks.size === 1) {\n matchedOldPath = pendingUnlinks.keys().next().value;\n }\n\n if (matchedOldPath) {\n const pending = pendingUnlinks.get(matchedOldPath);\n if (pending) {\n clearTimeout(pending.timer);\n pendingUnlinks.delete(matchedOldPath);\n }\n isMove = true;\n appLogger(`File moved from ${matchedOldPath} to ${filePath}`);\n }\n\n if (isMove && matchedOldPath) {\n processEvent(async () => {\n await handleContentDeclarationFileMoved(\n matchedOldPath!,\n filePath,\n configuration\n );\n });\n } else {\n // Debounce: wait for write to finish before reading the file\n scheduleStable(path, () => {\n processEvent(async () => {\n const fileContent = await readFile(filePath, 'utf-8');\n const isEmpty = fileContent === '';\n\n if (isEmpty) {\n const { key, locale } = parseContentDeclarationFileName(\n filePath,\n configuration\n );\n\n // A markdown declaration carries a single locale body, so it\n // must always state which locale it holds.\n const isMarkdown =\n getFormatFromExtension(extname(filePath)) === 'md';\n const declaredLocale =\n locale ??\n (isMarkdown\n ? configuration.internationalization.defaultLocale\n : undefined);\n\n // Lazy: pulls recast/ast-types, only needed for new empty files\n const { writeContentDeclaration } = await import(\n './writeContentDeclaration'\n );\n\n await writeContentDeclaration(\n {\n key,\n ...(declaredLocale && { locale: declaredLocale }),\n content: {},\n filePath,\n },\n configuration\n );\n }\n\n await handleAdditionalContentDeclarationFile(\n filePath,\n configuration\n );\n });\n });\n }\n } else if (event.type === 'update') {\n scheduleStable(path, () => {\n processEvent(async () => {\n if (isConfigFile) {\n appLogger('Configuration file changed, repreparing Intlayer');\n\n clearModuleCache(filePath);\n clearAllCache();\n\n const { configuration: newConfiguration } =\n getConfigurationAndFilePath(options?.configOptions);\n\n configuration = options?.configuration ?? newConfiguration;\n\n await prepareIntlayer(configuration, { clean: false });\n } else {\n // Clear module cache for the changed file to avoid stale require() results\n clearModuleCache(filePath);\n // Evict in-memory caches so loadContentDeclaration picks up fresh content\n clearAllCache();\n clearDiskCacheMemory();\n await handleContentDeclarationFileChange(filePath, configuration);\n }\n });\n });\n } else if (event.type === 'delete') {\n // Delay unlink processing to see if an 'add' event occurs (indicating a move)\n const timer = setTimeout(async () => {\n // If timer fires, the file was genuinely removed\n pendingUnlinks.delete(filePath);\n processEvent(async () =>\n handleUnlinkedContentDeclarationFile(filePath, configuration)\n );\n }, 200); // 200ms window to catch the 'create' event\n\n pendingUnlinks.set(filePath, { timer, oldPath: filePath });\n }\n }\n };\n\n for (const dir of dirsToWatch) {\n const sub = await subscribe(dir, contentHandler, {\n ignore: ignorePatterns,\n });\n\n subscriptions.push(sub);\n }\n\n return subscriptions;\n};\n\nexport const buildAndWatchIntlayer = async (options?: WatchOptions) => {\n const { skipPrepare, ...rest } = options ?? {};\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n\n if (!skipPrepare) {\n await prepareIntlayer(configuration, { forceRun: true });\n }\n\n // Only enter watch mode when the caller explicitly opts in via `persistent`.\n // `configuration.content.watch` is the dev-mode signal consumed by bundler\n // plugins (e.g. vite-intlayer's `configureServer`); it must not coerce\n // `intlayer build` (which passes `persistent: false`) into a persistent\n // watcher, since that prevents the build command from ever exiting.\n if (options?.persistent) {\n await watch({ ...rest, configuration });\n }\n};\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { writeFileIfChanged } from "./writeFileIfChanged.mjs";
2
2
 
3
3
  //#region src/writeJsonIfChanged.ts
4
- const writeJsonIfChanged = async (path, data, { pretty = true } = {}) => {
4
+ const writeJsonIfChanged = async (path, data, { pretty = process.env.NODE_ENV === "development" } = {}) => {
5
5
  const space = pretty ? 2 : void 0;
6
6
  let json = "{}";
7
7
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"writeJsonIfChanged.mjs","names":[],"sources":["../../src/writeJsonIfChanged.ts"],"sourcesContent":["import { writeFileIfChanged } from './writeFileIfChanged';\n\nexport const writeJsonIfChanged = async <T>(\n path: string,\n data: T,\n { pretty = process.env.NODE_ENV === 'development' } = {}\n): Promise<boolean> => {\n const space = pretty ? 2 : undefined;\n\n let json = '{}';\n\n try {\n json = JSON.stringify(data, null, space);\n } catch (error) {\n console.error(`Error while parsing data to JSON for ${path}:`, error);\n }\n\n return await writeFileIfChanged(path, json);\n};\n"],"mappings":";;;AAEA,MAAa,qBAAqB,OAChC,MACA,MACA,EAAE,SAAS,SAA2C,CAAC,MAClC;CACrB,MAAM,QAAQ,SAAS,IAAI;CAE3B,IAAI,OAAO;CAEX,IAAI;EACF,OAAO,KAAK,UAAU,MAAM,MAAM,KAAK;CACzC,SAAS,OAAO;EACd,QAAQ,MAAM,wCAAwC,KAAK,IAAI,KAAK;CACtE;CAEA,OAAO,MAAM,mBAAmB,MAAM,IAAI;AAC5C"}
1
+ {"version":3,"file":"writeJsonIfChanged.mjs","names":[],"sources":["../../src/writeJsonIfChanged.ts"],"sourcesContent":["import { writeFileIfChanged } from './writeFileIfChanged';\n\nexport const writeJsonIfChanged = async <T>(\n path: string,\n data: T,\n { pretty = process.env.NODE_ENV === 'development' } = {}\n): Promise<boolean> => {\n const space = pretty ? 2 : undefined;\n\n let json = '{}';\n\n try {\n json = JSON.stringify(data, null, space);\n } catch (error) {\n console.error(`Error while parsing data to JSON for ${path}:`, error);\n }\n\n return await writeFileIfChanged(path, json);\n};\n"],"mappings":";;;AAEA,MAAa,qBAAqB,OAChC,MACA,MACA,EAAE,kCAAkC,kBAAkB,CAAC,MAClC;CACrB,MAAM,QAAQ,SAAS,IAAI;CAE3B,IAAI,OAAO;CAEX,IAAI;EACF,OAAO,KAAK,UAAU,MAAM,MAAM,KAAK;CACzC,SAAS,OAAO;EACd,QAAQ,MAAM,wCAAwC,KAAK,IAAI,KAAK;CACtE;CAEA,OAAO,MAAM,mBAAmB,MAAM,IAAI;AAC5C"}
@@ -20,6 +20,7 @@ import { loadLocalDictionaries } from "./loadDictionaries/loadLocalDictionaries.
20
20
  import { formatDistantDictionaries, loadRemoteDictionaries } from "./loadDictionaries/loadRemoteDictionaries.js";
21
21
  import "./loadDictionaries/index.js";
22
22
  import { prepareIntlayer } from "./prepareIntlayer.js";
23
+ import { INTLAYER_WATCH_ENV_VAR, PrepareIntlayerServerOptions, getIsDevWatcherCommand, getIsServerDevelopment, prepareIntlayerServer } from "./prepareIntlayerServer.js";
23
24
  import { readDictionariesFromDisk } from "./utils/readDictionariesFromDisk.js";
24
25
  import { isCachedConfigurationUpToDate, writeConfiguration } from "./writeConfiguration/index.js";
25
26
  import { detectExportedComponentName } from "./writeContentDeclaration/detectExportedComponentName.js";
@@ -28,4 +29,4 @@ import { transformJSFile } from "./writeContentDeclaration/transformJSFile.js";
28
29
  import { writeContentDeclaration } from "./writeContentDeclaration/writeContentDeclaration.js";
29
30
  import { writeJSFile } from "./writeContentDeclaration/writeJSFile.js";
30
31
  import "./writeContentDeclaration/index.js";
31
- export { BuildDictionariesOptions, CreateDictionaryEntryPointOptions, DictionariesStatus, DictionaryStatus, buildDictionary, cleanOutputDir, createDictionaryEntryPoint, createModuleAugmentation, createTypes, detectExportedComponentName, ensureIntlayerBundle, formatDictionaries, formatDictionariesOutput, formatDictionary, formatDictionaryOutput, formatDistantDictionaries, formatDomains, formatLocalDictionaries, formatRewriteRules, generateDictionaryListContent, generateTypeScriptType, getBuiltDictionariesPath, getBuiltDynamicDictionariesPath, getBuiltFetchDictionariesPath, getBuiltRemoteDictionariesPath, getBuiltUnmergedDictionariesPath, getTypeName, isCachedConfigurationUpToDate, loadContentDeclaration, loadContentDeclarations, loadDictionaries, loadLocalDictionaries, loadRemoteDictionaries, prepareIntlayer, processContentDeclaration, readDictionariesFromDisk, transformJSFile, writeConfiguration, writeContentDeclaration, writeJSFile };
32
+ export { BuildDictionariesOptions, CreateDictionaryEntryPointOptions, DictionariesStatus, DictionaryStatus, INTLAYER_WATCH_ENV_VAR, PrepareIntlayerServerOptions, buildDictionary, cleanOutputDir, createDictionaryEntryPoint, createModuleAugmentation, createTypes, detectExportedComponentName, ensureIntlayerBundle, formatDictionaries, formatDictionariesOutput, formatDictionary, formatDictionaryOutput, formatDistantDictionaries, formatDomains, formatLocalDictionaries, formatRewriteRules, generateDictionaryListContent, generateTypeScriptType, getBuiltDictionariesPath, getBuiltDynamicDictionariesPath, getBuiltFetchDictionariesPath, getBuiltRemoteDictionariesPath, getBuiltUnmergedDictionariesPath, getIsDevWatcherCommand, getIsServerDevelopment, getTypeName, isCachedConfigurationUpToDate, loadContentDeclaration, loadContentDeclarations, loadDictionaries, loadLocalDictionaries, loadRemoteDictionaries, prepareIntlayer, prepareIntlayerServer, processContentDeclaration, readDictionariesFromDisk, transformJSFile, writeConfiguration, writeContentDeclaration, writeJSFile };
@@ -7,7 +7,7 @@ import { writeJSFile } from "./writeContentDeclaration/writeJSFile.js";
7
7
  import "./writeContentDeclaration/index.js";
8
8
  import { detectFormatCommand } from "./detectFormatCommand.js";
9
9
  import { getContentDeclarationFileTemplate } from "./getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.js";
10
- import { COMPAT_I18N_LIBRARIES, CompatI18nLibrary, PackageManager, detectCompatI18nLibraries, detectPackageManager, hasLintTooling, installPackages } from "./init/utils/packageManager.js";
10
+ import { COMPAT_I18N_LIBRARIES, CompatI18nLibrary, PackageManager, detectCompatI18nLibraries, detectPackageManager, findLockFileDir, hasLintTooling, installPackages } from "./init/utils/packageManager.js";
11
11
  import { RoutingMode } from "./init/utils/configManipulation.js";
12
12
  import { CmsCredentials, enableEditorInConfig, setupCmsCredentials, writeCmsCredentialsToEnv } from "./init/cms.js";
13
13
  import { DocumentationRouter, DocumentationRouterType, getDocumentationUrl } from "./init/documentationRouter.js";
@@ -17,10 +17,10 @@ import "./init/utils/index.js";
17
17
  import { ContentStrategy, InitOptions, getDefaultApplicationURL, initIntlayer, logInitSuccessMessage } from "./init/index.js";
18
18
  import { UpgradeIntlayerPackagesOptions, UpgradeIntlayerPackagesResult, upgradeIntlayerPackages } from "./init/upgradeIntlayerPackages.js";
19
19
  import { installLSP } from "./installLSP.js";
20
- import { PLATFORMS, PLATFORMS_METADATA, Platform, PlatformMetadata, SKILLS, SKILLS_METADATA, Skill, getInitialSkills, installSkills } from "./installSkills/index.js";
21
- import { MCPTransport, installMCP } from "./installMCP/installMCP.js";
20
+ import { PLATFORMS, PLATFORMS_METADATA, Platform, PlatformMetadata, SKILLS, SKILLS_METADATA, Skill, detectPlatform, getInitialSkills, installSkills } from "./installSkills/index.js";
21
+ import { MCPTransport, MCP_TRANSPORTS, installMCP } from "./installMCP/installMCP.js";
22
22
  import { listDictionaries, listDictionariesWithStats } from "./listDictionariesPath.js";
23
23
  import { DiffMode, ListGitFilesOptions, ListGitLinesOptions, listGitFiles, listGitLines } from "./listGitFiles.js";
24
24
  import { ListProjectsOptions, getGitRootDir, listProjects } from "./listProjects.js";
25
25
  import { logConfigDetails } from "./logConfigDetails.js";
26
- export { COMPAT_I18N_LIBRARIES, type CmsCredentials, type CompatI18nLibrary, ContentStrategy, DictionaryStatus, DiffMode, DocumentationRouter, type DocumentationRouterType, InitOptions, ListGitFilesOptions, ListGitLinesOptions, ListProjectsOptions, MCPTransport, NEXT_INTLAYER_BABEL_CONFIG_CONTENT, PLATFORMS, PLATFORMS_METADATA, type PackageManager, Platform, PlatformMetadata, type RoutingMode, SKILLS, SKILLS_METADATA, Skill, UpgradeIntlayerPackagesOptions, UpgradeIntlayerPackagesResult, detectCompatI18nLibraries, detectExportedComponentName, detectFormatCommand, detectPackageManager, enableEditorInConfig, getContentDeclarationFileTemplate, getDefaultApplicationURL, getDocumentationUrl, getGitRootDir, getInitialSkills, hasLintTooling, hasUrlRoutingFramework, initIntlayer, installLSP, installMCP, installPackages, installSkills, listDictionaries, listDictionariesWithStats, listGitFiles, listGitLines, listProjects, logConfigDetails, logInitSuccessMessage, prepareIntlayer, setupCmsCredentials, transformJSFile, upgradeIntlayerPackages, writeCmsCredentialsToEnv, writeContentDeclaration, writeJSFile };
26
+ export { COMPAT_I18N_LIBRARIES, type CmsCredentials, type CompatI18nLibrary, ContentStrategy, DictionaryStatus, DiffMode, DocumentationRouter, type DocumentationRouterType, InitOptions, ListGitFilesOptions, ListGitLinesOptions, ListProjectsOptions, MCPTransport, MCP_TRANSPORTS, NEXT_INTLAYER_BABEL_CONFIG_CONTENT, PLATFORMS, PLATFORMS_METADATA, type PackageManager, Platform, PlatformMetadata, type RoutingMode, SKILLS, SKILLS_METADATA, Skill, UpgradeIntlayerPackagesOptions, UpgradeIntlayerPackagesResult, detectCompatI18nLibraries, detectExportedComponentName, detectFormatCommand, detectPackageManager, detectPlatform, enableEditorInConfig, findLockFileDir, getContentDeclarationFileTemplate, getDefaultApplicationURL, getDocumentationUrl, getGitRootDir, getInitialSkills, hasLintTooling, hasUrlRoutingFramework, initIntlayer, installLSP, installMCP, installPackages, installSkills, listDictionaries, listDictionariesWithStats, listGitFiles, listGitLines, listProjects, logConfigDetails, logInitSuccessMessage, prepareIntlayer, setupCmsCredentials, transformJSFile, upgradeIntlayerPackages, writeCmsCredentialsToEnv, writeContentDeclaration, writeJSFile };
@@ -39,7 +39,7 @@ export type InitOptions = {
39
39
  noEslint?: boolean;
40
40
  /**
41
41
  * Skip the project setup: tsconfig types/aliases, the Intlayer config file,
42
- * bundler/framework configs, the dev script and framework-specific
42
+ * bundler/framework configs and framework-specific
43
43
  * scaffolding (middleware/proxy, providers in layout/page). Defaults to
44
44
  * enabled.
45
45
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/init/index.ts"],"mappings":";;;;;;;;;;qBA6Ea,2BAAwB,cACrB;;;;;;;;;;YAsBJ;;;;YAQA;EACV;;EAEA;;;;;EAKA;;EAEA;;EAEA;;EAEA;;;;;;;EAOA;;EAEA;;;;;;EAMA;;;;;;EAMA,cAAc;;;;;;;EAOd;;;;;;;EAOA,kBAAkB;;;;;qBAMP,eAAY,iBAAyB,UAAY,gBAAW;;;qBA6kC5D,wBAAqB"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/init/index.ts"],"mappings":";;;;;;;;;;qBA4Ea,2BAAwB,cACrB;;;;;;;;;;YAsBJ;;;;YAQA;EACV;;EAEA;;;;;EAKA;;EAEA;;EAEA;;EAEA;;;;;;;EAOA;;EAEA;;;;;;EAMA;;;;;;EAMA,cAAc;;;;;;;EAOd;;;;;;;EAOA,kBAAkB;;;;;qBAMP,eAAY,iBAAyB,UAAY,gBAAW;;;qBA6kC5D,wBAAqB"}
@@ -0,0 +1,5 @@
1
+ //#region src/init/utils/backendPackages.d.ts
2
+ /** Intlayer integrations for server frameworks (no bundler plugin). */
3
+ export declare const BACKEND_INTLAYER_PACKAGES: string[];
4
+ //#endregion
5
+ //# sourceMappingURL=backendPackages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backendPackages.d.ts","names":[],"sources":["../../../../src/init/utils/backendPackages.ts"],"mappings":";;qBACa"}
@@ -1,7 +1,7 @@
1
1
  import { COMPAT_I18N_LIBRARIES, COMPAT_PACKAGE_REPLACEMENTS, CompatI18nLibrary, CompatSyncConfig, CompatVitePluginConfig, DetectMissingPackagesOptions, IntlayerPackageAnalysis, MINIMUM_ESLINT_MAJOR, PENDING_COMPAT_ADAPTERS, PackageManager, detectCompatI18nLibraries, detectMissingIntlayerPackages, detectPackageManager, findLockFileDir, hasLegacyEslint, hasLintTooling, installPackages, isIntlayerPackageName, moveCompatPackagesToDevDependencies, normalizeVersion, runPackageInstall } from "./packageManager.js";
2
2
  import { RoutingMode, enableIntlayerEditorConfig, getMetroConfigTemplate, hasIntlayerVitePlugin, replaceViteConfigPluginImportSource, setIntlayerConfigCompilerOutput, setIntlayerConfigEnableProxy, setIntlayerConfigRoutingMode, setIntlayerConfigRoutingStorageOnly, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin, updateViteConfigForVueI18n } from "./configManipulation.js";
3
3
  import { ensureNamedImport, firstInsertIndex, isModuleScopeBinding } from "./astImports.js";
4
- import { BACKEND_INTLAYER_PACKAGES, ResolveDevScriptParams, resolveDevScript } from "./devScript.js";
4
+ import { BACKEND_INTLAYER_PACKAGES } from "./backendPackages.js";
5
5
  import { JsonLocalePattern, JsonLocalePatternType, LinguiCatalogPattern, NextIntlMessagesPattern, detectJsonLocalePattern, detectLinguiCatalogPattern, detectNextIntlMessagesPattern, ensureDirectory, exists, readFileFromRoot, writeFileToRoot } from "./fileSystem.js";
6
6
  import { GITHUB_FILL_WORKFLOW_PATH, GITHUB_TEST_WORKFLOW_PATH, GithubWorkflowFile, GithubWorkflowsContext, GithubWorkflowsOptions, getGithubWorkflows, resolveGithubWorkflowsContext } from "./githubActions.js";
7
7
  import { IntlayerDependency, IntlayerDependencyUpgrade, PackageJsonIntlayerDependencies, fetchLatestPackageVersion, findPackageJsonFiles, getIntlayerDependencies, getIntlayerDependencyUpgrades, listIntlayerDependencies, toRange, writeIntlayerDependencyUpgrades } from "./intlayerDependencies.js";
@@ -11,4 +11,4 @@ import { NEXT_INTLAYER_BABEL_CONFIG_CONTENT, setupNextCompilerBabelConfig } from
11
11
  import { findTsConfigFiles } from "./tsConfig.js";
12
12
  import { hasUrlRoutingFramework } from "./urlRoutingFramework.js";
13
13
  import { isVersionAtLeast } from "./version.js";
14
- export { BACKEND_INTLAYER_PACKAGES, COMPAT_I18N_LIBRARIES, COMPAT_PACKAGE_REPLACEMENTS, CompatI18nLibrary, CompatSyncConfig, CompatVitePluginConfig, DetectMissingPackagesOptions, GITHUB_FILL_WORKFLOW_PATH, GITHUB_TEST_WORKFLOW_PATH, GithubWorkflowFile, GithubWorkflowsContext, GithubWorkflowsOptions, IntlayerDependency, IntlayerDependencyUpgrade, IntlayerPackageAnalysis, JsonLocalePattern, JsonLocalePatternType, LINT_PLUGIN_PACKAGE_NAME, LinguiCatalogPattern, MINIMUM_ESLINT_MAJOR, NEXT_INTLAYER_BABEL_CONFIG_CONTENT, NextIntlMessagesPattern, OxlintConfig, PENDING_COMPAT_ADAPTERS, PackageJsonIntlayerDependencies, PackageManager, ResolveDevScriptParams, RoutingMode, addIntlayerRulesToOxlintConfig, detectCompatI18nLibraries, detectJsonLocalePattern, detectLinguiCatalogPattern, detectMissingIntlayerPackages, detectNextIntlMessagesPattern, detectPackageManager, enableIntlayerEditorConfig, ensureDirectory, ensureNamedImport, exists, fetchLatestPackageVersion, findLockFileDir, findPackageJsonFiles, findTsConfigFiles, firstInsertIndex, getGithubWorkflows, getIntlayerDependencies, getIntlayerDependencyUpgrades, getMetroConfigTemplate, hasIntlayerVitePlugin, hasLegacyEslint, hasLintTooling, hasUrlRoutingFramework, installPackages, isIntlayerPackageName, isModuleScopeBinding, isVersionAtLeast, listIntlayerDependencies, moveCompatPackagesToDevDependencies, normalizeVersion, parseJSONWithComments, readFileFromRoot, replaceViteConfigPluginImportSource, resolveDevScript, resolveGithubWorkflowsContext, runPackageInstall, setIntlayerConfigCompilerOutput, setIntlayerConfigEnableProxy, setIntlayerConfigRoutingMode, setIntlayerConfigRoutingStorageOnly, setupNextCompilerBabelConfig, toRange, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin, updateViteConfigForVueI18n, writeFileToRoot, writeIntlayerDependencyUpgrades };
14
+ export { BACKEND_INTLAYER_PACKAGES, COMPAT_I18N_LIBRARIES, COMPAT_PACKAGE_REPLACEMENTS, CompatI18nLibrary, CompatSyncConfig, CompatVitePluginConfig, DetectMissingPackagesOptions, GITHUB_FILL_WORKFLOW_PATH, GITHUB_TEST_WORKFLOW_PATH, GithubWorkflowFile, GithubWorkflowsContext, GithubWorkflowsOptions, IntlayerDependency, IntlayerDependencyUpgrade, IntlayerPackageAnalysis, JsonLocalePattern, JsonLocalePatternType, LINT_PLUGIN_PACKAGE_NAME, LinguiCatalogPattern, MINIMUM_ESLINT_MAJOR, NEXT_INTLAYER_BABEL_CONFIG_CONTENT, NextIntlMessagesPattern, OxlintConfig, PENDING_COMPAT_ADAPTERS, PackageJsonIntlayerDependencies, PackageManager, RoutingMode, addIntlayerRulesToOxlintConfig, detectCompatI18nLibraries, detectJsonLocalePattern, detectLinguiCatalogPattern, detectMissingIntlayerPackages, detectNextIntlMessagesPattern, detectPackageManager, enableIntlayerEditorConfig, ensureDirectory, ensureNamedImport, exists, fetchLatestPackageVersion, findLockFileDir, findPackageJsonFiles, findTsConfigFiles, firstInsertIndex, getGithubWorkflows, getIntlayerDependencies, getIntlayerDependencyUpgrades, getMetroConfigTemplate, hasIntlayerVitePlugin, hasLegacyEslint, hasLintTooling, hasUrlRoutingFramework, installPackages, isIntlayerPackageName, isModuleScopeBinding, isVersionAtLeast, listIntlayerDependencies, moveCompatPackagesToDevDependencies, normalizeVersion, parseJSONWithComments, readFileFromRoot, replaceViteConfigPluginImportSource, resolveGithubWorkflowsContext, runPackageInstall, setIntlayerConfigCompilerOutput, setIntlayerConfigEnableProxy, setIntlayerConfigRoutingMode, setIntlayerConfigRoutingStorageOnly, setupNextCompilerBabelConfig, toRange, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin, updateViteConfigForVueI18n, writeFileToRoot, writeIntlayerDependencyUpgrades };
@@ -132,6 +132,11 @@ export type DetectMissingPackagesOptions = {
132
132
  * The project's development dependencies (from `package.json` `devDependencies`).
133
133
  */
134
134
  devDependencies?: Record<string, string>;
135
+ /**
136
+ * Skip `eslint-plugin-intlayer`, even when the project lints. Set when the
137
+ * lint step is not part of the setup.
138
+ */
139
+ skipLintPlugin?: boolean;
135
140
  };
136
141
  /** An existing i18n library Intlayer ships a compat adapter for. */
137
142
  export type CompatI18nLibrary = {
@@ -1 +1 @@
1
- {"version":3,"file":"packageManager.d.ts","names":[],"sources":["../../../../src/init/utils/packageManager.ts"],"mappings":";;YAMY;;;;;YAMA;;;;;;;EAOV;;;;;EAKA;;;;;EAKA;;;;;;;;;;;;;;;EAeA;;;;;;;YAQU;;EAEV;;EAEA;;;;;;;;EAQA;;IAEE;;IAEA;;;;YAKQ;;EAEV;;EAEA;;EAEA;;;;;;EAMA,kBAAkB;;;;;;EAMlB,wBAAwB;;;;;;EAMxB;;;;;;;;qBASW,yBAAyB;;;;;;qBAiDzB,uBAAoB,oBAAsB;;;;;;qBAY1C,kBAAe;;;;;;;YA2ChB;;;;;;EAMV;;;;;;EAMA,eAAe;;;;EAIf,kBAAkB;;;YAIR;;EAEV;;;;;;EAMA;;;;;EAKA,cAAc;;;;;;;;qBASH,gCAAgC;;;;;qBA+GhC,6BAA6B;;;;;;;;qBAc7B,sCAAmC,aACjC;;;;;;;;;;qBA8BF,4BAAyB,cACtB;;qBAOH;;;;;;;;;qBAUA,kBAAe,cACZ;;;;;;;;;;;qBAiBH,iBAAc,cAAkB;qBAIhC,gCAA6B,iBACvB,wBAAsB,UAC9B,iCACR;;;;;qBAyZU,kBAAe,iBACX,oBACG,gBACF,gBAAc;;;;;;;;;;qBAgBnB,wBAAqB;;;;;;;;qBAarB,mBAAgB;;;;;;qBAahB,oBAAiB,iBACb,gBACC"}
1
+ {"version":3,"file":"packageManager.d.ts","names":[],"sources":["../../../../src/init/utils/packageManager.ts"],"mappings":";;YAMY;;;;;YAMA;;;;;;;EAOV;;;;;EAKA;;;;;EAKA;;;;;;;;;;;;;;;EAeA;;;;;;;YAQU;;EAEV;;EAEA;;;;;;;;EAQA;;IAEE;;IAEA;;;;YAKQ;;EAEV;;EAEA;;EAEA;;;;;;EAMA,kBAAkB;;;;;;EAMlB,wBAAwB;;;;;;EAMxB;;;;;;;;qBASW,yBAAyB;;;;;;qBAiDzB,uBAAoB,oBAAsB;;;;;;qBAY1C,kBAAe;;;;;;;YA2ChB;;;;;;EAMV;;;;;;EAMA,eAAe;;;;EAIf,kBAAkB;;;;;EAKlB;;;YAIU;;EAEV;;;;;;EAMA;;;;;EAKA,cAAc;;;;;;;;qBASH,gCAAgC;;;;;qBA+GhC,6BAA6B;;;;;;;;qBAc7B,sCAAmC,aACjC;;;;;;;;;;qBA8BF,4BAAyB,cACtB;;qBAOH;;;;;;;;;qBAUA,kBAAe,cACZ;;;;;;;;;;;qBAiBH,iBAAc,cAAkB;qBAIhC,gCAA6B,iBACvB,wBAAsB,UAC9B,iCACR;;;;;qBAyZU,kBAAe,iBACX,oBACG,gBACF,gBAAc;;;;;;;;;;qBAgBnB,wBAAqB;;;;;;;;qBAarB,mBAAgB;;;;;;qBAahB,oBAAiB,iBACb,gBACC"}
@@ -1,8 +1,12 @@
1
1
  import { Platform } from "../installSkills/index.js";
2
2
  //#region src/installMCP/installMCP.d.ts
3
3
  export type MCPTransport = 'stdio' | 'sse';
4
+ /** Transports accepted by `intlayer init mcp --transport`. */
5
+ export declare const MCP_TRANSPORTS: MCPTransport[];
4
6
  /**
5
7
  * Installs the Intlayer MCP server configuration for a specific platform.
8
+ * Every platform is configured at the project level (Claude Code included,
9
+ * through `.mcp.json`), so nothing outside the project is modified.
6
10
  */
7
11
  export declare const installMCP: (projectRoot: string, platform: Platform, transport: MCPTransport) => Promise<string>;
8
12
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"installMCP.d.ts","names":[],"sources":["../../../src/installMCP/installMCP.ts"],"mappings":";;YAKY;;;;qBAsBC,aAAU,qBACF,UACT,UAAQ,WACP,iBACV"}
1
+ {"version":3,"file":"installMCP.d.ts","names":[],"sources":["../../../src/installMCP/installMCP.ts"],"mappings":";;YAIY;;qBAGC,gBAAgB;;;;;;qBA4DhB,aAAU,qBACF,UACT,UAAQ,WACP,iBACV"}
@@ -9,6 +9,7 @@ export declare const SKILLS_METADATA: {
9
9
  readonly Usage: 'How to use Intlayer in your project';
10
10
  readonly CLI: 'Intlayer CLI commands and usage';
11
11
  readonly Compiler: 'Intlayer Compiler setup and usage for automatic content extraction without .content files';
12
+ readonly BundleOptimization: 'Purge, minify and import modes; writing code the bundle optimizer can follow';
12
13
  readonly RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content';
13
14
  readonly DevTools: 'ESLint, LSP, VS Code & Chrome extensions, MCP server and CI/CD';
14
15
  readonly Compat: 'Migrate from i18next, next-intl, react-intl, vue-i18n, Lingui… keeping their API';
@@ -45,6 +46,12 @@ export interface PlatformMetadata {
45
46
  export declare const PLATFORMS_METADATA: Record<string, PlatformMetadata>;
46
47
  export type Platform = keyof typeof PLATFORMS_METADATA;
47
48
  export declare const PLATFORMS: Platform[];
49
+ /**
50
+ * Detects the AI platform in use. The environment of the running tool wins;
51
+ * otherwise the first platform whose config folder (`.claude`, `.cursor`…)
52
+ * exists in the project root is returned.
53
+ */
54
+ export declare const detectPlatform: (projectRoot: string) => Platform | undefined;
48
55
  /**
49
56
  * Installs skills using the "Agent Skills" directory standard.
50
57
  * Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/installSkills/index.ts"],"mappings":";;;;qBASa;WACX;WACA;WACA;WAEA;WACA;WACA;WAEA;WACA;WACA;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;YAIU,qBAAqB;qBAEpB,QAAyC;;;;;;;qBAoFzC,mBAAgB,cACb,2BACb;iBAUc;EACf;EACA;EACA;;;;;qBAMW,oBAAoB,eAAe;YA6JpC,wBAAwB;qBAEvB,WAA+C;;;;;qBA8G/C,gBAAa,qBACL,UACT,UAAQ,QACV,YACP"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/installSkills/index.ts"],"mappings":";;;;qBASa;WACX;WACA;WACA;WAEA;WACA;WACA;WAEA;WAEA;WACA;WACA;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;YAIU,qBAAqB;qBAEpB,QAAyC;;;;;;;qBAqFzC,mBAAgB,cACb,2BACb;iBAUc;EACf;EACA;EACA;;;;;qBAMW,oBAAoB,eAAe;YA8JpC,wBAAwB;qBAEvB,WAA+C;;;;;;qBA4B/C,iBAAc,wBAA0B;;;;;qBAuHxC,gBAAa,qBACL,UACT,UAAQ,QACV,YACP"}
@@ -1 +1 @@
1
- {"version":3,"file":"loadRemoteDictionaries.d.ts","names":[],"sources":["../../../src/loadDictionaries/loadRemoteDictionaries.ts"],"mappings":";;;;qBAea,4BAAyB,eACrB,gBAAgB,kBAC9B;qBAOU,yBAAsB,0CAAA,gBAAA,kBAEf,QAAQ,+BAA6B;EAErD;EACA;EACA,WAAW,OAAO;MAEnB,QAAQ"}
1
+ {"version":3,"file":"loadRemoteDictionaries.d.ts","names":[],"sources":["../../../src/loadDictionaries/loadRemoteDictionaries.ts"],"mappings":";;;;qBAYa,4BAAyB,eACrB,gBAAgB,kBAC9B;qBAOU,yBAAsB,0CAAA,gBAAA,kBAEf,QAAQ,+BAA6B;EAErD;EACA;EACA,WAAW,OAAO;MAEnB,QAAQ"}
@@ -0,0 +1,14 @@
1
+ import { fetchDistantDictionaries } from "../fetchDistantDictionaries.js";
2
+ import { IntlayerConfig } from "@intlayer/types/config";
3
+ import { dictionaryEndpoint } from "@intlayer/api/dictionary";
4
+ //#region src/loadDictionaries/remoteDictionaryClient.d.ts
5
+ /**
6
+ * Creates the CMS dictionary client.
7
+ *
8
+ * Kept in its own module so `loadRemoteDictionaries` can import it lazily:
9
+ * `@intlayer/api` is only loaded when remote credentials are configured.
10
+ */
11
+ export declare const createRemoteDictionaryClient: (configuration: IntlayerConfig) => ReturnType<typeof dictionaryEndpoint>;
12
+ //#endregion
13
+ export { fetchDistantDictionaries };
14
+ //# sourceMappingURL=remoteDictionaryClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteDictionaryClient.d.ts","names":[],"sources":["../../../src/loadDictionaries/remoteDictionaryClient.ts"],"mappings":";;;;;;;;;;qBAYa,+BAA4B,eACxB,mBACd,kBAAkB"}
@@ -0,0 +1,67 @@
1
+ import { IntlayerConfig } from "@intlayer/types/config";
2
+ //#region src/prepareIntlayerServer.d.ts
3
+ /**
4
+ * Explicit override, for any setup the detection below does not recognise:
5
+ * `INTLAYER_WATCH=true` forces the content watcher on, `INTLAYER_WATCH=false`
6
+ * forces it off.
7
+ */
8
+ export declare const INTLAYER_WATCH_ENV_VAR = "INTLAYER_WATCH";
9
+ /**
10
+ * Whether a command line is a watcher that restarts its child on changes.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * getIsDevWatcherCommand('node /app/node_modules/.bin/nodemon src/index.ts'); // → true
15
+ * getIsDevWatcherCommand('node dist/index.js'); // → false
16
+ * ```
17
+ */
18
+ export declare const getIsDevWatcherCommand: (command: string) => boolean;
19
+ /**
20
+ * Whether a server process runs in development, and so should watch the
21
+ * content declarations.
22
+ *
23
+ * `INTLAYER_WATCH=true|false` decides first, then `NODE_ENV` when set. An unset
24
+ * `NODE_ENV` is not a sign of development (`bun dist/index.mjs` rarely sets
25
+ * it), so the process must then show a positive signal, cheapest first:
26
+ * 1. a runtime watch flag or marker (`bun --watch`/`--hot`, `node --watch`,
27
+ * `ts-node-dev`);
28
+ * 2. a `dev`-like package script;
29
+ * 3. a restarting watcher in its own command line or its ancestors'
30
+ * (`deno run --watch`, `nodemon`, `tsx watch`…), for those started
31
+ * directly rather than through a script.
32
+ */
33
+ export declare const getIsServerDevelopment: () => Promise<boolean>;
34
+ export type PrepareIntlayerServerOptions = {
35
+ /**
36
+ * How the integration names itself in the watcher lock and in messages, e.g.
37
+ * `express-intlayer`.
38
+ */
39
+ label: string;
40
+ /**
41
+ * Whether to watch the content declarations after preparing them.
42
+ * Defaults to {@link getIsServerDevelopment}.
43
+ */
44
+ watch?: boolean;
45
+ };
46
+ /**
47
+ * Prepares the dictionaries for a server integration (Express, Fastify, Hono…)
48
+ * and, in development, keeps them in sync with the content declarations.
49
+ *
50
+ * Replaces wrapping the dev server in `intlayer watch --with`: the watcher runs
51
+ * inside the server, deduplicated through the project's watcher lock, so a
52
+ * server restarted by `tsx watch` / `node --watch` hands it over to its
53
+ * successor, and a remaining `intlayer watch` makes it stand down.
54
+ *
55
+ * Fire-and-forget: the server must not wait on the build to start listening.
56
+ *
57
+ * @param configuration - The resolved Intlayer configuration.
58
+ * @param options - How the integration identifies itself, and whether to watch.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * prepareIntlayerServer(getConfiguration(), { label: 'express-intlayer' });
63
+ * ```
64
+ */
65
+ export declare const prepareIntlayerServer: (configuration: IntlayerConfig, { label, watch }: PrepareIntlayerServerOptions) => void;
66
+ //#endregion
67
+ //# sourceMappingURL=prepareIntlayerServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepareIntlayerServer.d.ts","names":[],"sources":["../../src/prepareIntlayerServer.ts"],"mappings":";;;;;;;qBAWa;;;;;;;;;;qBAiDA,yBAAsB;;;;;;;;;;;;;;;qBA4BtB,8BAAmC;YAkCpC;;;;;EAKV;;;;;EAKA;;;;;;;;;;;;;;;;;;;;;qBAsBW,wBAAqB,eACjB,kBAAc,OAAA,SACX"}
@@ -0,0 +1,35 @@
1
+ //#region src/utils/getProcessChainCommands.d.ts
2
+ /** Process as listed by the OS: its parent and the command line it runs. */
3
+ export type ProcessEntry = {
4
+ parentPid: number;
5
+ command: string;
6
+ };
7
+ /**
8
+ * Parses the output of `ps -A -o pid=,ppid=,command=`.
9
+ *
10
+ * @param output - One `<pid> <ppid> <command>` row per line.
11
+ * @returns The processes, keyed by PID.
12
+ */
13
+ export declare const parseProcessTable: (output: string) => Map<number, ProcessEntry>;
14
+ /**
15
+ * Command lines of this process and of the processes above it, closest first.
16
+ *
17
+ * This process is included because some runtimes restart the script inside
18
+ * the same process, leaving their watch flag only on their own command line
19
+ * (`deno run --watch`).
20
+ *
21
+ * Best effort: resolves to an empty list on Windows, or when the process list
22
+ * cannot be read (sandbox, missing `ps`, Deno without the permission), and
23
+ * never throws.
24
+ *
25
+ * @param maxDepth - How many processes to read at most, this one included.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * await getProcessChainCommands();
30
+ * // → ['node src/index.js', 'node …/nodemon src/index.js', 'npm run dev']
31
+ * ```
32
+ */
33
+ export declare const getProcessChainCommands: (maxDepth?: number) => Promise<string[]>;
34
+ //#endregion
35
+ //# sourceMappingURL=getProcessChainCommands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getProcessChainCommands.d.ts","names":[],"sources":["../../../src/utils/getProcessChainCommands.ts"],"mappings":";;YAKY;EACV;EACA;;;;;;;;qBAYW,oBAAiB,mBAE3B,YAAY;;;;;;;;;;;;;;;;;;;;qBA2GF,0BAAuB,sBAEjC"}
@@ -20,6 +20,7 @@ import { RunOnceContext, runOnce } from "./runOnce.js";
20
20
  import { ParallelHandle, runParallel } from "./runParallel/index.js";
21
21
  import { sortAlphabetically } from "./sortAlphabetically.js";
22
22
  import { splitTextByLines } from "./splitTextByLine.js";
23
+ import { StartContentWatcherOptions, startContentWatcher } from "./startContentWatcher.js";
23
24
  import { verifyIdenticObjectFormat } from "./verifyIdenticObjectFormat.js";
24
25
  import { withFileLock } from "./withFileLock.js";
25
- export { CLI_CONTENT_WATCHER_ENV_VAR, ContentDeclarationFileName, ContentWatcherOwner, ContentWatcherSource, Extension, Format, JSONObject, JsonChunk, ParallelHandle, Primitive, Queue, Recursive, RunOnceContext, acquireContentWatcherLock, assembleJSON, autoDecorateContent, buildComponentFilesList, chunkArray, chunkJSON, claimCliContentWatcher, excludeObjectFormat, formatLocale, formatPath, getChunk, getCliContentWatcherLabel, getContentExtension, getContentWatcherLockFilePath, getContentWatcherOwner, getExtensionFromFormat, getFormatFromExtension, getGlobalLimiter, getPathHash, getTaskLimiter, mergeChunks, pLimit, parallelize, parallelizeGlobal, parseContentDeclarationFileName, reconstructFromSingleChunk, reduceObjectFormat, reportRedundantContentWatcher, resolveObjectPromises, resolveRelativePath, runOnce, runParallel, sortAlphabetically, splitTextByLines, verifyIdenticObjectFormat, withFileLock };
26
+ export { CLI_CONTENT_WATCHER_ENV_VAR, ContentDeclarationFileName, ContentWatcherOwner, ContentWatcherSource, Extension, Format, JSONObject, JsonChunk, ParallelHandle, Primitive, Queue, Recursive, RunOnceContext, StartContentWatcherOptions, acquireContentWatcherLock, assembleJSON, autoDecorateContent, buildComponentFilesList, chunkArray, chunkJSON, claimCliContentWatcher, excludeObjectFormat, formatLocale, formatPath, getChunk, getCliContentWatcherLabel, getContentExtension, getContentWatcherLockFilePath, getContentWatcherOwner, getExtensionFromFormat, getFormatFromExtension, getGlobalLimiter, getPathHash, getTaskLimiter, mergeChunks, pLimit, parallelize, parallelizeGlobal, parseContentDeclarationFileName, reconstructFromSingleChunk, reduceObjectFormat, reportRedundantContentWatcher, resolveObjectPromises, resolveRelativePath, runOnce, runParallel, sortAlphabetically, splitTextByLines, startContentWatcher, verifyIdenticObjectFormat, withFileLock };
@@ -0,0 +1,40 @@
1
+ import { IntlayerConfig } from "@intlayer/types/config";
2
+ //#region src/utils/startContentWatcher.d.ts
3
+ export type StartContentWatcherOptions = {
4
+ /**
5
+ * How the integration names itself in the lock and in messages, e.g.
6
+ * `vite-intlayer`.
7
+ */
8
+ label: string;
9
+ /**
10
+ * Whether this process must never own the watcher, re-checked on every
11
+ * attempt (e.g. a helper process that outlives the dev server).
12
+ */
13
+ getShouldSkip?: () => boolean;
14
+ };
15
+ /**
16
+ * Starts the content declaration watcher from an integration (bundler plugin or
17
+ * server middleware), making sure only one watcher rebuilds a project's
18
+ * dictionaries.
19
+ *
20
+ * - Idempotent within a process, across module copies and hot reloads.
21
+ * - Stands down, with an explanation, when `intlayer watch` already covers the
22
+ * project, whether it spawned this process (`--with`) or runs elsewhere.
23
+ * - Otherwise the first process to take the project lock watches; the others
24
+ * retry in the background to take over once it stops.
25
+ *
26
+ * Not awaitable on purpose: a dev server must not wait on the watcher to serve.
27
+ *
28
+ * @param configuration - The resolved Intlayer configuration.
29
+ * @param options - How the integration identifies itself.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * configureServer() {
34
+ * startContentWatcher(configuration, { label: 'vite-intlayer' });
35
+ * }
36
+ * ```
37
+ */
38
+ export declare const startContentWatcher: (configuration: IntlayerConfig, options: StartContentWatcherOptions) => void;
39
+ //#endregion
40
+ //# sourceMappingURL=startContentWatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startContentWatcher.d.ts","names":[],"sources":["../../../src/utils/startContentWatcher.ts"],"mappings":";;YAgBY;;;;;EAKV;;;;;EAKA;;;;;;;;;;;;;;;;;;;;;;;;;qBA6GW,sBAAmB,eACf,gBAAc,SACpB"}