angular-intlayer 9.5.2 → 9.5.4-canary.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.
- package/README.md +9 -9
- package/dist/cjs/analytics/useAnalytics.cjs +1 -1
- package/dist/cjs/client/intlayerToken.cjs +1 -1
- package/dist/cjs/client/useDictionary.cjs +1 -1
- package/dist/cjs/client/useDictionaryAsync.cjs +1 -1
- package/dist/cjs/client/useDictionaryDynamic.cjs +2 -2
- package/dist/cjs/client/useIntlayer.cjs +1 -1
- package/dist/cjs/client/useLocale.cjs +1 -1
- package/dist/cjs/editor/EditorProvider.component.cjs +1 -1
- package/dist/cjs/editor/index.cjs +1 -1
- package/dist/cjs/esbuild/hiddenDirectory.cjs +20 -0
- package/dist/cjs/esbuild/hiddenDirectory.cjs.map +1 -0
- package/dist/cjs/esbuild/plugin.cjs +69 -5
- package/dist/cjs/esbuild/plugin.cjs.map +1 -1
- package/dist/cjs/esbuild/resolvePackageExport.cjs +118 -0
- package/dist/cjs/esbuild/resolvePackageExport.cjs.map +1 -0
- package/dist/cjs/format/index.cjs +3 -3
- package/dist/cjs/index.cjs +3 -3
- package/dist/cjs/markdown/installIntlayerMarkdown.cjs +1 -1
- package/dist/cjs/plugins.cjs +36 -40
- package/dist/cjs/plugins.cjs.map +1 -1
- package/dist/cjs/webpack/mergeConfig.cjs +1 -1
- package/dist/cjs/webpack/mergeConfig.cjs.map +1 -1
- package/dist/esm/analytics/useAnalytics.mjs +1 -1
- package/dist/esm/client/intlayerToken.mjs +1 -1
- package/dist/esm/client/useDictionary.mjs +1 -1
- package/dist/esm/client/useDictionaryAsync.mjs +1 -1
- package/dist/esm/client/useDictionaryDynamic.mjs +2 -2
- package/dist/esm/client/useIntlayer.mjs +1 -1
- package/dist/esm/client/useLocale.mjs +1 -1
- package/dist/esm/editor/EditorProvider.component.mjs +1 -1
- package/dist/esm/editor/index.mjs +1 -1
- package/dist/esm/esbuild/hiddenDirectory.mjs +19 -0
- package/dist/esm/esbuild/hiddenDirectory.mjs.map +1 -0
- package/dist/esm/esbuild/plugin.mjs +70 -7
- package/dist/esm/esbuild/plugin.mjs.map +1 -1
- package/dist/esm/esbuild/resolvePackageExport.mjs +115 -0
- package/dist/esm/esbuild/resolvePackageExport.mjs.map +1 -0
- package/dist/esm/format/index.mjs +3 -3
- package/dist/esm/index.mjs +3 -3
- package/dist/esm/markdown/installIntlayerMarkdown.mjs +1 -1
- package/dist/esm/plugins.mjs +36 -40
- package/dist/esm/plugins.mjs.map +1 -1
- package/dist/esm/webpack/mergeConfig.mjs +1 -2
- package/dist/esm/webpack/mergeConfig.mjs.map +1 -1
- package/dist/types/esbuild/hiddenDirectory.d.ts +15 -0
- package/dist/types/esbuild/hiddenDirectory.d.ts.map +1 -0
- package/dist/types/esbuild/index.d.ts +2 -2
- package/dist/types/esbuild/plugin.d.ts +34 -18
- package/dist/types/esbuild/plugin.d.ts.map +1 -1
- package/dist/types/esbuild/resolvePackageExport.d.ts +37 -0
- package/dist/types/esbuild/resolvePackageExport.d.ts.map +1 -0
- package/dist/types/plugins.d.ts.map +1 -1
- package/dist/types/webpack/mergeConfig.d.ts.map +1 -1
- package/package.json +11 -10
- package/dist/esm/_virtual/_rolldown/runtime.mjs +0 -8
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<a href="https://intlayer.org" rel="">
|
|
3
|
-
<img src="https://raw.githubusercontent.com/aymericzip/intlayer/main/docs/assets/cover.
|
|
3
|
+
<img src="https://raw.githubusercontent.com/aymericzip/intlayer/main/docs/assets/cover.webp" width="60%" alt="Intlayer Logo" />
|
|
4
4
|
</a>
|
|
5
5
|
</p>
|
|
6
6
|
|
|
@@ -49,10 +49,10 @@ With **per-locale content files**, **TypeScript autocompletion**, **tree-shakabl
|
|
|
49
49
|
|
|
50
50
|
| Feature | Description |
|
|
51
51
|
| --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
52
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/frameworks.
|
|
52
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/frameworks.webp?raw=true" alt="Feature" width="700"> | **Cross-Frameworks Support**<br><br>Intlayer is compatible with all major frameworks and libraries, including Next.js, React, Vite, Vue.js, Nuxt, Preact, Express, and more. |
|
|
53
53
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/javascript_content_management.jpg?raw=true" alt="Feature" width="700"> | **JavaScript-Powered Content Management**<br><br>Harness the flexibility of JavaScript to define and manage your content efficiently. <br><br> - [Content declaration](https://intlayer.org/doc/concept/content) |
|
|
54
54
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/per_locale_content_declaration_file.png?raw=true" alt="Feature" width="700"> | **Per-Locale Content Declaration File**<br><br>Speed up your development by declaring your content once, before auto generation.<br><br> - [Per-Locale Content Declaration File](https://intlayer.org/doc/concept/per-locale-file) |
|
|
55
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/compiler.
|
|
55
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/compiler.webp?raw=true" alt="Feature" width="700"> | **Compiler**<br><br>The Intlayer Compiler extract automatically the content from the components and generate the dictionary files.<br><br> - [Compiler](https://intlayer.org/doc/compiler) |
|
|
56
56
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true" alt="Feature" width="700"> | **Type-Safe Environment**<br><br>Leverage TypeScript to ensure your content definitions and code are error-free, while also benefiting from IDE autocompletion.<br><br> - [TypeScript configuration](https://intlayer.org/doc/environment/vite-and-react#configure-typescript) |
|
|
57
57
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/config_file.png?raw=true" alt="Feature" width="700"> | **Simplified Setup**<br><br>Get up and running quickly with minimal configuration. Adjust settings for internationalization, routing, AI, build, and content handling with ease. <br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
|
|
58
58
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/content_retrieval.png?raw=true" alt="Feature" width="700"> | **Simplified Content Retrieval**<br><br>No need to call your `t` function for each piece of content. Retrieve all your content directly using a single hook.<br><br> - [React integration](https://intlayer.org/doc/environment/create-react-app) |
|
|
@@ -60,12 +60,12 @@ With **per-locale content files**, **TypeScript autocompletion**, **tree-shakabl
|
|
|
60
60
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/file_tree.png?raw=true" alt="Feature" width="700"> | **Organized Codebase**<br><br>Keep your codebase more organized: 1 component = 1 dictionary in the same folder. Translations close to their respective components, enhance maintainability and clarity. <br><br> - [How Intlayer works](https://intlayer.org/doc/concept/how-works-intlayer) |
|
|
61
61
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/url_routing.png?raw=true" alt="Feature" width="700"> | **Enhanced Routing**<br><br>Full support of app routing, adapting seamlessly to complex application structures, for Next.js, React, Vite, Vue.js, etc.<br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
|
|
62
62
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/markdown.png?raw=true" alt="Feature" width="700"> | **Markdown Support**<br><br>Import and interpret, locale files and remote Markdown for multilingual content like privacy policies, documentation, etc. Interpret and make Markdown metadata accessible in your code.<br><br> - [Content files](https://intlayer.org/doc/concept/content/file) |
|
|
63
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/visual_editor.
|
|
64
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.
|
|
65
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/static_rendering.
|
|
63
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/visual_editor.webp?raw=true" alt="Feature" width="700"> | **Free Visual Editor & CMS**<br><br>A free visual editor and CMS are available for content writers, removing the need for a localization platform. Keep your content synchronized using Git, or externalize it totally or partially with the CMS.<br><br> - [Intlayer Editor](https://intlayer.org/doc/concept/editor) <br> - [Intlayer CMS](https://intlayer.org/doc/concept/cms) |
|
|
64
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.webp?raw=true" alt="Feature" width="700"> | **Tree-shakable Content**<br><br>Tree-shakable content, reducing the size of the final bundle. Loads content per component, excluding any unused content from your bundle. Supports lazy loading to enhance app loading efficiency. <br><br> - [App build optimization](https://intlayer.org/doc/concept/how-works-intlayer#app-build-optimization) |
|
|
65
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/static_rendering.webp?raw=true" alt="Feature" width="700"> | **Static Rendering**<br><br>Doesn't block Static Rendering. <br><br> - [Next.js integration](https://intlayer.org/doc/environment/nextjs) |
|
|
66
66
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/AI_translation.png?raw=true" alt="Feature" width="700"> | **AI-Powered Translation**<br><br>Transform your website into 231 languages with just one click using Intlayer's advanced AI-powered translation tools using your own AI provider / API key. <br><br> - [CI/CD integration](https://intlayer.org/doc/concept/ci-cd) <br> - [Intlayer CLI](https://intlayer.org/doc/concept/cli) <br> - [Auto fill](https://intlayer.org/doc/concept/auto-fill) |
|
|
67
67
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/mcp.png?raw=true" alt="Feature" width="700"> | **MCP Server Integration**<br><br>Provides an MCP (Model Context Protocol) server for IDE automation, enabling seamless content management and i18n workflows directly within your development environment. <br><br> - [MCP Server](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/mcp_server.md) |
|
|
68
|
-
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/vscode_extension.
|
|
68
|
+
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/vscode_extension.webp?raw=true" alt="Feature" width="700"> | **VSCode Extension**<br><br>Intlayer provides a VSCode extension to help you manage your content and translations, building your dictionaries, translating your content, and more. <br><br> - [VSCode Extension](https://intlayer.org/doc/vs-code-extension) |
|
|
69
69
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/interoperability.png?raw=true" alt="Feature" width="700"> | **Interoperability**<br><br>Allow interoperability with react-i18next, next-i18next, next-intl, react-intl, vue-i18n. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) <br> - [Intlayer and vue-i18n](https://intlayer.org/blog/intlayer-with-vue-i18n) <br> - [Intlayer compat adapters](https://intlayer.org/doc/compatibility) |
|
|
70
70
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/benchmark.png?raw=true" alt="Feature" width="700"> | **Performances & Benchmark**<br><br>Uses advanced tree-shaking and dynamic loading to boost performances and keep the solution as light as possible. <br><br> - [Performances & Benchmark](https://intlayer.org/doc/benchmark) |
|
|
71
71
|
|
|
@@ -262,7 +262,7 @@ Intlayer connects **developers**, **copywriters**, and **AI agents** in one work
|
|
|
262
262
|
- Feature flags
|
|
263
263
|
- Headless CMSs (e.g. Contentful, Strapi, Sanity)
|
|
264
264
|
|
|
265
|
-

