angular-intlayer 9.5.5 → 9.5.6
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/README.md
CHANGED
|
@@ -201,7 +201,6 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
|
|
|
201
201
|
<li><a href="https://intlayer.org/doc/environment/astro/vue" rel=''>Vue</a></li>
|
|
202
202
|
<li><a href="https://intlayer.org/doc/environment/astro/svelte" rel=''>Svelte</a></li>
|
|
203
203
|
<li><a href="https://intlayer.org/doc/environment/astro/solid" rel=''>Solid</a></li>
|
|
204
|
-
<li><a href="https://intlayer.org/doc/environment/astro/vanilla" rel=''>Vanilla JS</a></li>
|
|
205
204
|
<li><a href="https://intlayer.org/doc/environment/astro/lit" rel=''>Lit</a></li>
|
|
206
205
|
</ul>
|
|
207
206
|
</li>
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_esbuild_hiddenDirectory = require('./hiddenDirectory.cjs');
|
|
3
3
|
const require_esbuild_resolvePackageExport = require('./resolvePackageExport.cjs');
|
|
4
|
-
let node_fs_promises = require("node:fs/promises");
|
|
5
4
|
let node_module = require("node:module");
|
|
6
5
|
let node_path = require("node:path");
|
|
6
|
+
let _intlayer_config_node = require("@intlayer/config/node");
|
|
7
|
+
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
8
|
+
let node_fs_promises = require("node:fs/promises");
|
|
7
9
|
let _intlayer_config_dictionaryPreload = require("@intlayer/config/dictionaryPreload");
|
|
8
10
|
let _intlayer_config_envVars = require("@intlayer/config/envVars");
|
|
9
11
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
10
|
-
let _intlayer_config_node = require("@intlayer/config/node");
|
|
11
|
-
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
12
12
|
let _intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
|
|
13
13
|
let _intlayer_engine_build = require("@intlayer/engine/build");
|
|
14
14
|
let _intlayer_engine_cli = require("@intlayer/engine/cli");
|
|
@@ -110,6 +110,12 @@ const intlayerEsbuildPlugin = (options) => {
|
|
|
110
110
|
[wrapKey("NODE_ENV")]: wrapValue(isProduction ? "production" : "development"),
|
|
111
111
|
...(0, _intlayer_config_envVars.getConfigEnvVars)(config, wrapKey, wrapValue)
|
|
112
112
|
};
|
|
113
|
+
if (!preparePromise) preparePromise = (0, _intlayer_engine_build.prepareIntlayer)(config, {
|
|
114
|
+
clean: isProduction,
|
|
115
|
+
cacheTimeoutMs: isProduction ? 3e4 : 36e5,
|
|
116
|
+
env: isProduction ? "prod" : "dev"
|
|
117
|
+
});
|
|
118
|
+
await preparePromise;
|
|
113
119
|
if (isProduction) {
|
|
114
120
|
const dictionaries = (0, _intlayer_dictionaries_entry.getDictionaries)(config);
|
|
115
121
|
if (Object.keys(dictionaries).length === 0) appLogger("No dictionaries found. Please check your configuration.", { isVerbose: true });
|
|
@@ -171,12 +177,6 @@ const intlayerEsbuildPlugin = (options) => {
|
|
|
171
177
|
};
|
|
172
178
|
});
|
|
173
179
|
}
|
|
174
|
-
if (!preparePromise) preparePromise = (0, _intlayer_engine_build.prepareIntlayer)(config, {
|
|
175
|
-
clean: isProduction,
|
|
176
|
-
cacheTimeoutMs: isProduction ? 3e4 : 36e5,
|
|
177
|
-
env: isProduction ? "prod" : "dev"
|
|
178
|
-
});
|
|
179
|
-
await preparePromise;
|
|
180
180
|
build.onStart(async () => {
|
|
181
181
|
if (externalizesPackages === void 0) {
|
|
182
182
|
externalizesPackages = (await build.resolve("@angular/core", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs","names":["normalizePath","resolvePreloadModuleId","createRequire","isInHiddenDirectory","relative","getConfiguration","getAlias","join","getAppLogger","getConfigEnvVars","getDictionaries","getUnusedNodeTypesAsync","formatNodeTypeToEnvVar","formatDictionarySelectorEnvVar","getHasDictionarySelector","resolvePackageExport","dirname","readFile","basename","createDynamicEntryFilter","addDynamicEntryPreload","prepareIntlayer","watch"],"sources":["../../../src/esbuild/plugin.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { basename, dirname, join, relative } from 'node:path';\nimport {\n addDynamicEntryPreload,\n createDynamicEntryFilter,\n resolvePreloadModuleId,\n} from '@intlayer/config/dictionaryPreload';\nimport {\n formatDictionarySelectorEnvVar,\n formatNodeTypeToEnvVar,\n getConfigEnvVars,\n} from '@intlayer/config/envVars';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n getAlias,\n getHasDictionarySelector,\n getUnusedNodeTypesAsync,\n normalizePath,\n} from '@intlayer/config/utils';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { watch } from '@intlayer/engine/watcher';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { isInHiddenDirectory } from './hiddenDirectory';\nimport { resolvePackageExport } from './resolvePackageExport';\n\n/**\n * Absolute id of the locale resolver the injected preamble imports.\n *\n * Resolved from this package, which declares `@intlayer/core` as a dependency,\n * rather than left bare in the emitted source: the importer is a generated\n * entry point under the application's `.intlayer` directory, and an application\n * only depends on `intlayer` and its framework binding, so the bare specifier\n * would resolve from a tree that need not contain the package at all.\n *\n * Always built from `import.meta.url`: the bundler shims it to `__filename` in\n * the CommonJS output, whereas a `typeof require` guard is unreliable here —\n * the ESM output rewrites `require` into an always-defined proxy that has no\n * `resolve` method.\n */\nconst preloadModuleId = normalizePath(\n resolvePreloadModuleId(createRequire(import.meta.url))\n);\n\n/** Bare specifiers of the packages this plugin keeps inside its own build. */\nconst INTLAYER_PACKAGE_FILTER =\n /^(?:intlayer|angular-intlayer|@intlayer\\/[^/]+)(?:\\/|$)/;\n\n/** Namespace of the re-export shims standing in for externalised packages. */\nconst INTLAYER_PACKAGE_NAMESPACE = 'intlayer-package';\n\n/** Matches a module that has a default export, on unminified sources. */\nconst DEFAULT_EXPORT_PATTERN =\n /\\bexport\\s+default\\b|\\bas\\s+default\\b|\\{\\s*default\\s*[,}]/;\n\n// Minimal subset of the esbuild Plugin interface to avoid a hard dependency on\n// the `esbuild` package for type resolution. The shape is compatible with\n// esbuild >=0.17, `@angular-builders/custom-esbuild`, and NX esbuild builders.\nexport type EsbuildResolveArgs = {\n path: string;\n importer: string;\n namespace: string;\n resolveDir: string;\n kind: string;\n pluginData?: unknown;\n};\n\nexport type EsbuildResolveResult = {\n path?: string;\n namespace?: string;\n external?: boolean;\n sideEffects?: boolean;\n pluginData?: unknown;\n errors?: unknown[];\n warnings?: unknown[];\n};\n\nexport type EsbuildLoadArgs = {\n path: string;\n namespace: string;\n pluginData?: unknown;\n};\n\nexport type EsbuildLoadResult = {\n contents: string;\n loader?: string;\n /** Directory relative imports of `contents` resolve from. */\n resolveDir?: string;\n};\n\nexport interface EsbuildPluginBuild {\n initialOptions: {\n alias?: Record<string, string>;\n define?: Record<string, string>;\n minify?: boolean;\n watch?: unknown;\n /** Absolute working directory of the esbuild context (set by Angular's builder). */\n absWorkingDir?: string;\n };\n onStart(callback: () => void | Promise<void>): void;\n /** Intercept module resolution — works even for imports inside node_modules. */\n onResolve(\n options: { filter: RegExp; namespace?: string },\n callback: (\n args: EsbuildResolveArgs\n ) =>\n | EsbuildResolveResult\n | null\n | undefined\n | Promise<EsbuildResolveResult | null | undefined>\n ): void;\n /** Run the remaining resolution pipeline (other plugins, then esbuild). */\n resolve(\n path: string,\n options: Partial<Omit<EsbuildResolveArgs, 'path'>>\n ): Promise<EsbuildResolveResult & { path: string; external: boolean }>;\n /** Intercept module contents, so a resolved file can be rewritten. */\n onLoad(\n options: { filter: RegExp; namespace?: string },\n callback: (\n args: EsbuildLoadArgs\n ) =>\n | EsbuildLoadResult\n | null\n | undefined\n | Promise<EsbuildLoadResult | null | undefined>\n ): void;\n}\n\nexport interface EsbuildPlugin {\n name: string;\n setup(build: EsbuildPluginBuild): void | Promise<void>;\n}\n\nexport type IntlayerEsbuildPluginOptions = {\n configOptions?: GetConfigurationOptions;\n /**\n * Whether to start the Intlayer file watcher for dictionary regeneration.\n * - `true`: always start the watcher (useful for `ng serve`)\n * - `false`: never start the watcher (useful for `ng build`)\n * - `undefined` (default): auto-detect based on the build context\n * (skips the watcher when a production build is detected)\n */\n watch?: boolean;\n};\n\n/**\n * The dev server's file watcher skips dot-directories, so type declarations\n * generated there are never re-read: a key added to a dictionary stays unknown\n * to template type-checking until `ng serve` restarts. Nothing in the plugin\n * can reach that cache, so the fix is to generate the types elsewhere.\n */\nconst warnAboutHiddenTypesDirectory = (\n configuration: IntlayerConfig,\n appLogger: ReturnType<typeof getAppLogger>\n) => {\n const { baseDir, typesDir, moduleAugmentationDir } = configuration.system;\n\n const hiddenDirectories = [\n ...new Set([typesDir, moduleAugmentationDir]),\n ].filter((directory) => isInHiddenDirectory(baseDir, directory));\n\n if (hiddenDirectories.length === 0) return;\n\n appLogger(\n [\n `Type declarations are generated under ${hiddenDirectories.map((directory) => relative(baseDir, directory)).join(', ')}.`,\n \"The Angular dev server does not watch dot-directories, so keys added to a dictionary stay unknown to template type-checking until 'ng serve' restarts.\",\n \"Set 'system.typesDir' and 'system.moduleAugmentationDir' to a directory outside any dot-directory (e.g. 'intlayer-types') and point the tsconfig 'include' at it.\",\n ].join(' '),\n { level: 'warn' }\n );\n};\n\n/**\n * esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.\n *\n * Handles:\n * 1. Injecting `alias` entries so `@intlayer/dictionaries-entry` etc. resolve to\n * the generated files under `.intlayer/`.\n * 2. Defining `process.env.*` tree-shaking constants for production builds.\n * 3. Running `prepareIntlayer` (dictionary generation) before the first build.\n * 4. Starting the chokidar file-watcher in dev / serve mode.\n *\n * Compatible with:\n * - `@angular-builders/custom-esbuild` (`application` or `browser-esbuild` builder)\n * - NX `@nx/angular:browser-esbuild`\n * - Any raw esbuild setup that accepts the standard `Plugin` interface\n *\n * @example\n * ```ts\n * // esbuild.plugins.ts (referenced from angular.json \"plugins\" option)\n * import { intlayerEsbuildPlugin } from 'angular-intlayer/esbuild';\n * export default [intlayerEsbuildPlugin()];\n * ```\n */\nexport const intlayerEsbuildPlugin = (\n options?: IntlayerEsbuildPluginOptions\n): EsbuildPlugin => {\n // All Node.js-heavy initialization (getConfiguration, getAlias, …) is deferred\n // into setup() so it runs in esbuild's Node.js context, not at module-evaluation\n // time. @angular/build loads the plugin file through Vite's SSR module runner\n // (ESM) where CommonJS globals like __filename are undefined. Calling\n // getConfiguration() here would trigger: buildSync → worker threads →\n // __filename → ReferenceError, crashing the plugin before setup() ever runs.\n let config: ReturnType<typeof getConfiguration> | null = null;\n let alias: Record<string, string> | null = null;\n\n // Shared across parallel setup() calls (Angular spawns one per bundle context).\n let preparePromise: Promise<void> | null = null;\n let watcherStarted = false;\n // Once any esbuild context (browser or server) detects a production build,\n // suppress the watcher for all contexts so `ng build` can exit cleanly.\n let isBuildMode = false;\n\n return {\n name: 'intlayer',\n\n async setup(build) {\n if (!config) {\n const baseDir =\n build.initialOptions.absWorkingDir ??\n options?.configOptions?.baseDir ??\n process.cwd();\n\n config = getConfiguration({ baseDir, ...options?.configOptions });\n logConfigDetails({ baseDir, ...options?.configOptions });\n\n alias = getAlias({\n configuration: config,\n formatter: (value: string) => join(config!.system.baseDir, value),\n });\n }\n\n const appLogger = getAppLogger(config);\n const nodeEnvDefine =\n build.initialOptions.define?.['process.env.NODE_ENV'];\n\n // Angular's esbuild builder doesn't set `minify` or `process.env.NODE_ENV`\n // on initialOptions — it handles optimisation through its own pipeline.\n // Instead, Angular defines `ngDevMode` as `\"false\"` in production builds.\n const isProduction =\n nodeEnvDefine === '\"production\"' ||\n nodeEnvDefine === \"'production'\" ||\n build.initialOptions.minify === true ||\n build.initialOptions.define?.['ngDevMode'] === 'false';\n\n if (isProduction) {\n isBuildMode = true;\n }\n\n const wrapKey = (key: string) => `process.env.${key}`;\n const wrapValue = (value: string) => `\"${value}\"`;\n\n const envVars: Record<string, string> = {\n // Catch-all so that any `process.env.*` read NOT covered by a specific\n // key below resolves to `undefined` instead of dereferencing a bare\n // `process`, which is not defined in browser bundles and throws\n // `process is not defined`. esbuild resolves the most specific define\n // first, so the keys below keep their tree-shaking effect.\n 'process.env': '{}',\n [wrapKey('INTLAYER')]: wrapValue('true'),\n [wrapKey('NODE_ENV')]: wrapValue(\n isProduction ? 'production' : 'development'\n ),\n // Tree shaking flags derived from the config (routing / storage /\n // editor). Emitted in every mode so behaviour is consistent in dev.\n ...getConfigEnvVars(config, wrapKey, wrapValue),\n };\n\n if (isProduction) {\n const dictionaries = getDictionaries(config);\n if (Object.keys(dictionaries).length === 0) {\n appLogger('No dictionaries found. Please check your configuration.', {\n isVerbose: true,\n });\n }\n\n const unusedNodeTypes = await getUnusedNodeTypesAsync(dictionaries);\n Object.assign(\n envVars,\n // Tree shaking based on unused node types\n formatNodeTypeToEnvVar(unusedNodeTypes, wrapKey, wrapValue),\n // Tree shaking the dictionary selector logic\n // (collections / variants)\n formatDictionarySelectorEnvVar(\n getHasDictionarySelector(dictionaries),\n wrapKey,\n wrapValue\n )\n );\n }\n\n // Existing defines (Angular's own, or the user's angular.json `define`\n // block) take precedence over the Intlayer ones.\n build.initialOptions.define = {\n ...envVars,\n ...(build.initialOptions.define ?? {}),\n };\n\n build.initialOptions.alias = {\n ...alias,\n ...(build.initialOptions.alias ?? {}),\n };\n\n for (const [from, to] of Object.entries(alias!)) {\n const escapedFrom = from.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({\n path: to,\n }));\n }\n\n // Angular's dev server marks every import that resolves under\n // `node_modules` as external so Vite can pre-bundle it. Vite's\n // pre-bundler runs without this plugin, so the aliases above never apply\n // there and the real `@intlayer/config/built` — a Node config loader —\n // ends up in the browser. Angular's externalising plugin is registered\n // ahead of this one and only lets a resolution through when the path it\n // gets back is outside `node_modules`; so in that mode an Intlayer\n // package resolves to a re-export shim in its own namespace, whose\n // relative import of the real file the pipeline then bundles as usual.\n // Whether the pipeline externalises packages is probed once, at the\n // first build, so production builds keep the bundler's own resolution.\n let externalizesPackages: boolean | undefined;\n\n build.onResolve({ filter: INTLAYER_PACKAGE_FILTER }, (args) => {\n if (!externalizesPackages || !args.resolveDir) return null;\n\n const importCondition = args.kind.startsWith('require')\n ? 'require'\n : 'import';\n const resolved = resolvePackageExport(args.path, args.resolveDir, [\n 'browser',\n 'module',\n importCondition,\n ]);\n\n if (!resolved) return null;\n\n return {\n // Neither a `node_modules` segment nor a script extension, which the\n // externalising plugin and Angular's own JS loader key on. Ends with\n // the specifier so a lazy chunk is named after it, and starts with\n // the encoded directory so two copies of a package stay distinct.\n path: `${encodeURIComponent(dirname(resolved.path))}/${args.path}`,\n namespace: INTLAYER_PACKAGE_NAMESPACE,\n pluginData: { realPath: resolved.path },\n sideEffects: resolved.sideEffects,\n };\n });\n\n build.onLoad(\n { filter: /.*/, namespace: INTLAYER_PACKAGE_NAMESPACE },\n async (args) => {\n const { realPath } = args.pluginData as { realPath: string };\n const source = await readFile(realPath, 'utf-8');\n const specifier = JSON.stringify(`./${basename(realPath)}`);\n\n const contents = [\n `export * from ${specifier};`,\n DEFAULT_EXPORT_PATTERN.test(source) &&\n `export { default } from ${specifier};`,\n ]\n .filter(Boolean)\n .join('\\n');\n\n return { contents, loader: 'js', resolveDir: dirname(realPath) };\n }\n );\n\n // Dictionaries load with the chunk that needs them rather than being\n // fetched once that chunk renders: the entry point starts the browsing\n // locale's load as it evaluates, so a lazily loaded route requests its\n // content on `import()` instead of on first render. Without it every\n // dictionary read renders an empty placeholder first and fills in a tick\n // later.\n //\n // Not gated on the configured `importMode`: a `.content` file can set\n // `importMode: 'dynamic'` on a single dictionary under a `static` or\n // `fetch` global mode, and that dictionary needs the preload just the\n // same. Only entry points the optimizer imported are ever loaded, so the\n // path check below is the accurate gate.\n if (config.build.dictionariesPreload) {\n const dynamicDictionariesDir = normalizePath(\n config.system.dynamicDictionariesDir\n );\n\n build.onLoad(\n { filter: createDynamicEntryFilter(dynamicDictionariesDir) },\n async ({ path }) => {\n const posixPath = normalizePath(path);\n if (!posixPath.startsWith(`${dynamicDictionariesDir}/`))\n return null;\n\n const code = await readFile(path, 'utf-8');\n const result = addDynamicEntryPreload(code, preloadModuleId);\n\n if (result.skipped) return null;\n\n return { contents: result.code, loader: 'js' };\n }\n );\n }\n\n if (!preparePromise) {\n preparePromise = prepareIntlayer(config, {\n clean: isProduction,\n cacheTimeoutMs: isProduction ? 1000 * 30 : 1000 * 60 * 60,\n env: isProduction ? 'prod' : 'dev',\n });\n }\n\n await preparePromise;\n\n build.onStart(async () => {\n // `@angular/core` is always installed and never worth excluding from\n // pre-bundling, so its fate tells whether packages get externalised.\n if (externalizesPackages === undefined) {\n externalizesPackages = (\n await build.resolve('@angular/core', {\n kind: 'import-statement',\n resolveDir: config!.system.baseDir,\n })\n ).external;\n\n if (externalizesPackages) {\n warnAboutHiddenTypesDirectory(config!, appLogger);\n }\n }\n\n // Determine whether the watcher should run:\n // 1. Explicit option from the caller takes precedence\n // 2. If any esbuild context detected a production build, skip\n // 3. esbuild's own watch mode is a positive signal\n const shouldWatch = options?.watch ?? !isBuildMode;\n\n if (shouldWatch && !watcherStarted) {\n watcherStarted = true;\n\n await watch({ configuration: config! });\n }\n });\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,MAAM,sBAAkBA,0CACtBC,+DAAuBC,wEAA6B,CAAC,CACvD;;AAGA,MAAM,0BACJ;;AAGF,MAAM,6BAA6B;;AAGnC,MAAM,yBACJ;;;;;;;AAmGF,MAAM,iCACJ,eACA,cACG;CACH,MAAM,EAAE,SAAS,UAAU,0BAA0B,cAAc;CAEnE,MAAM,oBAAoB,CACxB,mBAAG,IAAI,IAAI,CAAC,UAAU,qBAAqB,CAAC,CAC9C,CAAC,CAAC,QAAQ,cAAcC,oDAAoB,SAAS,SAAS,CAAC;CAE/D,IAAI,kBAAkB,WAAW,GAAG;CAEpC,UACE;EACE,yCAAyC,kBAAkB,KAAK,kBAAcC,oBAAS,SAAS,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;EACvH;EACA;CACF,CAAC,CAAC,KAAK,GAAG,GACV,EAAE,OAAO,OAAO,CAClB;AACF;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,yBACX,YACkB;CAOlB,IAAI,SAAqD;CACzD,IAAI,QAAuC;CAG3C,IAAI,iBAAuC;CAC3C,IAAI,iBAAiB;CAGrB,IAAI,cAAc;CAElB,OAAO;EACL,MAAM;EAEN,MAAM,MAAM,OAAO;GACjB,IAAI,CAAC,QAAQ;IACX,MAAM,UACJ,MAAM,eAAe,iBACrB,SAAS,eAAe,WACxB,QAAQ,IAAI;IAEd,aAASC,wCAAiB;KAAE;KAAS,GAAG,SAAS;IAAc,CAAC;IAChE,2CAAiB;KAAE;KAAS,GAAG,SAAS;IAAc,CAAC;IAEvD,YAAQC,iCAAS;KACf,eAAe;KACf,YAAY,cAAkBC,gBAAK,OAAQ,OAAO,SAAS,KAAK;IAClE,CAAC;GACH;GAEA,MAAM,gBAAYC,sCAAa,MAAM;GACrC,MAAM,gBACJ,MAAM,eAAe,SAAS;GAKhC,MAAM,eACJ,kBAAkB,oBAClB,kBAAkB,kBAClB,MAAM,eAAe,WAAW,QAChC,MAAM,eAAe,SAAS,iBAAiB;GAEjD,IAAI,cACF,cAAc;GAGhB,MAAM,WAAW,QAAgB,eAAe;GAChD,MAAM,aAAa,UAAkB,IAAI,MAAM;GAE/C,MAAM,UAAkC;IAMtC,eAAe;KACd,QAAQ,UAAU,IAAI,UAAU,MAAM;KACtC,QAAQ,UAAU,IAAI,UACrB,eAAe,eAAe,aAChC;IAGA,OAAGC,2CAAiB,QAAQ,SAAS,SAAS;GAChD;GAEA,IAAI,cAAc;IAChB,MAAM,mBAAeC,8CAAgB,MAAM;IAC3C,IAAI,OAAO,KAAK,YAAY,CAAC,CAAC,WAAW,GACvC,UAAU,2DAA2D,EACnE,WAAW,KACb,CAAC;IAGH,MAAM,kBAAkB,UAAMC,gDAAwB,YAAY;IAClE,OAAO,OACL,aAEAC,iDAAuB,iBAAiB,SAAS,SAAS,OAG1DC,6DACEC,iDAAyB,YAAY,GACrC,SACA,SACF,CACF;GACF;GAIA,MAAM,eAAe,SAAS;IAC5B,GAAG;IACH,GAAI,MAAM,eAAe,UAAU,CAAC;GACtC;GAEA,MAAM,eAAe,QAAQ;IAC3B,GAAG;IACH,GAAI,MAAM,eAAe,SAAS,CAAC;GACrC;GAEA,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,KAAM,GAAG;IAC/C,MAAM,cAAc,KAAK,QAAQ,uBAAuB,MAAM;IAE9D,MAAM,UAAU,EAAE,QAAQ,IAAI,OAAO,IAAI,YAAY,EAAE,EAAE,UAAU,EACjE,MAAM,GACR,EAAE;GACJ;GAaA,IAAI;GAEJ,MAAM,UAAU,EAAE,QAAQ,wBAAwB,IAAI,SAAS;IAC7D,IAAI,CAAC,wBAAwB,CAAC,KAAK,YAAY,OAAO;IAEtD,MAAM,kBAAkB,KAAK,KAAK,WAAW,SAAS,IAClD,YACA;IACJ,MAAM,WAAWC,0DAAqB,KAAK,MAAM,KAAK,YAAY;KAChE;KACA;KACA;IACF,CAAC;IAED,IAAI,CAAC,UAAU,OAAO;IAEtB,OAAO;KAKL,MAAM,GAAG,uBAAmBC,mBAAQ,SAAS,IAAI,CAAC,EAAE,GAAG,KAAK;KAC5D,WAAW;KACX,YAAY,EAAE,UAAU,SAAS,KAAK;KACtC,aAAa,SAAS;IACxB;GACF,CAAC;GAED,MAAM,OACJ;IAAE,QAAQ;IAAM,WAAW;GAA2B,GACtD,OAAO,SAAS;IACd,MAAM,EAAE,aAAa,KAAK;IAC1B,MAAM,SAAS,UAAMC,2BAAS,UAAU,OAAO;IAC/C,MAAM,YAAY,KAAK,UAAU,SAAKC,oBAAS,QAAQ,GAAG;IAU1D,OAAO;KAAE,UARQ,CACf,iBAAiB,UAAU,IAC3B,uBAAuB,KAAK,MAAM,KAChC,2BAA2B,UAAU,EACzC,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,IAEQ;KAAG,QAAQ;KAAM,gBAAYF,mBAAQ,QAAQ;IAAE;GACjE,CACF;GAcA,IAAI,OAAO,MAAM,qBAAqB;IACpC,MAAM,6BAAyBhB,sCAC7B,OAAO,OAAO,sBAChB;IAEA,MAAM,OACJ,EAAE,YAAQmB,6DAAyB,sBAAsB,EAAE,GAC3D,OAAO,EAAE,WAAW;KAElB,IAAI,KADcnB,sCAAc,IACnB,CAAC,CAAC,WAAW,GAAG,uBAAuB,EAAE,GACpD,OAAO;KAET,MAAM,OAAO,UAAMiB,2BAAS,MAAM,OAAO;KACzC,MAAM,aAASG,2DAAuB,MAAM,eAAe;KAE3D,IAAI,OAAO,SAAS,OAAO;KAE3B,OAAO;MAAE,UAAU,OAAO;MAAM,QAAQ;KAAK;IAC/C,CACF;GACF;GAEA,IAAI,CAAC,gBACH,qBAAiBC,wCAAgB,QAAQ;IACvC,OAAO;IACP,gBAAgB,eAAe,MAAY;IAC3C,KAAK,eAAe,SAAS;GAC/B,CAAC;GAGH,MAAM;GAEN,MAAM,QAAQ,YAAY;IAGxB,IAAI,yBAAyB,QAAW;KACtC,wBACE,MAAM,MAAM,QAAQ,iBAAiB;MACnC,MAAM;MACN,YAAY,OAAQ,OAAO;KAC7B,CAAC,EAAC,CACF;KAEF,IAAI,sBACF,8BAA8B,QAAS,SAAS;IAEpD;IAQA,KAFoB,SAAS,SAAS,CAAC,gBAEpB,CAAC,gBAAgB;KAClC,iBAAiB;KAEjB,UAAMC,gCAAM,EAAE,eAAe,OAAQ,CAAC;IACxC;GACF,CAAC;EACH;CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"plugin.cjs","names":["normalizePath","resolvePreloadModuleId","createRequire","isInHiddenDirectory","relative","getConfiguration","getAlias","join","getAppLogger","getConfigEnvVars","prepareIntlayer","getDictionaries","getUnusedNodeTypesAsync","formatNodeTypeToEnvVar","formatDictionarySelectorEnvVar","getHasDictionarySelector","resolvePackageExport","dirname","readFile","basename","createDynamicEntryFilter","addDynamicEntryPreload","watch"],"sources":["../../../src/esbuild/plugin.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { basename, dirname, join, relative } from 'node:path';\nimport {\n addDynamicEntryPreload,\n createDynamicEntryFilter,\n resolvePreloadModuleId,\n} from '@intlayer/config/dictionaryPreload';\nimport {\n formatDictionarySelectorEnvVar,\n formatNodeTypeToEnvVar,\n getConfigEnvVars,\n} from '@intlayer/config/envVars';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n getAlias,\n getHasDictionarySelector,\n getUnusedNodeTypesAsync,\n normalizePath,\n} from '@intlayer/config/utils';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { watch } from '@intlayer/engine/watcher';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { isInHiddenDirectory } from './hiddenDirectory';\nimport { resolvePackageExport } from './resolvePackageExport';\n\n/**\n * Absolute id of the locale resolver the injected preamble imports.\n *\n * Resolved from this package, which declares `@intlayer/core` as a dependency,\n * rather than left bare in the emitted source: the importer is a generated\n * entry point under the application's `.intlayer` directory, and an application\n * only depends on `intlayer` and its framework binding, so the bare specifier\n * would resolve from a tree that need not contain the package at all.\n *\n * Always built from `import.meta.url`: the bundler shims it to `__filename` in\n * the CommonJS output, whereas a `typeof require` guard is unreliable here —\n * the ESM output rewrites `require` into an always-defined proxy that has no\n * `resolve` method.\n */\nconst preloadModuleId = normalizePath(\n resolvePreloadModuleId(createRequire(import.meta.url))\n);\n\n/** Bare specifiers of the packages this plugin keeps inside its own build. */\nconst INTLAYER_PACKAGE_FILTER =\n /^(?:intlayer|angular-intlayer|@intlayer\\/[^/]+)(?:\\/|$)/;\n\n/** Namespace of the re-export shims standing in for externalised packages. */\nconst INTLAYER_PACKAGE_NAMESPACE = 'intlayer-package';\n\n/** Matches a module that has a default export, on unminified sources. */\nconst DEFAULT_EXPORT_PATTERN =\n /\\bexport\\s+default\\b|\\bas\\s+default\\b|\\{\\s*default\\s*[,}]/;\n\n// Minimal subset of the esbuild Plugin interface to avoid a hard dependency on\n// the `esbuild` package for type resolution. The shape is compatible with\n// esbuild >=0.17, `@angular-builders/custom-esbuild`, and NX esbuild builders.\nexport type EsbuildResolveArgs = {\n path: string;\n importer: string;\n namespace: string;\n resolveDir: string;\n kind: string;\n pluginData?: unknown;\n};\n\nexport type EsbuildResolveResult = {\n path?: string;\n namespace?: string;\n external?: boolean;\n sideEffects?: boolean;\n pluginData?: unknown;\n errors?: unknown[];\n warnings?: unknown[];\n};\n\nexport type EsbuildLoadArgs = {\n path: string;\n namespace: string;\n pluginData?: unknown;\n};\n\nexport type EsbuildLoadResult = {\n contents: string;\n loader?: string;\n /** Directory relative imports of `contents` resolve from. */\n resolveDir?: string;\n};\n\nexport interface EsbuildPluginBuild {\n initialOptions: {\n alias?: Record<string, string>;\n define?: Record<string, string>;\n minify?: boolean;\n watch?: unknown;\n /** Absolute working directory of the esbuild context (set by Angular's builder). */\n absWorkingDir?: string;\n };\n onStart(callback: () => void | Promise<void>): void;\n /** Intercept module resolution — works even for imports inside node_modules. */\n onResolve(\n options: { filter: RegExp; namespace?: string },\n callback: (\n args: EsbuildResolveArgs\n ) =>\n | EsbuildResolveResult\n | null\n | undefined\n | Promise<EsbuildResolveResult | null | undefined>\n ): void;\n /** Run the remaining resolution pipeline (other plugins, then esbuild). */\n resolve(\n path: string,\n options: Partial<Omit<EsbuildResolveArgs, 'path'>>\n ): Promise<EsbuildResolveResult & { path: string; external: boolean }>;\n /** Intercept module contents, so a resolved file can be rewritten. */\n onLoad(\n options: { filter: RegExp; namespace?: string },\n callback: (\n args: EsbuildLoadArgs\n ) =>\n | EsbuildLoadResult\n | null\n | undefined\n | Promise<EsbuildLoadResult | null | undefined>\n ): void;\n}\n\nexport interface EsbuildPlugin {\n name: string;\n setup(build: EsbuildPluginBuild): void | Promise<void>;\n}\n\nexport type IntlayerEsbuildPluginOptions = {\n configOptions?: GetConfigurationOptions;\n /**\n * Whether to start the Intlayer file watcher for dictionary regeneration.\n * - `true`: always start the watcher (useful for `ng serve`)\n * - `false`: never start the watcher (useful for `ng build`)\n * - `undefined` (default): auto-detect based on the build context\n * (skips the watcher when a production build is detected)\n */\n watch?: boolean;\n};\n\n/**\n * The dev server's file watcher skips dot-directories, so type declarations\n * generated there are never re-read: a key added to a dictionary stays unknown\n * to template type-checking until `ng serve` restarts. Nothing in the plugin\n * can reach that cache, so the fix is to generate the types elsewhere.\n */\nconst warnAboutHiddenTypesDirectory = (\n configuration: IntlayerConfig,\n appLogger: ReturnType<typeof getAppLogger>\n) => {\n const { baseDir, typesDir, moduleAugmentationDir } = configuration.system;\n\n const hiddenDirectories = [\n ...new Set([typesDir, moduleAugmentationDir]),\n ].filter((directory) => isInHiddenDirectory(baseDir, directory));\n\n if (hiddenDirectories.length === 0) return;\n\n appLogger(\n [\n `Type declarations are generated under ${hiddenDirectories.map((directory) => relative(baseDir, directory)).join(', ')}.`,\n \"The Angular dev server does not watch dot-directories, so keys added to a dictionary stay unknown to template type-checking until 'ng serve' restarts.\",\n \"Set 'system.typesDir' and 'system.moduleAugmentationDir' to a directory outside any dot-directory (e.g. 'intlayer-types') and point the tsconfig 'include' at it.\",\n ].join(' '),\n { level: 'warn' }\n );\n};\n\n/**\n * esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.\n *\n * Handles:\n * 1. Injecting `alias` entries so `@intlayer/dictionaries-entry` etc. resolve to\n * the generated files under `.intlayer/`.\n * 2. Defining `process.env.*` tree-shaking constants for production builds.\n * 3. Running `prepareIntlayer` (dictionary generation) before the first build.\n * 4. Starting the chokidar file-watcher in dev / serve mode.\n *\n * Compatible with:\n * - `@angular-builders/custom-esbuild` (`application` or `browser-esbuild` builder)\n * - NX `@nx/angular:browser-esbuild`\n * - Any raw esbuild setup that accepts the standard `Plugin` interface\n *\n * @example\n * ```ts\n * // esbuild.plugins.ts (referenced from angular.json \"plugins\" option)\n * import { intlayerEsbuildPlugin } from 'angular-intlayer/esbuild';\n * export default [intlayerEsbuildPlugin()];\n * ```\n */\nexport const intlayerEsbuildPlugin = (\n options?: IntlayerEsbuildPluginOptions\n): EsbuildPlugin => {\n // All Node.js-heavy initialization (getConfiguration, getAlias, …) is deferred\n // into setup() so it runs in esbuild's Node.js context, not at module-evaluation\n // time. @angular/build loads the plugin file through Vite's SSR module runner\n // (ESM) where CommonJS globals like __filename are undefined. Calling\n // getConfiguration() here would trigger: buildSync → worker threads →\n // __filename → ReferenceError, crashing the plugin before setup() ever runs.\n let config: ReturnType<typeof getConfiguration> | null = null;\n let alias: Record<string, string> | null = null;\n\n // Shared across parallel setup() calls (Angular spawns one per bundle context).\n let preparePromise: Promise<void> | null = null;\n let watcherStarted = false;\n // Once any esbuild context (browser or server) detects a production build,\n // suppress the watcher for all contexts so `ng build` can exit cleanly.\n let isBuildMode = false;\n\n return {\n name: 'intlayer',\n\n async setup(build) {\n if (!config) {\n const baseDir =\n build.initialOptions.absWorkingDir ??\n options?.configOptions?.baseDir ??\n process.cwd();\n\n config = getConfiguration({ baseDir, ...options?.configOptions });\n logConfigDetails({ baseDir, ...options?.configOptions });\n\n alias = getAlias({\n configuration: config,\n formatter: (value: string) => join(config!.system.baseDir, value),\n });\n }\n\n const appLogger = getAppLogger(config);\n const nodeEnvDefine =\n build.initialOptions.define?.['process.env.NODE_ENV'];\n\n // Angular's esbuild builder doesn't set `minify` or `process.env.NODE_ENV`\n // on initialOptions — it handles optimisation through its own pipeline.\n // Instead, Angular defines `ngDevMode` as `\"false\"` in production builds.\n const isProduction =\n nodeEnvDefine === '\"production\"' ||\n nodeEnvDefine === \"'production'\" ||\n build.initialOptions.minify === true ||\n build.initialOptions.define?.['ngDevMode'] === 'false';\n\n if (isProduction) {\n isBuildMode = true;\n }\n\n const wrapKey = (key: string) => `process.env.${key}`;\n const wrapValue = (value: string) => `\"${value}\"`;\n\n const envVars: Record<string, string> = {\n // Catch-all so that any `process.env.*` read NOT covered by a specific\n // key below resolves to `undefined` instead of dereferencing a bare\n // `process`, which is not defined in browser bundles and throws\n // `process is not defined`. esbuild resolves the most specific define\n // first, so the keys below keep their tree-shaking effect.\n 'process.env': '{}',\n [wrapKey('INTLAYER')]: wrapValue('true'),\n [wrapKey('NODE_ENV')]: wrapValue(\n isProduction ? 'production' : 'development'\n ),\n // Tree shaking flags derived from the config (routing / storage /\n // editor). Emitted in every mode so behaviour is consistent in dev.\n ...getConfigEnvVars(config, wrapKey, wrapValue),\n };\n\n // Dictionaries must exist on disk before the tree-shaking flags below\n // are derived from them: on a clean checkout (CI, Vercel…) nothing is\n // generated yet, so reading them first reports every node type as\n // unused and strips the translation plugin from the production bundle.\n if (!preparePromise) {\n preparePromise = prepareIntlayer(config, {\n clean: isProduction,\n cacheTimeoutMs: isProduction ? 1000 * 30 : 1000 * 60 * 60,\n env: isProduction ? 'prod' : 'dev',\n });\n }\n\n await preparePromise;\n\n if (isProduction) {\n const dictionaries = getDictionaries(config);\n if (Object.keys(dictionaries).length === 0) {\n appLogger('No dictionaries found. Please check your configuration.', {\n isVerbose: true,\n });\n }\n\n const unusedNodeTypes = await getUnusedNodeTypesAsync(dictionaries);\n Object.assign(\n envVars,\n // Tree shaking based on unused node types\n formatNodeTypeToEnvVar(unusedNodeTypes, wrapKey, wrapValue),\n // Tree shaking the dictionary selector logic\n // (collections / variants)\n formatDictionarySelectorEnvVar(\n getHasDictionarySelector(dictionaries),\n wrapKey,\n wrapValue\n )\n );\n }\n\n // Existing defines (Angular's own, or the user's angular.json `define`\n // block) take precedence over the Intlayer ones.\n build.initialOptions.define = {\n ...envVars,\n ...(build.initialOptions.define ?? {}),\n };\n\n build.initialOptions.alias = {\n ...alias,\n ...(build.initialOptions.alias ?? {}),\n };\n\n for (const [from, to] of Object.entries(alias!)) {\n const escapedFrom = from.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({\n path: to,\n }));\n }\n\n // Angular's dev server marks every import that resolves under\n // `node_modules` as external so Vite can pre-bundle it. Vite's\n // pre-bundler runs without this plugin, so the aliases above never apply\n // there and the real `@intlayer/config/built` — a Node config loader —\n // ends up in the browser. Angular's externalising plugin is registered\n // ahead of this one and only lets a resolution through when the path it\n // gets back is outside `node_modules`; so in that mode an Intlayer\n // package resolves to a re-export shim in its own namespace, whose\n // relative import of the real file the pipeline then bundles as usual.\n // Whether the pipeline externalises packages is probed once, at the\n // first build, so production builds keep the bundler's own resolution.\n let externalizesPackages: boolean | undefined;\n\n build.onResolve({ filter: INTLAYER_PACKAGE_FILTER }, (args) => {\n if (!externalizesPackages || !args.resolveDir) return null;\n\n const importCondition = args.kind.startsWith('require')\n ? 'require'\n : 'import';\n const resolved = resolvePackageExport(args.path, args.resolveDir, [\n 'browser',\n 'module',\n importCondition,\n ]);\n\n if (!resolved) return null;\n\n return {\n // Neither a `node_modules` segment nor a script extension, which the\n // externalising plugin and Angular's own JS loader key on. Ends with\n // the specifier so a lazy chunk is named after it, and starts with\n // the encoded directory so two copies of a package stay distinct.\n path: `${encodeURIComponent(dirname(resolved.path))}/${args.path}`,\n namespace: INTLAYER_PACKAGE_NAMESPACE,\n pluginData: { realPath: resolved.path },\n sideEffects: resolved.sideEffects,\n };\n });\n\n build.onLoad(\n { filter: /.*/, namespace: INTLAYER_PACKAGE_NAMESPACE },\n async (args) => {\n const { realPath } = args.pluginData as { realPath: string };\n const source = await readFile(realPath, 'utf-8');\n const specifier = JSON.stringify(`./${basename(realPath)}`);\n\n const contents = [\n `export * from ${specifier};`,\n DEFAULT_EXPORT_PATTERN.test(source) &&\n `export { default } from ${specifier};`,\n ]\n .filter(Boolean)\n .join('\\n');\n\n return { contents, loader: 'js', resolveDir: dirname(realPath) };\n }\n );\n\n // Dictionaries load with the chunk that needs them rather than being\n // fetched once that chunk renders: the entry point starts the browsing\n // locale's load as it evaluates, so a lazily loaded route requests its\n // content on `import()` instead of on first render. Without it every\n // dictionary read renders an empty placeholder first and fills in a tick\n // later.\n //\n // Not gated on the configured `importMode`: a `.content` file can set\n // `importMode: 'dynamic'` on a single dictionary under a `static` or\n // `fetch` global mode, and that dictionary needs the preload just the\n // same. Only entry points the optimizer imported are ever loaded, so the\n // path check below is the accurate gate.\n if (config.build.dictionariesPreload) {\n const dynamicDictionariesDir = normalizePath(\n config.system.dynamicDictionariesDir\n );\n\n build.onLoad(\n { filter: createDynamicEntryFilter(dynamicDictionariesDir) },\n async ({ path }) => {\n const posixPath = normalizePath(path);\n if (!posixPath.startsWith(`${dynamicDictionariesDir}/`))\n return null;\n\n const code = await readFile(path, 'utf-8');\n const result = addDynamicEntryPreload(code, preloadModuleId);\n\n if (result.skipped) return null;\n\n return { contents: result.code, loader: 'js' };\n }\n );\n }\n\n build.onStart(async () => {\n // `@angular/core` is always installed and never worth excluding from\n // pre-bundling, so its fate tells whether packages get externalised.\n if (externalizesPackages === undefined) {\n externalizesPackages = (\n await build.resolve('@angular/core', {\n kind: 'import-statement',\n resolveDir: config!.system.baseDir,\n })\n ).external;\n\n if (externalizesPackages) {\n warnAboutHiddenTypesDirectory(config!, appLogger);\n }\n }\n\n // Determine whether the watcher should run:\n // 1. Explicit option from the caller takes precedence\n // 2. If any esbuild context detected a production build, skip\n // 3. esbuild's own watch mode is a positive signal\n const shouldWatch = options?.watch ?? !isBuildMode;\n\n if (shouldWatch && !watcherStarted) {\n watcherStarted = true;\n\n await watch({ configuration: config! });\n }\n });\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,MAAM,sBAAkBA,0CACtBC,+DAAuBC,wEAA6B,CAAC,CACvD;;AAGA,MAAM,0BACJ;;AAGF,MAAM,6BAA6B;;AAGnC,MAAM,yBACJ;;;;;;;AAmGF,MAAM,iCACJ,eACA,cACG;CACH,MAAM,EAAE,SAAS,UAAU,0BAA0B,cAAc;CAEnE,MAAM,oBAAoB,CACxB,mBAAG,IAAI,IAAI,CAAC,UAAU,qBAAqB,CAAC,CAC9C,CAAC,CAAC,QAAQ,cAAcC,oDAAoB,SAAS,SAAS,CAAC;CAE/D,IAAI,kBAAkB,WAAW,GAAG;CAEpC,UACE;EACE,yCAAyC,kBAAkB,KAAK,kBAAcC,oBAAS,SAAS,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;EACvH;EACA;CACF,CAAC,CAAC,KAAK,GAAG,GACV,EAAE,OAAO,OAAO,CAClB;AACF;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,yBACX,YACkB;CAOlB,IAAI,SAAqD;CACzD,IAAI,QAAuC;CAG3C,IAAI,iBAAuC;CAC3C,IAAI,iBAAiB;CAGrB,IAAI,cAAc;CAElB,OAAO;EACL,MAAM;EAEN,MAAM,MAAM,OAAO;GACjB,IAAI,CAAC,QAAQ;IACX,MAAM,UACJ,MAAM,eAAe,iBACrB,SAAS,eAAe,WACxB,QAAQ,IAAI;IAEd,aAASC,wCAAiB;KAAE;KAAS,GAAG,SAAS;IAAc,CAAC;IAChE,2CAAiB;KAAE;KAAS,GAAG,SAAS;IAAc,CAAC;IAEvD,YAAQC,iCAAS;KACf,eAAe;KACf,YAAY,cAAkBC,gBAAK,OAAQ,OAAO,SAAS,KAAK;IAClE,CAAC;GACH;GAEA,MAAM,gBAAYC,sCAAa,MAAM;GACrC,MAAM,gBACJ,MAAM,eAAe,SAAS;GAKhC,MAAM,eACJ,kBAAkB,oBAClB,kBAAkB,kBAClB,MAAM,eAAe,WAAW,QAChC,MAAM,eAAe,SAAS,iBAAiB;GAEjD,IAAI,cACF,cAAc;GAGhB,MAAM,WAAW,QAAgB,eAAe;GAChD,MAAM,aAAa,UAAkB,IAAI,MAAM;GAE/C,MAAM,UAAkC;IAMtC,eAAe;KACd,QAAQ,UAAU,IAAI,UAAU,MAAM;KACtC,QAAQ,UAAU,IAAI,UACrB,eAAe,eAAe,aAChC;IAGA,OAAGC,2CAAiB,QAAQ,SAAS,SAAS;GAChD;GAMA,IAAI,CAAC,gBACH,qBAAiBC,wCAAgB,QAAQ;IACvC,OAAO;IACP,gBAAgB,eAAe,MAAY;IAC3C,KAAK,eAAe,SAAS;GAC/B,CAAC;GAGH,MAAM;GAEN,IAAI,cAAc;IAChB,MAAM,mBAAeC,8CAAgB,MAAM;IAC3C,IAAI,OAAO,KAAK,YAAY,CAAC,CAAC,WAAW,GACvC,UAAU,2DAA2D,EACnE,WAAW,KACb,CAAC;IAGH,MAAM,kBAAkB,UAAMC,gDAAwB,YAAY;IAClE,OAAO,OACL,aAEAC,iDAAuB,iBAAiB,SAAS,SAAS,OAG1DC,6DACEC,iDAAyB,YAAY,GACrC,SACA,SACF,CACF;GACF;GAIA,MAAM,eAAe,SAAS;IAC5B,GAAG;IACH,GAAI,MAAM,eAAe,UAAU,CAAC;GACtC;GAEA,MAAM,eAAe,QAAQ;IAC3B,GAAG;IACH,GAAI,MAAM,eAAe,SAAS,CAAC;GACrC;GAEA,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,KAAM,GAAG;IAC/C,MAAM,cAAc,KAAK,QAAQ,uBAAuB,MAAM;IAE9D,MAAM,UAAU,EAAE,QAAQ,IAAI,OAAO,IAAI,YAAY,EAAE,EAAE,UAAU,EACjE,MAAM,GACR,EAAE;GACJ;GAaA,IAAI;GAEJ,MAAM,UAAU,EAAE,QAAQ,wBAAwB,IAAI,SAAS;IAC7D,IAAI,CAAC,wBAAwB,CAAC,KAAK,YAAY,OAAO;IAEtD,MAAM,kBAAkB,KAAK,KAAK,WAAW,SAAS,IAClD,YACA;IACJ,MAAM,WAAWC,0DAAqB,KAAK,MAAM,KAAK,YAAY;KAChE;KACA;KACA;IACF,CAAC;IAED,IAAI,CAAC,UAAU,OAAO;IAEtB,OAAO;KAKL,MAAM,GAAG,uBAAmBC,mBAAQ,SAAS,IAAI,CAAC,EAAE,GAAG,KAAK;KAC5D,WAAW;KACX,YAAY,EAAE,UAAU,SAAS,KAAK;KACtC,aAAa,SAAS;IACxB;GACF,CAAC;GAED,MAAM,OACJ;IAAE,QAAQ;IAAM,WAAW;GAA2B,GACtD,OAAO,SAAS;IACd,MAAM,EAAE,aAAa,KAAK;IAC1B,MAAM,SAAS,UAAMC,2BAAS,UAAU,OAAO;IAC/C,MAAM,YAAY,KAAK,UAAU,SAAKC,oBAAS,QAAQ,GAAG;IAU1D,OAAO;KAAE,UARQ,CACf,iBAAiB,UAAU,IAC3B,uBAAuB,KAAK,MAAM,KAChC,2BAA2B,UAAU,EACzC,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,IAEQ;KAAG,QAAQ;KAAM,gBAAYF,mBAAQ,QAAQ;IAAE;GACjE,CACF;GAcA,IAAI,OAAO,MAAM,qBAAqB;IACpC,MAAM,6BAAyBjB,sCAC7B,OAAO,OAAO,sBAChB;IAEA,MAAM,OACJ,EAAE,YAAQoB,6DAAyB,sBAAsB,EAAE,GAC3D,OAAO,EAAE,WAAW;KAElB,IAAI,KADcpB,sCAAc,IACnB,CAAC,CAAC,WAAW,GAAG,uBAAuB,EAAE,GACpD,OAAO;KAET,MAAM,OAAO,UAAMkB,2BAAS,MAAM,OAAO;KACzC,MAAM,aAASG,2DAAuB,MAAM,eAAe;KAE3D,IAAI,OAAO,SAAS,OAAO;KAE3B,OAAO;MAAE,UAAU,OAAO;MAAM,QAAQ;KAAK;IAC/C,CACF;GACF;GAEA,MAAM,QAAQ,YAAY;IAGxB,IAAI,yBAAyB,QAAW;KACtC,wBACE,MAAM,MAAM,QAAQ,iBAAiB;MACnC,MAAM;MACN,YAAY,OAAQ,OAAO;KAC7B,CAAC,EAAC,CACF;KAEF,IAAI,sBACF,8BAA8B,QAAS,SAAS;IAEpD;IAQA,KAFoB,SAAS,SAAS,CAAC,gBAEpB,CAAC,gBAAgB;KAClC,iBAAiB;KAEjB,UAAMC,gCAAM,EAAE,eAAe,OAAQ,CAAC;IACxC;GACF,CAAC;EACH;CACF;AACF"}
|
|
@@ -109,6 +109,12 @@ const intlayerEsbuildPlugin = (options) => {
|
|
|
109
109
|
[wrapKey("NODE_ENV")]: wrapValue(isProduction ? "production" : "development"),
|
|
110
110
|
...getConfigEnvVars(config, wrapKey, wrapValue)
|
|
111
111
|
};
|
|
112
|
+
if (!preparePromise) preparePromise = prepareIntlayer(config, {
|
|
113
|
+
clean: isProduction,
|
|
114
|
+
cacheTimeoutMs: isProduction ? 3e4 : 36e5,
|
|
115
|
+
env: isProduction ? "prod" : "dev"
|
|
116
|
+
});
|
|
117
|
+
await preparePromise;
|
|
112
118
|
if (isProduction) {
|
|
113
119
|
const dictionaries = getDictionaries(config);
|
|
114
120
|
if (Object.keys(dictionaries).length === 0) appLogger("No dictionaries found. Please check your configuration.", { isVerbose: true });
|
|
@@ -170,12 +176,6 @@ const intlayerEsbuildPlugin = (options) => {
|
|
|
170
176
|
};
|
|
171
177
|
});
|
|
172
178
|
}
|
|
173
|
-
if (!preparePromise) preparePromise = prepareIntlayer(config, {
|
|
174
|
-
clean: isProduction,
|
|
175
|
-
cacheTimeoutMs: isProduction ? 3e4 : 36e5,
|
|
176
|
-
env: isProduction ? "prod" : "dev"
|
|
177
|
-
});
|
|
178
|
-
await preparePromise;
|
|
179
179
|
build.onStart(async () => {
|
|
180
180
|
if (externalizesPackages === void 0) {
|
|
181
181
|
externalizesPackages = (await build.resolve("@angular/core", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.mjs","names":[],"sources":["../../../src/esbuild/plugin.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { basename, dirname, join, relative } from 'node:path';\nimport {\n addDynamicEntryPreload,\n createDynamicEntryFilter,\n resolvePreloadModuleId,\n} from '@intlayer/config/dictionaryPreload';\nimport {\n formatDictionarySelectorEnvVar,\n formatNodeTypeToEnvVar,\n getConfigEnvVars,\n} from '@intlayer/config/envVars';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n getAlias,\n getHasDictionarySelector,\n getUnusedNodeTypesAsync,\n normalizePath,\n} from '@intlayer/config/utils';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { watch } from '@intlayer/engine/watcher';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { isInHiddenDirectory } from './hiddenDirectory';\nimport { resolvePackageExport } from './resolvePackageExport';\n\n/**\n * Absolute id of the locale resolver the injected preamble imports.\n *\n * Resolved from this package, which declares `@intlayer/core` as a dependency,\n * rather than left bare in the emitted source: the importer is a generated\n * entry point under the application's `.intlayer` directory, and an application\n * only depends on `intlayer` and its framework binding, so the bare specifier\n * would resolve from a tree that need not contain the package at all.\n *\n * Always built from `import.meta.url`: the bundler shims it to `__filename` in\n * the CommonJS output, whereas a `typeof require` guard is unreliable here —\n * the ESM output rewrites `require` into an always-defined proxy that has no\n * `resolve` method.\n */\nconst preloadModuleId = normalizePath(\n resolvePreloadModuleId(createRequire(import.meta.url))\n);\n\n/** Bare specifiers of the packages this plugin keeps inside its own build. */\nconst INTLAYER_PACKAGE_FILTER =\n /^(?:intlayer|angular-intlayer|@intlayer\\/[^/]+)(?:\\/|$)/;\n\n/** Namespace of the re-export shims standing in for externalised packages. */\nconst INTLAYER_PACKAGE_NAMESPACE = 'intlayer-package';\n\n/** Matches a module that has a default export, on unminified sources. */\nconst DEFAULT_EXPORT_PATTERN =\n /\\bexport\\s+default\\b|\\bas\\s+default\\b|\\{\\s*default\\s*[,}]/;\n\n// Minimal subset of the esbuild Plugin interface to avoid a hard dependency on\n// the `esbuild` package for type resolution. The shape is compatible with\n// esbuild >=0.17, `@angular-builders/custom-esbuild`, and NX esbuild builders.\nexport type EsbuildResolveArgs = {\n path: string;\n importer: string;\n namespace: string;\n resolveDir: string;\n kind: string;\n pluginData?: unknown;\n};\n\nexport type EsbuildResolveResult = {\n path?: string;\n namespace?: string;\n external?: boolean;\n sideEffects?: boolean;\n pluginData?: unknown;\n errors?: unknown[];\n warnings?: unknown[];\n};\n\nexport type EsbuildLoadArgs = {\n path: string;\n namespace: string;\n pluginData?: unknown;\n};\n\nexport type EsbuildLoadResult = {\n contents: string;\n loader?: string;\n /** Directory relative imports of `contents` resolve from. */\n resolveDir?: string;\n};\n\nexport interface EsbuildPluginBuild {\n initialOptions: {\n alias?: Record<string, string>;\n define?: Record<string, string>;\n minify?: boolean;\n watch?: unknown;\n /** Absolute working directory of the esbuild context (set by Angular's builder). */\n absWorkingDir?: string;\n };\n onStart(callback: () => void | Promise<void>): void;\n /** Intercept module resolution — works even for imports inside node_modules. */\n onResolve(\n options: { filter: RegExp; namespace?: string },\n callback: (\n args: EsbuildResolveArgs\n ) =>\n | EsbuildResolveResult\n | null\n | undefined\n | Promise<EsbuildResolveResult | null | undefined>\n ): void;\n /** Run the remaining resolution pipeline (other plugins, then esbuild). */\n resolve(\n path: string,\n options: Partial<Omit<EsbuildResolveArgs, 'path'>>\n ): Promise<EsbuildResolveResult & { path: string; external: boolean }>;\n /** Intercept module contents, so a resolved file can be rewritten. */\n onLoad(\n options: { filter: RegExp; namespace?: string },\n callback: (\n args: EsbuildLoadArgs\n ) =>\n | EsbuildLoadResult\n | null\n | undefined\n | Promise<EsbuildLoadResult | null | undefined>\n ): void;\n}\n\nexport interface EsbuildPlugin {\n name: string;\n setup(build: EsbuildPluginBuild): void | Promise<void>;\n}\n\nexport type IntlayerEsbuildPluginOptions = {\n configOptions?: GetConfigurationOptions;\n /**\n * Whether to start the Intlayer file watcher for dictionary regeneration.\n * - `true`: always start the watcher (useful for `ng serve`)\n * - `false`: never start the watcher (useful for `ng build`)\n * - `undefined` (default): auto-detect based on the build context\n * (skips the watcher when a production build is detected)\n */\n watch?: boolean;\n};\n\n/**\n * The dev server's file watcher skips dot-directories, so type declarations\n * generated there are never re-read: a key added to a dictionary stays unknown\n * to template type-checking until `ng serve` restarts. Nothing in the plugin\n * can reach that cache, so the fix is to generate the types elsewhere.\n */\nconst warnAboutHiddenTypesDirectory = (\n configuration: IntlayerConfig,\n appLogger: ReturnType<typeof getAppLogger>\n) => {\n const { baseDir, typesDir, moduleAugmentationDir } = configuration.system;\n\n const hiddenDirectories = [\n ...new Set([typesDir, moduleAugmentationDir]),\n ].filter((directory) => isInHiddenDirectory(baseDir, directory));\n\n if (hiddenDirectories.length === 0) return;\n\n appLogger(\n [\n `Type declarations are generated under ${hiddenDirectories.map((directory) => relative(baseDir, directory)).join(', ')}.`,\n \"The Angular dev server does not watch dot-directories, so keys added to a dictionary stay unknown to template type-checking until 'ng serve' restarts.\",\n \"Set 'system.typesDir' and 'system.moduleAugmentationDir' to a directory outside any dot-directory (e.g. 'intlayer-types') and point the tsconfig 'include' at it.\",\n ].join(' '),\n { level: 'warn' }\n );\n};\n\n/**\n * esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.\n *\n * Handles:\n * 1. Injecting `alias` entries so `@intlayer/dictionaries-entry` etc. resolve to\n * the generated files under `.intlayer/`.\n * 2. Defining `process.env.*` tree-shaking constants for production builds.\n * 3. Running `prepareIntlayer` (dictionary generation) before the first build.\n * 4. Starting the chokidar file-watcher in dev / serve mode.\n *\n * Compatible with:\n * - `@angular-builders/custom-esbuild` (`application` or `browser-esbuild` builder)\n * - NX `@nx/angular:browser-esbuild`\n * - Any raw esbuild setup that accepts the standard `Plugin` interface\n *\n * @example\n * ```ts\n * // esbuild.plugins.ts (referenced from angular.json \"plugins\" option)\n * import { intlayerEsbuildPlugin } from 'angular-intlayer/esbuild';\n * export default [intlayerEsbuildPlugin()];\n * ```\n */\nexport const intlayerEsbuildPlugin = (\n options?: IntlayerEsbuildPluginOptions\n): EsbuildPlugin => {\n // All Node.js-heavy initialization (getConfiguration, getAlias, …) is deferred\n // into setup() so it runs in esbuild's Node.js context, not at module-evaluation\n // time. @angular/build loads the plugin file through Vite's SSR module runner\n // (ESM) where CommonJS globals like __filename are undefined. Calling\n // getConfiguration() here would trigger: buildSync → worker threads →\n // __filename → ReferenceError, crashing the plugin before setup() ever runs.\n let config: ReturnType<typeof getConfiguration> | null = null;\n let alias: Record<string, string> | null = null;\n\n // Shared across parallel setup() calls (Angular spawns one per bundle context).\n let preparePromise: Promise<void> | null = null;\n let watcherStarted = false;\n // Once any esbuild context (browser or server) detects a production build,\n // suppress the watcher for all contexts so `ng build` can exit cleanly.\n let isBuildMode = false;\n\n return {\n name: 'intlayer',\n\n async setup(build) {\n if (!config) {\n const baseDir =\n build.initialOptions.absWorkingDir ??\n options?.configOptions?.baseDir ??\n process.cwd();\n\n config = getConfiguration({ baseDir, ...options?.configOptions });\n logConfigDetails({ baseDir, ...options?.configOptions });\n\n alias = getAlias({\n configuration: config,\n formatter: (value: string) => join(config!.system.baseDir, value),\n });\n }\n\n const appLogger = getAppLogger(config);\n const nodeEnvDefine =\n build.initialOptions.define?.['process.env.NODE_ENV'];\n\n // Angular's esbuild builder doesn't set `minify` or `process.env.NODE_ENV`\n // on initialOptions — it handles optimisation through its own pipeline.\n // Instead, Angular defines `ngDevMode` as `\"false\"` in production builds.\n const isProduction =\n nodeEnvDefine === '\"production\"' ||\n nodeEnvDefine === \"'production'\" ||\n build.initialOptions.minify === true ||\n build.initialOptions.define?.['ngDevMode'] === 'false';\n\n if (isProduction) {\n isBuildMode = true;\n }\n\n const wrapKey = (key: string) => `process.env.${key}`;\n const wrapValue = (value: string) => `\"${value}\"`;\n\n const envVars: Record<string, string> = {\n // Catch-all so that any `process.env.*` read NOT covered by a specific\n // key below resolves to `undefined` instead of dereferencing a bare\n // `process`, which is not defined in browser bundles and throws\n // `process is not defined`. esbuild resolves the most specific define\n // first, so the keys below keep their tree-shaking effect.\n 'process.env': '{}',\n [wrapKey('INTLAYER')]: wrapValue('true'),\n [wrapKey('NODE_ENV')]: wrapValue(\n isProduction ? 'production' : 'development'\n ),\n // Tree shaking flags derived from the config (routing / storage /\n // editor). Emitted in every mode so behaviour is consistent in dev.\n ...getConfigEnvVars(config, wrapKey, wrapValue),\n };\n\n if (isProduction) {\n const dictionaries = getDictionaries(config);\n if (Object.keys(dictionaries).length === 0) {\n appLogger('No dictionaries found. Please check your configuration.', {\n isVerbose: true,\n });\n }\n\n const unusedNodeTypes = await getUnusedNodeTypesAsync(dictionaries);\n Object.assign(\n envVars,\n // Tree shaking based on unused node types\n formatNodeTypeToEnvVar(unusedNodeTypes, wrapKey, wrapValue),\n // Tree shaking the dictionary selector logic\n // (collections / variants)\n formatDictionarySelectorEnvVar(\n getHasDictionarySelector(dictionaries),\n wrapKey,\n wrapValue\n )\n );\n }\n\n // Existing defines (Angular's own, or the user's angular.json `define`\n // block) take precedence over the Intlayer ones.\n build.initialOptions.define = {\n ...envVars,\n ...(build.initialOptions.define ?? {}),\n };\n\n build.initialOptions.alias = {\n ...alias,\n ...(build.initialOptions.alias ?? {}),\n };\n\n for (const [from, to] of Object.entries(alias!)) {\n const escapedFrom = from.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({\n path: to,\n }));\n }\n\n // Angular's dev server marks every import that resolves under\n // `node_modules` as external so Vite can pre-bundle it. Vite's\n // pre-bundler runs without this plugin, so the aliases above never apply\n // there and the real `@intlayer/config/built` — a Node config loader —\n // ends up in the browser. Angular's externalising plugin is registered\n // ahead of this one and only lets a resolution through when the path it\n // gets back is outside `node_modules`; so in that mode an Intlayer\n // package resolves to a re-export shim in its own namespace, whose\n // relative import of the real file the pipeline then bundles as usual.\n // Whether the pipeline externalises packages is probed once, at the\n // first build, so production builds keep the bundler's own resolution.\n let externalizesPackages: boolean | undefined;\n\n build.onResolve({ filter: INTLAYER_PACKAGE_FILTER }, (args) => {\n if (!externalizesPackages || !args.resolveDir) return null;\n\n const importCondition = args.kind.startsWith('require')\n ? 'require'\n : 'import';\n const resolved = resolvePackageExport(args.path, args.resolveDir, [\n 'browser',\n 'module',\n importCondition,\n ]);\n\n if (!resolved) return null;\n\n return {\n // Neither a `node_modules` segment nor a script extension, which the\n // externalising plugin and Angular's own JS loader key on. Ends with\n // the specifier so a lazy chunk is named after it, and starts with\n // the encoded directory so two copies of a package stay distinct.\n path: `${encodeURIComponent(dirname(resolved.path))}/${args.path}`,\n namespace: INTLAYER_PACKAGE_NAMESPACE,\n pluginData: { realPath: resolved.path },\n sideEffects: resolved.sideEffects,\n };\n });\n\n build.onLoad(\n { filter: /.*/, namespace: INTLAYER_PACKAGE_NAMESPACE },\n async (args) => {\n const { realPath } = args.pluginData as { realPath: string };\n const source = await readFile(realPath, 'utf-8');\n const specifier = JSON.stringify(`./${basename(realPath)}`);\n\n const contents = [\n `export * from ${specifier};`,\n DEFAULT_EXPORT_PATTERN.test(source) &&\n `export { default } from ${specifier};`,\n ]\n .filter(Boolean)\n .join('\\n');\n\n return { contents, loader: 'js', resolveDir: dirname(realPath) };\n }\n );\n\n // Dictionaries load with the chunk that needs them rather than being\n // fetched once that chunk renders: the entry point starts the browsing\n // locale's load as it evaluates, so a lazily loaded route requests its\n // content on `import()` instead of on first render. Without it every\n // dictionary read renders an empty placeholder first and fills in a tick\n // later.\n //\n // Not gated on the configured `importMode`: a `.content` file can set\n // `importMode: 'dynamic'` on a single dictionary under a `static` or\n // `fetch` global mode, and that dictionary needs the preload just the\n // same. Only entry points the optimizer imported are ever loaded, so the\n // path check below is the accurate gate.\n if (config.build.dictionariesPreload) {\n const dynamicDictionariesDir = normalizePath(\n config.system.dynamicDictionariesDir\n );\n\n build.onLoad(\n { filter: createDynamicEntryFilter(dynamicDictionariesDir) },\n async ({ path }) => {\n const posixPath = normalizePath(path);\n if (!posixPath.startsWith(`${dynamicDictionariesDir}/`))\n return null;\n\n const code = await readFile(path, 'utf-8');\n const result = addDynamicEntryPreload(code, preloadModuleId);\n\n if (result.skipped) return null;\n\n return { contents: result.code, loader: 'js' };\n }\n );\n }\n\n if (!preparePromise) {\n preparePromise = prepareIntlayer(config, {\n clean: isProduction,\n cacheTimeoutMs: isProduction ? 1000 * 30 : 1000 * 60 * 60,\n env: isProduction ? 'prod' : 'dev',\n });\n }\n\n await preparePromise;\n\n build.onStart(async () => {\n // `@angular/core` is always installed and never worth excluding from\n // pre-bundling, so its fate tells whether packages get externalised.\n if (externalizesPackages === undefined) {\n externalizesPackages = (\n await build.resolve('@angular/core', {\n kind: 'import-statement',\n resolveDir: config!.system.baseDir,\n })\n ).external;\n\n if (externalizesPackages) {\n warnAboutHiddenTypesDirectory(config!, appLogger);\n }\n }\n\n // Determine whether the watcher should run:\n // 1. Explicit option from the caller takes precedence\n // 2. If any esbuild context detected a production build, skip\n // 3. esbuild's own watch mode is a positive signal\n const shouldWatch = options?.watch ?? !isBuildMode;\n\n if (shouldWatch && !watcherStarted) {\n watcherStarted = true;\n\n await watch({ configuration: config! });\n }\n });\n },\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.mjs","names":[],"sources":["../../../src/esbuild/plugin.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { basename, dirname, join, relative } from 'node:path';\nimport {\n addDynamicEntryPreload,\n createDynamicEntryFilter,\n resolvePreloadModuleId,\n} from '@intlayer/config/dictionaryPreload';\nimport {\n formatDictionarySelectorEnvVar,\n formatNodeTypeToEnvVar,\n getConfigEnvVars,\n} from '@intlayer/config/envVars';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n getAlias,\n getHasDictionarySelector,\n getUnusedNodeTypesAsync,\n normalizePath,\n} from '@intlayer/config/utils';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { watch } from '@intlayer/engine/watcher';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { isInHiddenDirectory } from './hiddenDirectory';\nimport { resolvePackageExport } from './resolvePackageExport';\n\n/**\n * Absolute id of the locale resolver the injected preamble imports.\n *\n * Resolved from this package, which declares `@intlayer/core` as a dependency,\n * rather than left bare in the emitted source: the importer is a generated\n * entry point under the application's `.intlayer` directory, and an application\n * only depends on `intlayer` and its framework binding, so the bare specifier\n * would resolve from a tree that need not contain the package at all.\n *\n * Always built from `import.meta.url`: the bundler shims it to `__filename` in\n * the CommonJS output, whereas a `typeof require` guard is unreliable here —\n * the ESM output rewrites `require` into an always-defined proxy that has no\n * `resolve` method.\n */\nconst preloadModuleId = normalizePath(\n resolvePreloadModuleId(createRequire(import.meta.url))\n);\n\n/** Bare specifiers of the packages this plugin keeps inside its own build. */\nconst INTLAYER_PACKAGE_FILTER =\n /^(?:intlayer|angular-intlayer|@intlayer\\/[^/]+)(?:\\/|$)/;\n\n/** Namespace of the re-export shims standing in for externalised packages. */\nconst INTLAYER_PACKAGE_NAMESPACE = 'intlayer-package';\n\n/** Matches a module that has a default export, on unminified sources. */\nconst DEFAULT_EXPORT_PATTERN =\n /\\bexport\\s+default\\b|\\bas\\s+default\\b|\\{\\s*default\\s*[,}]/;\n\n// Minimal subset of the esbuild Plugin interface to avoid a hard dependency on\n// the `esbuild` package for type resolution. The shape is compatible with\n// esbuild >=0.17, `@angular-builders/custom-esbuild`, and NX esbuild builders.\nexport type EsbuildResolveArgs = {\n path: string;\n importer: string;\n namespace: string;\n resolveDir: string;\n kind: string;\n pluginData?: unknown;\n};\n\nexport type EsbuildResolveResult = {\n path?: string;\n namespace?: string;\n external?: boolean;\n sideEffects?: boolean;\n pluginData?: unknown;\n errors?: unknown[];\n warnings?: unknown[];\n};\n\nexport type EsbuildLoadArgs = {\n path: string;\n namespace: string;\n pluginData?: unknown;\n};\n\nexport type EsbuildLoadResult = {\n contents: string;\n loader?: string;\n /** Directory relative imports of `contents` resolve from. */\n resolveDir?: string;\n};\n\nexport interface EsbuildPluginBuild {\n initialOptions: {\n alias?: Record<string, string>;\n define?: Record<string, string>;\n minify?: boolean;\n watch?: unknown;\n /** Absolute working directory of the esbuild context (set by Angular's builder). */\n absWorkingDir?: string;\n };\n onStart(callback: () => void | Promise<void>): void;\n /** Intercept module resolution — works even for imports inside node_modules. */\n onResolve(\n options: { filter: RegExp; namespace?: string },\n callback: (\n args: EsbuildResolveArgs\n ) =>\n | EsbuildResolveResult\n | null\n | undefined\n | Promise<EsbuildResolveResult | null | undefined>\n ): void;\n /** Run the remaining resolution pipeline (other plugins, then esbuild). */\n resolve(\n path: string,\n options: Partial<Omit<EsbuildResolveArgs, 'path'>>\n ): Promise<EsbuildResolveResult & { path: string; external: boolean }>;\n /** Intercept module contents, so a resolved file can be rewritten. */\n onLoad(\n options: { filter: RegExp; namespace?: string },\n callback: (\n args: EsbuildLoadArgs\n ) =>\n | EsbuildLoadResult\n | null\n | undefined\n | Promise<EsbuildLoadResult | null | undefined>\n ): void;\n}\n\nexport interface EsbuildPlugin {\n name: string;\n setup(build: EsbuildPluginBuild): void | Promise<void>;\n}\n\nexport type IntlayerEsbuildPluginOptions = {\n configOptions?: GetConfigurationOptions;\n /**\n * Whether to start the Intlayer file watcher for dictionary regeneration.\n * - `true`: always start the watcher (useful for `ng serve`)\n * - `false`: never start the watcher (useful for `ng build`)\n * - `undefined` (default): auto-detect based on the build context\n * (skips the watcher when a production build is detected)\n */\n watch?: boolean;\n};\n\n/**\n * The dev server's file watcher skips dot-directories, so type declarations\n * generated there are never re-read: a key added to a dictionary stays unknown\n * to template type-checking until `ng serve` restarts. Nothing in the plugin\n * can reach that cache, so the fix is to generate the types elsewhere.\n */\nconst warnAboutHiddenTypesDirectory = (\n configuration: IntlayerConfig,\n appLogger: ReturnType<typeof getAppLogger>\n) => {\n const { baseDir, typesDir, moduleAugmentationDir } = configuration.system;\n\n const hiddenDirectories = [\n ...new Set([typesDir, moduleAugmentationDir]),\n ].filter((directory) => isInHiddenDirectory(baseDir, directory));\n\n if (hiddenDirectories.length === 0) return;\n\n appLogger(\n [\n `Type declarations are generated under ${hiddenDirectories.map((directory) => relative(baseDir, directory)).join(', ')}.`,\n \"The Angular dev server does not watch dot-directories, so keys added to a dictionary stay unknown to template type-checking until 'ng serve' restarts.\",\n \"Set 'system.typesDir' and 'system.moduleAugmentationDir' to a directory outside any dot-directory (e.g. 'intlayer-types') and point the tsconfig 'include' at it.\",\n ].join(' '),\n { level: 'warn' }\n );\n};\n\n/**\n * esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.\n *\n * Handles:\n * 1. Injecting `alias` entries so `@intlayer/dictionaries-entry` etc. resolve to\n * the generated files under `.intlayer/`.\n * 2. Defining `process.env.*` tree-shaking constants for production builds.\n * 3. Running `prepareIntlayer` (dictionary generation) before the first build.\n * 4. Starting the chokidar file-watcher in dev / serve mode.\n *\n * Compatible with:\n * - `@angular-builders/custom-esbuild` (`application` or `browser-esbuild` builder)\n * - NX `@nx/angular:browser-esbuild`\n * - Any raw esbuild setup that accepts the standard `Plugin` interface\n *\n * @example\n * ```ts\n * // esbuild.plugins.ts (referenced from angular.json \"plugins\" option)\n * import { intlayerEsbuildPlugin } from 'angular-intlayer/esbuild';\n * export default [intlayerEsbuildPlugin()];\n * ```\n */\nexport const intlayerEsbuildPlugin = (\n options?: IntlayerEsbuildPluginOptions\n): EsbuildPlugin => {\n // All Node.js-heavy initialization (getConfiguration, getAlias, …) is deferred\n // into setup() so it runs in esbuild's Node.js context, not at module-evaluation\n // time. @angular/build loads the plugin file through Vite's SSR module runner\n // (ESM) where CommonJS globals like __filename are undefined. Calling\n // getConfiguration() here would trigger: buildSync → worker threads →\n // __filename → ReferenceError, crashing the plugin before setup() ever runs.\n let config: ReturnType<typeof getConfiguration> | null = null;\n let alias: Record<string, string> | null = null;\n\n // Shared across parallel setup() calls (Angular spawns one per bundle context).\n let preparePromise: Promise<void> | null = null;\n let watcherStarted = false;\n // Once any esbuild context (browser or server) detects a production build,\n // suppress the watcher for all contexts so `ng build` can exit cleanly.\n let isBuildMode = false;\n\n return {\n name: 'intlayer',\n\n async setup(build) {\n if (!config) {\n const baseDir =\n build.initialOptions.absWorkingDir ??\n options?.configOptions?.baseDir ??\n process.cwd();\n\n config = getConfiguration({ baseDir, ...options?.configOptions });\n logConfigDetails({ baseDir, ...options?.configOptions });\n\n alias = getAlias({\n configuration: config,\n formatter: (value: string) => join(config!.system.baseDir, value),\n });\n }\n\n const appLogger = getAppLogger(config);\n const nodeEnvDefine =\n build.initialOptions.define?.['process.env.NODE_ENV'];\n\n // Angular's esbuild builder doesn't set `minify` or `process.env.NODE_ENV`\n // on initialOptions — it handles optimisation through its own pipeline.\n // Instead, Angular defines `ngDevMode` as `\"false\"` in production builds.\n const isProduction =\n nodeEnvDefine === '\"production\"' ||\n nodeEnvDefine === \"'production'\" ||\n build.initialOptions.minify === true ||\n build.initialOptions.define?.['ngDevMode'] === 'false';\n\n if (isProduction) {\n isBuildMode = true;\n }\n\n const wrapKey = (key: string) => `process.env.${key}`;\n const wrapValue = (value: string) => `\"${value}\"`;\n\n const envVars: Record<string, string> = {\n // Catch-all so that any `process.env.*` read NOT covered by a specific\n // key below resolves to `undefined` instead of dereferencing a bare\n // `process`, which is not defined in browser bundles and throws\n // `process is not defined`. esbuild resolves the most specific define\n // first, so the keys below keep their tree-shaking effect.\n 'process.env': '{}',\n [wrapKey('INTLAYER')]: wrapValue('true'),\n [wrapKey('NODE_ENV')]: wrapValue(\n isProduction ? 'production' : 'development'\n ),\n // Tree shaking flags derived from the config (routing / storage /\n // editor). Emitted in every mode so behaviour is consistent in dev.\n ...getConfigEnvVars(config, wrapKey, wrapValue),\n };\n\n // Dictionaries must exist on disk before the tree-shaking flags below\n // are derived from them: on a clean checkout (CI, Vercel…) nothing is\n // generated yet, so reading them first reports every node type as\n // unused and strips the translation plugin from the production bundle.\n if (!preparePromise) {\n preparePromise = prepareIntlayer(config, {\n clean: isProduction,\n cacheTimeoutMs: isProduction ? 1000 * 30 : 1000 * 60 * 60,\n env: isProduction ? 'prod' : 'dev',\n });\n }\n\n await preparePromise;\n\n if (isProduction) {\n const dictionaries = getDictionaries(config);\n if (Object.keys(dictionaries).length === 0) {\n appLogger('No dictionaries found. Please check your configuration.', {\n isVerbose: true,\n });\n }\n\n const unusedNodeTypes = await getUnusedNodeTypesAsync(dictionaries);\n Object.assign(\n envVars,\n // Tree shaking based on unused node types\n formatNodeTypeToEnvVar(unusedNodeTypes, wrapKey, wrapValue),\n // Tree shaking the dictionary selector logic\n // (collections / variants)\n formatDictionarySelectorEnvVar(\n getHasDictionarySelector(dictionaries),\n wrapKey,\n wrapValue\n )\n );\n }\n\n // Existing defines (Angular's own, or the user's angular.json `define`\n // block) take precedence over the Intlayer ones.\n build.initialOptions.define = {\n ...envVars,\n ...(build.initialOptions.define ?? {}),\n };\n\n build.initialOptions.alias = {\n ...alias,\n ...(build.initialOptions.alias ?? {}),\n };\n\n for (const [from, to] of Object.entries(alias!)) {\n const escapedFrom = from.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({\n path: to,\n }));\n }\n\n // Angular's dev server marks every import that resolves under\n // `node_modules` as external so Vite can pre-bundle it. Vite's\n // pre-bundler runs without this plugin, so the aliases above never apply\n // there and the real `@intlayer/config/built` — a Node config loader —\n // ends up in the browser. Angular's externalising plugin is registered\n // ahead of this one and only lets a resolution through when the path it\n // gets back is outside `node_modules`; so in that mode an Intlayer\n // package resolves to a re-export shim in its own namespace, whose\n // relative import of the real file the pipeline then bundles as usual.\n // Whether the pipeline externalises packages is probed once, at the\n // first build, so production builds keep the bundler's own resolution.\n let externalizesPackages: boolean | undefined;\n\n build.onResolve({ filter: INTLAYER_PACKAGE_FILTER }, (args) => {\n if (!externalizesPackages || !args.resolveDir) return null;\n\n const importCondition = args.kind.startsWith('require')\n ? 'require'\n : 'import';\n const resolved = resolvePackageExport(args.path, args.resolveDir, [\n 'browser',\n 'module',\n importCondition,\n ]);\n\n if (!resolved) return null;\n\n return {\n // Neither a `node_modules` segment nor a script extension, which the\n // externalising plugin and Angular's own JS loader key on. Ends with\n // the specifier so a lazy chunk is named after it, and starts with\n // the encoded directory so two copies of a package stay distinct.\n path: `${encodeURIComponent(dirname(resolved.path))}/${args.path}`,\n namespace: INTLAYER_PACKAGE_NAMESPACE,\n pluginData: { realPath: resolved.path },\n sideEffects: resolved.sideEffects,\n };\n });\n\n build.onLoad(\n { filter: /.*/, namespace: INTLAYER_PACKAGE_NAMESPACE },\n async (args) => {\n const { realPath } = args.pluginData as { realPath: string };\n const source = await readFile(realPath, 'utf-8');\n const specifier = JSON.stringify(`./${basename(realPath)}`);\n\n const contents = [\n `export * from ${specifier};`,\n DEFAULT_EXPORT_PATTERN.test(source) &&\n `export { default } from ${specifier};`,\n ]\n .filter(Boolean)\n .join('\\n');\n\n return { contents, loader: 'js', resolveDir: dirname(realPath) };\n }\n );\n\n // Dictionaries load with the chunk that needs them rather than being\n // fetched once that chunk renders: the entry point starts the browsing\n // locale's load as it evaluates, so a lazily loaded route requests its\n // content on `import()` instead of on first render. Without it every\n // dictionary read renders an empty placeholder first and fills in a tick\n // later.\n //\n // Not gated on the configured `importMode`: a `.content` file can set\n // `importMode: 'dynamic'` on a single dictionary under a `static` or\n // `fetch` global mode, and that dictionary needs the preload just the\n // same. Only entry points the optimizer imported are ever loaded, so the\n // path check below is the accurate gate.\n if (config.build.dictionariesPreload) {\n const dynamicDictionariesDir = normalizePath(\n config.system.dynamicDictionariesDir\n );\n\n build.onLoad(\n { filter: createDynamicEntryFilter(dynamicDictionariesDir) },\n async ({ path }) => {\n const posixPath = normalizePath(path);\n if (!posixPath.startsWith(`${dynamicDictionariesDir}/`))\n return null;\n\n const code = await readFile(path, 'utf-8');\n const result = addDynamicEntryPreload(code, preloadModuleId);\n\n if (result.skipped) return null;\n\n return { contents: result.code, loader: 'js' };\n }\n );\n }\n\n build.onStart(async () => {\n // `@angular/core` is always installed and never worth excluding from\n // pre-bundling, so its fate tells whether packages get externalised.\n if (externalizesPackages === undefined) {\n externalizesPackages = (\n await build.resolve('@angular/core', {\n kind: 'import-statement',\n resolveDir: config!.system.baseDir,\n })\n ).external;\n\n if (externalizesPackages) {\n warnAboutHiddenTypesDirectory(config!, appLogger);\n }\n }\n\n // Determine whether the watcher should run:\n // 1. Explicit option from the caller takes precedence\n // 2. If any esbuild context detected a production build, skip\n // 3. esbuild's own watch mode is a positive signal\n const shouldWatch = options?.watch ?? !isBuildMode;\n\n if (shouldWatch && !watcherStarted) {\n watcherStarted = true;\n\n await watch({ configuration: config! });\n }\n });\n },\n };\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "angular-intlayer",
|
|
3
|
-
"version": "9.5.
|
|
3
|
+
"version": "9.5.6",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Easily internationalize i18n your Angular applications with type-safe multilingual content management.",
|
|
6
6
|
"keywords": [
|
|
@@ -120,13 +120,13 @@
|
|
|
120
120
|
"@babel/core": "^8.0.1",
|
|
121
121
|
"@babel/plugin-syntax-import-attributes": "7.29.7",
|
|
122
122
|
"@babel/preset-env": "8.0.2",
|
|
123
|
-
"@intlayer/config": "9.5.
|
|
124
|
-
"@intlayer/core": "9.5.
|
|
125
|
-
"@intlayer/dictionaries-entry": "9.5.
|
|
126
|
-
"@intlayer/editor": "9.5.
|
|
127
|
-
"@intlayer/engine": "9.5.
|
|
128
|
-
"@intlayer/types": "9.5.
|
|
129
|
-
"@intlayer/webpack": "9.5.
|
|
123
|
+
"@intlayer/config": "9.5.6",
|
|
124
|
+
"@intlayer/core": "9.5.6",
|
|
125
|
+
"@intlayer/dictionaries-entry": "9.5.6",
|
|
126
|
+
"@intlayer/editor": "9.5.6",
|
|
127
|
+
"@intlayer/engine": "9.5.6",
|
|
128
|
+
"@intlayer/types": "9.5.6",
|
|
129
|
+
"@intlayer/webpack": "9.5.6",
|
|
130
130
|
"babel-loader": "10.1.1",
|
|
131
131
|
"defu": "6.1.7"
|
|
132
132
|
},
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
}
|
|
157
157
|
},
|
|
158
158
|
"optionalDependencies": {
|
|
159
|
-
"@intlayer/analytics": "9.5.
|
|
159
|
+
"@intlayer/analytics": "9.5.6"
|
|
160
160
|
},
|
|
161
161
|
"engines": {
|
|
162
162
|
"node": ">=14.18"
|