|
|
266
266
|
|
|
267
267
|
## 🌐 Readme in other languages
|
|
268
268
|
|
|
@@ -328,4 +328,4 @@ Contribute on [GitHub](https://github.com/aymericzip/intlayer), [GitLab](https:/
|
|
|
328
328
|
|
|
329
329
|
If you like Intlayer, give us a ⭐ on GitHub. It helps others discover the project! [See why GitHub Stars matter](https://github.com/aymericzip/intlayer/blob/main/CONTRIBUTING.md#why-github-stars-matter-).
|
|
330
330
|
|
|
331
|
-
[](https://
|
|
331
|
+
[](https://star-history.com/#aymericzip/intlayer&Date)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_analytics_exposureSink = require('./exposureSink.cjs');
|
|
3
2
|
const require_client_intlayerToken = require('../client/intlayerToken.cjs');
|
|
3
|
+
const require_analytics_exposureSink = require('./exposureSink.cjs');
|
|
4
4
|
let _angular_core = require("@angular/core");
|
|
5
5
|
let _intlayer_analytics_isEnabled = require("@intlayer/analytics/isEnabled");
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
let _intlayer_config_built = require("@intlayer/config/built");
|
|
3
2
|
let _angular_core = require("@angular/core");
|
|
3
|
+
let _intlayer_config_built = require("@intlayer/config/built");
|
|
4
4
|
let _intlayer_config_client = require("@intlayer/config/client");
|
|
5
5
|
|
|
6
6
|
//#region src/client/intlayerToken.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_getDictionary = require('../getDictionary.cjs');
|
|
3
2
|
const require_client_intlayerToken = require('./intlayerToken.cjs');
|
|
3
|
+
const require_getDictionary = require('../getDictionary.cjs');
|
|
4
4
|
let _angular_core = require("@angular/core");
|
|
5
5
|
let _intlayer_core_dictionaryManipulator = require("@intlayer/core/dictionaryManipulator");
|
|
6
6
|
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_client_intlayerToken = require('./intlayerToken.cjs');
|
|
5
5
|
const require_client_useDictionary = require('./useDictionary.cjs');
|
|
6
|
-
let _intlayer_config_built = require("@intlayer/config/built");
|
|
7
6
|
let _angular_core = require("@angular/core");
|
|
7
|
+
let _intlayer_config_built = require("@intlayer/config/built");
|
|
8
8
|
|
|
9
9
|
//#region src/client/useDictionaryAsync.ts
|
|
10
10
|
/**
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
-
const require_getDictionary = require('../getDictionary.cjs');
|
|
5
4
|
const require_client_intlayerToken = require('./intlayerToken.cjs');
|
|
5
|
+
const require_getDictionary = require('../getDictionary.cjs');
|
|
6
6
|
const require_client_useDictionary = require('./useDictionary.cjs');
|
|
7
7
|
const require_client_useLoadDynamic = require('./useLoadDynamic.cjs');
|
|
8
|
-
let _intlayer_config_built = require("@intlayer/config/built");
|
|
9
8
|
let _angular_core = require("@angular/core");
|
|
9
|
+
let _intlayer_config_built = require("@intlayer/config/built");
|
|
10
10
|
let _intlayer_core_dictionaryManipulator = require("@intlayer/core/dictionaryManipulator");
|
|
11
11
|
|
|
12
12
|
//#region src/client/useDictionaryDynamic.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_getIntlayer = require('../getIntlayer.cjs');
|
|
3
2
|
const require_client_intlayerToken = require('./intlayerToken.cjs');
|
|
3
|
+
const require_getIntlayer = require('../getIntlayer.cjs');
|
|
4
4
|
let _angular_core = require("@angular/core");
|
|
5
5
|
let _intlayer_core_dictionaryManipulator = require("@intlayer/core/dictionaryManipulator");
|
|
6
6
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_client_intlayerToken = require('./intlayerToken.cjs');
|
|
3
3
|
const require_client_useLocaleStorage = require('./useLocaleStorage.cjs');
|
|
4
|
-
let _intlayer_config_built = require("@intlayer/config/built");
|
|
5
4
|
let _angular_core = require("@angular/core");
|
|
5
|
+
let _intlayer_config_built = require("@intlayer/config/built");
|
|
6
6
|
|
|
7
7
|
//#region src/client/useLocale.ts
|
|
8
8
|
const { defaultLocale, locales: availableLocales } = _intlayer_config_built.internationalization ?? {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_editor_useEditor = require('./useEditor.cjs');
|
|
2
3
|
const require_decorateMetadata = require('../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.cjs');
|
|
3
4
|
const require_decorate = require('../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.cjs');
|
|
4
|
-
const require_editor_useEditor = require('./useEditor.cjs');
|
|
5
5
|
let _angular_core = require("@angular/core");
|
|
6
6
|
|
|
7
7
|
//#region src/editor/EditorProvider.component.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_editor_ContentSelector_component = require('./ContentSelector.component.cjs');
|
|
3
2
|
const require_editor_useEditor = require('./useEditor.cjs');
|
|
3
|
+
const require_editor_ContentSelector_component = require('./ContentSelector.component.cjs');
|
|
4
4
|
const require_editor_EditorProvider_component = require('./EditorProvider.component.cjs');
|
|
5
5
|
|
|
6
6
|
Object.defineProperty(exports, 'ContentSelectorWrapperComponent', {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
let node_path = require("node:path");
|
|
3
|
+
|
|
4
|
+
//#region src/esbuild/hiddenDirectory.ts
|
|
5
|
+
/**
|
|
6
|
+
* Whether `directory` sits under a dot-directory (`.intlayer/…`) of `baseDir`.
|
|
7
|
+
*
|
|
8
|
+
* Angular's esbuild dev server ignores `<workspace>/**\/.*\/**` in its file
|
|
9
|
+
* watcher, so generated files living there never invalidate its TypeScript
|
|
10
|
+
* source cache: a key added to a dictionary regenerates the types, but the
|
|
11
|
+
* template type-checker keeps the stale declaration until `ng serve` restarts.
|
|
12
|
+
*
|
|
13
|
+
* @param baseDir - Angular workspace root (the Intlayer `system.baseDir`).
|
|
14
|
+
* @param directory - Absolute directory to test.
|
|
15
|
+
*/
|
|
16
|
+
const isInHiddenDirectory = (baseDir, directory) => (0, node_path.relative)(baseDir, directory).split(node_path.sep).some((segment) => segment.startsWith(".") && segment !== "..");
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
exports.isInHiddenDirectory = isInHiddenDirectory;
|
|
20
|
+
//# sourceMappingURL=hiddenDirectory.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hiddenDirectory.cjs","names":["relative","sep"],"sources":["../../../src/esbuild/hiddenDirectory.ts"],"sourcesContent":["import { relative, sep } from 'node:path';\n\n/**\n * Whether `directory` sits under a dot-directory (`.intlayer/…`) of `baseDir`.\n *\n * Angular's esbuild dev server ignores `<workspace>/**\\/.*\\/**` in its file\n * watcher, so generated files living there never invalidate its TypeScript\n * source cache: a key added to a dictionary regenerates the types, but the\n * template type-checker keeps the stale declaration until `ng serve` restarts.\n *\n * @param baseDir - Angular workspace root (the Intlayer `system.baseDir`).\n * @param directory - Absolute directory to test.\n */\nexport const isInHiddenDirectory = (\n baseDir: string,\n directory: string\n): boolean =>\n relative(baseDir, directory)\n .split(sep)\n .some((segment) => segment.startsWith('.') && segment !== '..');\n"],"mappings":";;;;;;;;;;;;;;;AAaA,MAAa,uBACX,SACA,kBAEAA,oBAAS,SAAS,SAAS,CAAC,CACzB,MAAMC,aAAG,CAAC,CACV,MAAM,YAAY,QAAQ,WAAW,GAAG,KAAK,YAAY,IAAI"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_esbuild_hiddenDirectory = require('./hiddenDirectory.cjs');
|
|
3
|
+
const require_esbuild_resolvePackageExport = require('./resolvePackageExport.cjs');
|
|
4
|
+
let node_fs_promises = require("node:fs/promises");
|
|
2
5
|
let node_module = require("node:module");
|
|
3
6
|
let node_path = require("node:path");
|
|
4
|
-
let _intlayer_config_node = require("@intlayer/config/node");
|
|
5
|
-
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
6
|
-
let node_fs_promises = require("node:fs/promises");
|
|
7
7
|
let _intlayer_config_dictionaryPreload = require("@intlayer/config/dictionaryPreload");
|
|
8
8
|
let _intlayer_config_envVars = require("@intlayer/config/envVars");
|
|
9
9
|
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");
|
|
10
12
|
let _intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
|
|
11
13
|
let _intlayer_engine_build = require("@intlayer/engine/build");
|
|
12
14
|
let _intlayer_engine_cli = require("@intlayer/engine/cli");
|
|
@@ -22,9 +24,34 @@ let _intlayer_engine_watcher = require("@intlayer/engine/watcher");
|
|
|
22
24
|
* only depends on `intlayer` and its framework binding, so the bare specifier
|
|
23
25
|
* would resolve from a tree that need not contain the package at all.
|
|
24
26
|
*
|
|
25
|
-
*
|
|
27
|
+
* Always built from `import.meta.url`: the bundler shims it to `__filename` in
|
|
28
|
+
* the CommonJS output, whereas a `typeof require` guard is unreliable here —
|
|
29
|
+
* the ESM output rewrites `require` into an always-defined proxy that has no
|
|
30
|
+
* `resolve` method.
|
|
26
31
|
*/
|
|
27
|
-
const preloadModuleId = (0, _intlayer_config_utils.normalizePath)((0, _intlayer_config_dictionaryPreload.resolvePreloadModuleId)(
|
|
32
|
+
const preloadModuleId = (0, _intlayer_config_utils.normalizePath)((0, _intlayer_config_dictionaryPreload.resolvePreloadModuleId)((0, node_module.createRequire)(require("url").pathToFileURL(__filename).href)));
|
|
33
|
+
/** Bare specifiers of the packages this plugin keeps inside its own build. */
|
|
34
|
+
const INTLAYER_PACKAGE_FILTER = /^(?:intlayer|angular-intlayer|@intlayer\/[^/]+)(?:\/|$)/;
|
|
35
|
+
/** Namespace of the re-export shims standing in for externalised packages. */
|
|
36
|
+
const INTLAYER_PACKAGE_NAMESPACE = "intlayer-package";
|
|
37
|
+
/** Matches a module that has a default export, on unminified sources. */
|
|
38
|
+
const DEFAULT_EXPORT_PATTERN = /\bexport\s+default\b|\bas\s+default\b|\{\s*default\s*[,}]/;
|
|
39
|
+
/**
|
|
40
|
+
* The dev server's file watcher skips dot-directories, so type declarations
|
|
41
|
+
* generated there are never re-read: a key added to a dictionary stays unknown
|
|
42
|
+
* to template type-checking until `ng serve` restarts. Nothing in the plugin
|
|
43
|
+
* can reach that cache, so the fix is to generate the types elsewhere.
|
|
44
|
+
*/
|
|
45
|
+
const warnAboutHiddenTypesDirectory = (configuration, appLogger) => {
|
|
46
|
+
const { baseDir, typesDir, moduleAugmentationDir } = configuration.system;
|
|
47
|
+
const hiddenDirectories = [.../* @__PURE__ */ new Set([typesDir, moduleAugmentationDir])].filter((directory) => require_esbuild_hiddenDirectory.isInHiddenDirectory(baseDir, directory));
|
|
48
|
+
if (hiddenDirectories.length === 0) return;
|
|
49
|
+
appLogger([
|
|
50
|
+
`Type declarations are generated under ${hiddenDirectories.map((directory) => (0, node_path.relative)(baseDir, directory)).join(", ")}.`,
|
|
51
|
+
"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.",
|
|
52
|
+
"Set 'system.typesDir' and 'system.moduleAugmentationDir' to a directory outside any dot-directory (e.g. 'intlayer-types') and point the tsconfig 'include' at it."
|
|
53
|
+
].join(" "), { level: "warn" });
|
|
54
|
+
};
|
|
28
55
|
/**
|
|
29
56
|
* esbuild plugin that integrates Intlayer into the Angular (or any esbuild-based) build process.
|
|
30
57
|
*
|
|
@@ -101,6 +128,36 @@ const intlayerEsbuildPlugin = (options) => {
|
|
|
101
128
|
const escapedFrom = from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
102
129
|
build.onResolve({ filter: new RegExp(`^${escapedFrom}$`) }, () => ({ path: to }));
|
|
103
130
|
}
|
|
131
|
+
let externalizesPackages;
|
|
132
|
+
build.onResolve({ filter: INTLAYER_PACKAGE_FILTER }, (args) => {
|
|
133
|
+
if (!externalizesPackages || !args.resolveDir) return null;
|
|
134
|
+
const importCondition = args.kind.startsWith("require") ? "require" : "import";
|
|
135
|
+
const resolved = require_esbuild_resolvePackageExport.resolvePackageExport(args.path, args.resolveDir, [
|
|
136
|
+
"browser",
|
|
137
|
+
"module",
|
|
138
|
+
importCondition
|
|
139
|
+
]);
|
|
140
|
+
if (!resolved) return null;
|
|
141
|
+
return {
|
|
142
|
+
path: `${encodeURIComponent((0, node_path.dirname)(resolved.path))}/${args.path}`,
|
|
143
|
+
namespace: INTLAYER_PACKAGE_NAMESPACE,
|
|
144
|
+
pluginData: { realPath: resolved.path },
|
|
145
|
+
sideEffects: resolved.sideEffects
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
build.onLoad({
|
|
149
|
+
filter: /.*/,
|
|
150
|
+
namespace: INTLAYER_PACKAGE_NAMESPACE
|
|
151
|
+
}, async (args) => {
|
|
152
|
+
const { realPath } = args.pluginData;
|
|
153
|
+
const source = await (0, node_fs_promises.readFile)(realPath, "utf-8");
|
|
154
|
+
const specifier = JSON.stringify(`./${(0, node_path.basename)(realPath)}`);
|
|
155
|
+
return {
|
|
156
|
+
contents: [`export * from ${specifier};`, DEFAULT_EXPORT_PATTERN.test(source) && `export { default } from ${specifier};`].filter(Boolean).join("\n"),
|
|
157
|
+
loader: "js",
|
|
158
|
+
resolveDir: (0, node_path.dirname)(realPath)
|
|
159
|
+
};
|
|
160
|
+
});
|
|
104
161
|
if (config.build.dictionariesPreload) {
|
|
105
162
|
const dynamicDictionariesDir = (0, _intlayer_config_utils.normalizePath)(config.system.dynamicDictionariesDir);
|
|
106
163
|
build.onLoad({ filter: (0, _intlayer_config_dictionaryPreload.createDynamicEntryFilter)(dynamicDictionariesDir) }, async ({ path }) => {
|
|
@@ -121,6 +178,13 @@ const intlayerEsbuildPlugin = (options) => {
|
|
|
121
178
|
});
|
|
122
179
|
await preparePromise;
|
|
123
180
|
build.onStart(async () => {
|
|
181
|
+
if (externalizesPackages === void 0) {
|
|
182
|
+
externalizesPackages = (await build.resolve("@angular/core", {
|
|
183
|
+
kind: "import-statement",
|
|
184
|
+
resolveDir: config.system.baseDir
|
|
185
|
+
})).external;
|
|
186
|
+
if (externalizesPackages) warnAboutHiddenTypesDirectory(config, appLogger);
|
|
187
|
+
}
|
|
124
188
|
if ((options?.watch ?? !isBuildMode) && !watcherStarted) {
|
|
125
189
|
watcherStarted = true;
|
|
126
190
|
await (0, _intlayer_engine_watcher.watch)({ configuration: config });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs","names":["normalizePath","resolvePreloadModuleId","createRequire","getConfiguration","getAlias","join","getAppLogger","getConfigEnvVars","getDictionaries","getUnusedNodeTypesAsync","formatNodeTypeToEnvVar","formatDictionarySelectorEnvVar","getHasDictionarySelector","createDynamicEntryFilter","readFile","addDynamicEntryPreload","prepareIntlayer","watch"],"sources":["../../../src/esbuild/plugin.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { join } 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';\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 * This package ships both module formats, hence the `require` fallback.\n */\nconst preloadModuleId = normalizePath(\n resolvePreloadModuleId(\n typeof require !== 'undefined' ? require : createRequire(import.meta.url)\n )\n);\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 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: (args: {\n path: string;\n importer: string;\n namespace: string;\n resolveDir: string;\n }) => { path: string; namespace?: string } | null | undefined\n ): void;\n /** Intercept module contents, so a resolved file can be rewritten. */\n onLoad(\n options: { filter: RegExp; namespace?: string },\n callback: (args: {\n path: string;\n namespace: string;\n }) =>\n | { contents: string; loader?: string }\n | null\n | undefined\n | Promise<{ contents: string; loader?: string } | 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 * 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 // 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 // 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":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,MAAM,sBAAkBA,0CACtBC,2DACE,OAAO,YAAY,cAAc,cAAUC,wEAA6B,CAC1E,CACF;;;;;;;;;;;;;;;;;;;;;;;AA8EA,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;GAcA,IAAI,OAAO,MAAM,qBAAqB;IACpC,MAAM,6BAAyBZ,sCAC7B,OAAO,OAAO,sBAChB;IAEA,MAAM,OACJ,EAAE,YAAQa,6DAAyB,sBAAsB,EAAE,GAC3D,OAAO,EAAE,WAAW;KAElB,IAAI,KADcb,sCAAc,IACnB,CAAC,CAAC,WAAW,GAAG,uBAAuB,EAAE,GACpD,OAAO;KAET,MAAM,OAAO,UAAMc,2BAAS,MAAM,OAAO;KACzC,MAAM,aAASC,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;IAOxB,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","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":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
let node_path = require("node:path");
|
|
3
|
+
let node_fs = require("node:fs");
|
|
4
|
+
|
|
5
|
+
//#region src/esbuild/resolvePackageExport.ts
|
|
6
|
+
/** Splits a bare specifier into its package name and `./`-prefixed subpath. */
|
|
7
|
+
const parsePackageSpecifier = (specifier) => {
|
|
8
|
+
const segments = specifier.split("/");
|
|
9
|
+
const nameSegmentCount = specifier.startsWith("@") ? 2 : 1;
|
|
10
|
+
const packageName = segments.slice(0, nameSegmentCount).join("/");
|
|
11
|
+
const rest = segments.slice(nameSegmentCount).join("/");
|
|
12
|
+
return {
|
|
13
|
+
packageName,
|
|
14
|
+
subpath: rest ? `./${rest}` : "."
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Locates `node_modules/<packageName>/package.json` the way Node does: from
|
|
19
|
+
* `startDir` upward, first hit wins.
|
|
20
|
+
*/
|
|
21
|
+
const findPackageManifest = (packageName, startDir) => {
|
|
22
|
+
let currentDir = (0, node_path.resolve)(startDir);
|
|
23
|
+
while (true) {
|
|
24
|
+
const candidate = (0, node_path.join)(currentDir, "node_modules", packageName, "package.json");
|
|
25
|
+
if ((0, node_fs.existsSync)(candidate)) return candidate;
|
|
26
|
+
const parentDir = (0, node_path.dirname)(currentDir);
|
|
27
|
+
if (parentDir === currentDir) return void 0;
|
|
28
|
+
currentDir = parentDir;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Picks the file for a target, honouring the manifest's own key order for
|
|
33
|
+
* condition maps as the ESM resolver does.
|
|
34
|
+
*/
|
|
35
|
+
const resolveExportTarget = (target, conditions) => {
|
|
36
|
+
if (typeof target === "string") return target;
|
|
37
|
+
if (target === null) return void 0;
|
|
38
|
+
if (Array.isArray(target)) {
|
|
39
|
+
for (const candidate of target) {
|
|
40
|
+
const resolved = resolveExportTarget(candidate, conditions);
|
|
41
|
+
if (resolved) return resolved;
|
|
42
|
+
}
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
for (const [condition, value] of Object.entries(target)) {
|
|
46
|
+
if (condition !== "default" && !conditions.has(condition)) continue;
|
|
47
|
+
const resolved = resolveExportTarget(value, conditions);
|
|
48
|
+
if (resolved) return resolved;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Matches `subpath` against the `exports` map: an exact key first, then the
|
|
53
|
+
* `*` pattern with the longest literal prefix, substituting the wildcard into
|
|
54
|
+
* the resolved target.
|
|
55
|
+
*/
|
|
56
|
+
const resolveSubpathExport = (exportsMap, subpath, conditions) => {
|
|
57
|
+
if (!(typeof exportsMap === "object" && exportsMap !== null && !Array.isArray(exportsMap) && Object.keys(exportsMap).some((key) => key.startsWith(".")))) return subpath === "." ? resolveExportTarget(exportsMap, conditions) : void 0;
|
|
58
|
+
const subpathMap = exportsMap;
|
|
59
|
+
if (subpath in subpathMap) return resolveExportTarget(subpathMap[subpath], conditions);
|
|
60
|
+
let bestMatch = {
|
|
61
|
+
prefix: "",
|
|
62
|
+
wildcard: "",
|
|
63
|
+
target: null
|
|
64
|
+
};
|
|
65
|
+
for (const [pattern, target] of Object.entries(subpathMap)) {
|
|
66
|
+
const wildcardIndex = pattern.indexOf("*");
|
|
67
|
+
if (wildcardIndex === -1) continue;
|
|
68
|
+
const prefix = pattern.slice(0, wildcardIndex);
|
|
69
|
+
const suffix = pattern.slice(wildcardIndex + 1);
|
|
70
|
+
if (!(subpath.startsWith(prefix) && subpath.length >= prefix.length + suffix.length && subpath.endsWith(suffix)) || prefix.length <= bestMatch.prefix.length) continue;
|
|
71
|
+
bestMatch = {
|
|
72
|
+
prefix,
|
|
73
|
+
wildcard: subpath.slice(prefix.length, subpath.length - suffix.length),
|
|
74
|
+
target
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return resolveExportTarget(bestMatch.target, conditions)?.replaceAll("*", bestMatch.wildcard);
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Resolves a bare specifier to an absolute file through the package manifest,
|
|
81
|
+
* without going through the bundler's own resolver.
|
|
82
|
+
*
|
|
83
|
+
* Needed inside Angular's dev server: its esbuild pipeline marks every file
|
|
84
|
+
* resolved under `node_modules` as external so Vite can pre-bundle it, and the
|
|
85
|
+
* pre-bundler neither runs the Intlayer plugin nor sees its aliases — the real
|
|
86
|
+
* `@intlayer/config/built` (a Node config loader) then lands in the browser.
|
|
87
|
+
* Resolving here and returning a plain path keeps the package inside the
|
|
88
|
+
* plugin-aware esbuild build.
|
|
89
|
+
*
|
|
90
|
+
* @param specifier - Bare specifier such as `@intlayer/core/interpreter`.
|
|
91
|
+
* @param resolveDir - Directory the import is issued from.
|
|
92
|
+
* @param conditions - Export conditions to honour, in addition to `default`.
|
|
93
|
+
* @returns The resolved file, or `undefined` when the manifest cannot be found
|
|
94
|
+
* or does not map the subpath — the caller then leaves the bundler to it.
|
|
95
|
+
*/
|
|
96
|
+
const resolvePackageExport = (specifier, resolveDir, conditions) => {
|
|
97
|
+
const { packageName, subpath } = parsePackageSpecifier(specifier);
|
|
98
|
+
const manifestPath = findPackageManifest(packageName, resolveDir);
|
|
99
|
+
if (!manifestPath) return void 0;
|
|
100
|
+
const manifest = JSON.parse((0, node_fs.readFileSync)(manifestPath, "utf-8"));
|
|
101
|
+
const packageDir = (0, node_path.dirname)(manifestPath);
|
|
102
|
+
const conditionSet = new Set(conditions);
|
|
103
|
+
let target;
|
|
104
|
+
if (manifest.exports !== void 0) target = resolveSubpathExport(manifest.exports, subpath, conditionSet);
|
|
105
|
+
else if (subpath === ".") target = manifest.module ?? manifest.main ?? "./index.js";
|
|
106
|
+
else if ((0, node_fs.existsSync)((0, node_path.join)(packageDir, subpath))) target = subpath;
|
|
107
|
+
if (!target) return void 0;
|
|
108
|
+
return {
|
|
109
|
+
path: (0, node_path.resolve)(packageDir, target),
|
|
110
|
+
sideEffects: manifest.sideEffects === false ? false : void 0
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
//#endregion
|
|
115
|
+
exports.findPackageManifest = findPackageManifest;
|
|
116
|
+
exports.parsePackageSpecifier = parsePackageSpecifier;
|
|
117
|
+
exports.resolvePackageExport = resolvePackageExport;
|
|
118
|
+
//# sourceMappingURL=resolvePackageExport.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolvePackageExport.cjs","names":["resolve","join","existsSync","dirname","readFileSync"],"sources":["../../../src/esbuild/resolvePackageExport.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\n/**\n * A target under a package manifest `exports` map: a file path, a condition\n * map, an ordered fallback list, or `null` to block the subpath.\n */\ntype ExportTarget =\n | string\n | null\n | ExportTarget[]\n | { [condition: string]: ExportTarget };\n\n/** The subset of a `package.json` this resolution reads. */\ntype PackageManifest = {\n main?: string;\n module?: string;\n exports?: ExportTarget;\n sideEffects?: boolean | string[];\n};\n\nexport type ResolvedPackageExport = {\n /** Absolute path of the file the specifier maps to. */\n path: string;\n /** `false` when the manifest declares the whole package side-effect free. */\n sideEffects: false | undefined;\n};\n\n/** Splits a bare specifier into its package name and `./`-prefixed subpath. */\nexport const parsePackageSpecifier = (\n specifier: string\n): { packageName: string; subpath: string } => {\n const segments = specifier.split('/');\n const nameSegmentCount = specifier.startsWith('@') ? 2 : 1;\n const packageName = segments.slice(0, nameSegmentCount).join('/');\n const rest = segments.slice(nameSegmentCount).join('/');\n\n return { packageName, subpath: rest ? `./${rest}` : '.' };\n};\n\n/**\n * Locates `node_modules/<packageName>/package.json` the way Node does: from\n * `startDir` upward, first hit wins.\n */\nexport const findPackageManifest = (\n packageName: string,\n startDir: string\n): string | undefined => {\n let currentDir = resolve(startDir);\n\n while (true) {\n const candidate = join(\n currentDir,\n 'node_modules',\n packageName,\n 'package.json'\n );\n if (existsSync(candidate)) return candidate;\n\n const parentDir = dirname(currentDir);\n if (parentDir === currentDir) return undefined;\n currentDir = parentDir;\n }\n};\n\n/**\n * Picks the file for a target, honouring the manifest's own key order for\n * condition maps as the ESM resolver does.\n */\nconst resolveExportTarget = (\n target: ExportTarget,\n conditions: ReadonlySet<string>\n): string | undefined => {\n if (typeof target === 'string') return target;\n if (target === null) return undefined;\n\n if (Array.isArray(target)) {\n for (const candidate of target) {\n const resolved = resolveExportTarget(candidate, conditions);\n if (resolved) return resolved;\n }\n return undefined;\n }\n\n for (const [condition, value] of Object.entries(target)) {\n if (condition !== 'default' && !conditions.has(condition)) continue;\n\n const resolved = resolveExportTarget(value, conditions);\n if (resolved) return resolved;\n }\n\n return undefined;\n};\n\n/**\n * Matches `subpath` against the `exports` map: an exact key first, then the\n * `*` pattern with the longest literal prefix, substituting the wildcard into\n * the resolved target.\n */\nconst resolveSubpathExport = (\n exportsMap: ExportTarget,\n subpath: string,\n conditions: ReadonlySet<string>\n): string | undefined => {\n const isSubpathMap =\n typeof exportsMap === 'object' &&\n exportsMap !== null &&\n !Array.isArray(exportsMap) &&\n Object.keys(exportsMap).some((key) => key.startsWith('.'));\n\n if (!isSubpathMap) {\n return subpath === '.'\n ? resolveExportTarget(exportsMap, conditions)\n : undefined;\n }\n\n const subpathMap = exportsMap as { [subpath: string]: ExportTarget };\n\n if (subpath in subpathMap) {\n return resolveExportTarget(subpathMap[subpath]!, conditions);\n }\n\n let bestMatch: { prefix: string; wildcard: string; target: ExportTarget } = {\n prefix: '',\n wildcard: '',\n target: null,\n };\n\n for (const [pattern, target] of Object.entries(subpathMap)) {\n const wildcardIndex = pattern.indexOf('*');\n if (wildcardIndex === -1) continue;\n\n const prefix = pattern.slice(0, wildcardIndex);\n const suffix = pattern.slice(wildcardIndex + 1);\n const matches =\n subpath.startsWith(prefix) &&\n subpath.length >= prefix.length + suffix.length &&\n subpath.endsWith(suffix);\n\n if (!matches || prefix.length <= bestMatch.prefix.length) continue;\n\n bestMatch = {\n prefix,\n wildcard: subpath.slice(prefix.length, subpath.length - suffix.length),\n target,\n };\n }\n\n const resolved = resolveExportTarget(bestMatch.target, conditions);\n\n return resolved?.replaceAll('*', bestMatch.wildcard);\n};\n\n/**\n * Resolves a bare specifier to an absolute file through the package manifest,\n * without going through the bundler's own resolver.\n *\n * Needed inside Angular's dev server: its esbuild pipeline marks every file\n * resolved under `node_modules` as external so Vite can pre-bundle it, and the\n * pre-bundler neither runs the Intlayer plugin nor sees its aliases — the real\n * `@intlayer/config/built` (a Node config loader) then lands in the browser.\n * Resolving here and returning a plain path keeps the package inside the\n * plugin-aware esbuild build.\n *\n * @param specifier - Bare specifier such as `@intlayer/core/interpreter`.\n * @param resolveDir - Directory the import is issued from.\n * @param conditions - Export conditions to honour, in addition to `default`.\n * @returns The resolved file, or `undefined` when the manifest cannot be found\n * or does not map the subpath — the caller then leaves the bundler to it.\n */\nexport const resolvePackageExport = (\n specifier: string,\n resolveDir: string,\n conditions: readonly string[]\n): ResolvedPackageExport | undefined => {\n const { packageName, subpath } = parsePackageSpecifier(specifier);\n const manifestPath = findPackageManifest(packageName, resolveDir);\n if (!manifestPath) return undefined;\n\n const manifest = JSON.parse(\n readFileSync(manifestPath, 'utf-8')\n ) as PackageManifest;\n const packageDir = dirname(manifestPath);\n const conditionSet = new Set(conditions);\n\n let target: string | undefined;\n\n if (manifest.exports !== undefined) {\n target = resolveSubpathExport(manifest.exports, subpath, conditionSet);\n } else if (subpath === '.') {\n target = manifest.module ?? manifest.main ?? './index.js';\n } else if (existsSync(join(packageDir, subpath))) {\n target = subpath;\n }\n\n if (!target) return undefined;\n\n return {\n path: resolve(packageDir, target),\n sideEffects: manifest.sideEffects === false ? false : undefined,\n };\n};\n"],"mappings":"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"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_format_useCurrency = require('./useCurrency.cjs');
|
|
2
3
|
const require_format_useUnit = require('./useUnit.cjs');
|
|
3
4
|
const require_format_useDate = require('./useDate.cjs');
|
|
4
|
-
const require_format_useNumber = require('./useNumber.cjs');
|
|
5
|
-
const require_format_useRelativeTime = require('./useRelativeTime.cjs');
|
|
6
5
|
const require_format_useCompact = require('./useCompact.cjs');
|
|
7
6
|
const require_format_useIntl = require('./useIntl.cjs');
|
|
8
7
|
const require_format_useList = require('./useList.cjs');
|
|
8
|
+
const require_format_useNumber = require('./useNumber.cjs');
|
|
9
9
|
const require_format_usePercentage = require('./usePercentage.cjs');
|
|
10
|
-
const
|
|
10
|
+
const require_format_useRelativeTime = require('./useRelativeTime.cjs');
|
|
11
11
|
|
|
12
12
|
exports.useCompact = require_format_useCompact.useCompact;
|
|
13
13
|
exports.useCurrency = require_format_useCurrency.useCurrency;
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_plugins = require('./plugins.cjs');
|
|
3
|
-
const require_getIntlayer = require('./getIntlayer.cjs');
|
|
4
|
-
const require_getDictionary = require('./getDictionary.cjs');
|
|
5
2
|
const require_client_intlayerToken = require('./client/intlayerToken.cjs');
|
|
6
3
|
const require_analytics_useAnalytics = require('./analytics/useAnalytics.cjs');
|
|
7
4
|
const require_analytics_useConversion = require('./analytics/useConversion.cjs');
|
|
8
5
|
const require_analytics_useExperiment = require('./analytics/useExperiment.cjs');
|
|
9
6
|
const require_client_installIntlayer = require('./client/installIntlayer.cjs');
|
|
7
|
+
const require_plugins = require('./plugins.cjs');
|
|
8
|
+
const require_getDictionary = require('./getDictionary.cjs');
|
|
10
9
|
const require_client_useDictionary = require('./client/useDictionary.cjs');
|
|
11
10
|
const require_client_useDictionaryAsync = require('./client/useDictionaryAsync.cjs');
|
|
12
11
|
const require_client_useLoadDynamic = require('./client/useLoadDynamic.cjs');
|
|
13
12
|
const require_client_useDictionaryDynamic = require('./client/useDictionaryDynamic.cjs');
|
|
13
|
+
const require_getIntlayer = require('./getIntlayer.cjs');
|
|
14
14
|
const require_client_useIntlayer = require('./client/useIntlayer.cjs');
|
|
15
15
|
const require_client_useLocale = require('./client/useLocale.cjs');
|
|
16
16
|
const require_client_usePathname = require('./client/usePathname.cjs');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_decorate = require('../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.cjs');
|
|
3
|
-
let _intlayer_core_markdown = require("@intlayer/core/markdown");
|
|
4
3
|
let _angular_core = require("@angular/core");
|
|
4
|
+
let _intlayer_core_markdown = require("@intlayer/core/markdown");
|
|
5
5
|
|
|
6
6
|
//#region src/markdown/installIntlayerMarkdown.ts
|
|
7
7
|
/**
|