@analogjs/vite-plugin-angular 3.0.0-alpha.8 → 3.0.0-alpha.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/package.json +3 -7
  2. package/setup-vitest.js +154 -193
  3. package/setup-vitest.js.map +1 -1
  4. package/src/index.d.ts +1 -1
  5. package/src/index.js +6 -2
  6. package/src/index.js.map +1 -1
  7. package/src/lib/angular-build-optimizer-plugin.js +48 -63
  8. package/src/lib/angular-build-optimizer-plugin.js.map +1 -1
  9. package/src/lib/angular-jit-plugin.js +31 -37
  10. package/src/lib/angular-jit-plugin.js.map +1 -1
  11. package/src/lib/angular-pending-tasks.plugin.js +17 -18
  12. package/src/lib/angular-pending-tasks.plugin.js.map +1 -1
  13. package/src/lib/angular-vite-plugin.js +790 -1077
  14. package/src/lib/angular-vite-plugin.js.map +1 -1
  15. package/src/lib/angular-vitest-plugin.js +97 -135
  16. package/src/lib/angular-vitest-plugin.js.map +1 -1
  17. package/src/lib/compiler-plugin.js +40 -44
  18. package/src/lib/compiler-plugin.js.map +1 -1
  19. package/src/lib/component-resolvers.js +87 -120
  20. package/src/lib/component-resolvers.js.map +1 -1
  21. package/src/lib/host.js +69 -101
  22. package/src/lib/host.js.map +1 -1
  23. package/src/lib/live-reload-plugin.js +51 -63
  24. package/src/lib/live-reload-plugin.js.map +1 -1
  25. package/src/lib/nx-folder-plugin.js +18 -16
  26. package/src/lib/nx-folder-plugin.js.map +1 -1
  27. package/src/lib/plugins/file-replacements.plugin.js +35 -62
  28. package/src/lib/plugins/file-replacements.plugin.js.map +1 -1
  29. package/src/lib/router-plugin.js +23 -23
  30. package/src/lib/router-plugin.js.map +1 -1
  31. package/src/lib/tools/package.json +2 -5
  32. package/src/lib/tools/src/builders/vite/vite-build.impl.js +31 -38
  33. package/src/lib/tools/src/builders/vite/vite-build.impl.js.map +1 -1
  34. package/src/lib/tools/src/builders/vite-dev-server/dev-server.impl.js +52 -60
  35. package/src/lib/tools/src/builders/vite-dev-server/dev-server.impl.js.map +1 -1
  36. package/src/lib/tools/src/index.js +0 -2
  37. package/src/lib/utils/devkit.js +34 -38
  38. package/src/lib/utils/devkit.js.map +1 -1
  39. package/src/lib/utils/rolldown.js +9 -5
  40. package/src/lib/utils/rolldown.js.map +1 -1
  41. package/src/lib/utils/source-file-cache.js +35 -37
  42. package/src/lib/utils/source-file-cache.js.map +1 -1
  43. package/README.md +0 -91
  44. package/src/lib/models.js +0 -1
  45. package/src/lib/models.js.map +0 -1
  46. package/src/lib/tools/README.md +0 -3
  47. package/src/lib/tools/src/index.js.map +0 -1
  48. package/src/lib/utils/compiler-plugin-options.js +0 -1
  49. package/src/lib/utils/compiler-plugin-options.js.map +0 -1
  50. package/src/lib/utils/hmr-candidates.js +0 -272
  51. package/src/lib/utils/hmr-candidates.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"compiler-plugin.js","sourceRoot":"","sources":["../../../../../packages/vite-plugin-angular/src/lib/compiler-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAEL,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAK3B,MAAM,UAAU,oBAAoB,CAClC,aAAoC,EACpC,MAAe,EACf,gBAAyB;IAEzB,MAAM,qBAAqB,GAAG,IAAI,qBAAqB,CACrD,EAAE,GAAG,aAAa,EAAE,GAAG,EAAE,IAAI,EAAE,EAC/B,CAAC,CACF,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,gDAAgD;QACtD,KAAK,CAAC,KAAK,CAAC,KAAkB;YAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;oBACpD,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAEtE,OAAO;wBACL,QAAQ;wBACR,MAAM,EAAE,IAAI;qBACb,CAAC;gBACJ,CAAC,CAAC,CAAC;YACL,CAAC;YAED,IAAI,gBAAgB,EAAE,CAAC;gBACrB,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,aAAoC;IAEpC,MAAM,qBAAqB,GAAG,IAAI,qBAAqB,CACrD,EAAE,GAAG,aAAa,EAAE,GAAG,EAAE,IAAI,EAAE,EAC/B,CAAC,CACF,CAAC;IACF,OAAO;QACL,IAAI,EAAE,yCAAyC;QAC/C,IAAI,EAAE;YACJ,MAAM,EAAE;gBACN,EAAE,EAAE,YAAY;aACjB;YACD,KAAK,CAAC,OAAO,CAAC,EAAE;gBACd,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;gBAE/D,OAAO;oBACL,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;oBAC7C,MAAM,EAAE,IAAI;iBACN,CAAC;YACX,CAAC;SACF;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"compiler-plugin.js","names":[],"sources":["../../../../../packages/vite-plugin-angular/src/lib/compiler-plugin.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport type { DepOptimizationConfig, Rolldown } from 'vite';\nimport type { PluginBuild } from 'esbuild';\n\nimport {\n CompilerPluginOptions,\n JavaScriptTransformer,\n} from './utils/devkit.js';\n\ntype EsbuildOptions = NonNullable<DepOptimizationConfig['esbuildOptions']>;\ntype EsbuildPlugin = NonNullable<EsbuildOptions['plugins']>[number];\n\nexport function createCompilerPlugin(\n pluginOptions: CompilerPluginOptions,\n isTest: boolean,\n closeTransformer: boolean,\n): EsbuildPlugin {\n const javascriptTransformer = new JavaScriptTransformer(\n { ...pluginOptions, jit: true },\n 1,\n );\n\n return {\n name: 'analogjs-angular-esbuild-deps-optimizer-plugin',\n async setup(build: PluginBuild) {\n if (!isTest) {\n build.onLoad({ filter: /\\.[cm]?js$/ }, async (args) => {\n const contents = await javascriptTransformer.transformFile(args.path);\n\n return {\n contents,\n loader: 'js',\n };\n });\n }\n\n if (closeTransformer) {\n build.onEnd(() => javascriptTransformer.close());\n }\n },\n };\n}\n\nexport function createRolldownCompilerPlugin(\n pluginOptions: CompilerPluginOptions,\n): Rolldown.Plugin {\n const javascriptTransformer = new JavaScriptTransformer(\n { ...pluginOptions, jit: true },\n 1,\n );\n return {\n name: 'analogjs-rolldown-deps-optimizer-plugin',\n load: {\n filter: {\n id: /\\.[cm]?js$/,\n },\n async handler(id) {\n const contents = await javascriptTransformer.transformFile(id);\n\n return {\n code: Buffer.from(contents).toString('utf-8'),\n loader: 'js',\n } as any;\n },\n },\n };\n}\n"],"mappings":";;AAmBA,SAAgB,qBACd,eACA,QACA,kBACe;CACf,MAAM,wBAAwB,IAAI,GAChC;EAAE,GAAG;EAAe,KAAK;EAAM,EAC/B,EACD;AAED,QAAO;EACL,MAAM;EACN,MAAM,MAAM,OAAoB;AAC9B,OAAI,CAAC,OACH,OAAM,OAAO,EAAE,QAAQ,cAAc,EAAE,OAAO,SAAS;AAGrD,WAAO;KACL,UAHe,MAAM,sBAAsB,cAAc,KAAK,KAAK;KAInE,QAAQ;KACT;KACD;AAGJ,OAAI,iBACF,OAAM,YAAY,sBAAsB,OAAO,CAAC;;EAGrD;;AAGH,SAAgB,6BACd,eACiB;CACjB,MAAM,wBAAwB,IAAI,GAChC;EAAE,GAAG;EAAe,KAAK;EAAM,EAC/B,EACD;AACD,QAAO;EACL,MAAM;EACN,MAAM;GACJ,QAAQ,EACN,IAAI,cACL;GACD,MAAM,QAAQ,IAAI;IAChB,MAAM,WAAW,MAAM,sBAAsB,cAAc,GAAG;AAE9D,WAAO;KACL,MAAM,OAAO,KAAK,SAAS,CAAC,SAAS,QAAQ;KAC7C,QAAQ;KACT;;GAEJ;EACF"}
@@ -1,131 +1,98 @@
1
- import { dirname, resolve } from 'node:path';
2
- // OXC parser (native Rust, NAPI-RS) replaces ts-morph for AST extraction.
3
- // It is ~10-50x faster for the narrow task of pulling property values from
4
- // Angular component decorators. The Visitor helper from Rolldown walks the
5
- // ESTree-compatible AST that OXC produces.
6
- import { parseSync } from 'oxc-parser';
7
- import { Visitor } from 'rolldown/utils';
8
- import { normalizePath } from 'vite';
9
- // ---------------------------------------------------------------------------
10
- // AST helpers
11
- // ---------------------------------------------------------------------------
1
+ import { dirname, resolve } from "node:path";
2
+ import { normalizePath } from "vite";
3
+ import { parseSync } from "oxc-parser";
4
+ import { Visitor } from "rolldown/utils";
5
+ //#region packages/vite-plugin-angular/src/lib/component-resolvers.ts
12
6
  /**
13
- * Extracts a string value from an ESTree AST node.
14
- *
15
- * Handles three forms that Angular decorators may use:
16
- * - `Literal` with a string value → `'./foo.css'` / `"./foo.css"`
17
- * - `StringLiteral` (OXC-specific) → same representation
18
- * - `TemplateLiteral` with zero expressions → `` `./foo.css` ``
19
- *
20
- * Uses `any` because OXC's AST mixes standard ESTree nodes with
21
- * OXC-specific variants (e.g. `StringLiteral`), and the project's
22
- * tsconfig enforces `noPropertyAccessFromIndexSignature`.
23
- */
24
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+ * Extracts a string value from an ESTree AST node.
8
+ *
9
+ * Handles three forms that Angular decorators may use:
10
+ * - `Literal` with a string value → `'./foo.css'` / `"./foo.css"`
11
+ * - `StringLiteral` (OXC-specific) → same representation
12
+ * - `TemplateLiteral` with zero expressions → `` `./foo.css` ``
13
+ *
14
+ * Uses `any` because OXC's AST mixes standard ESTree nodes with
15
+ * OXC-specific variants (e.g. `StringLiteral`), and the project's
16
+ * tsconfig enforces `noPropertyAccessFromIndexSignature`.
17
+ */
25
18
  function getStringValue(node) {
26
- if (!node)
27
- return undefined;
28
- // Standard ESTree Literal (string value)
29
- if (node.type === 'Literal' && typeof node.value === 'string') {
30
- return node.value;
31
- }
32
- // OXC-specific StringLiteral node
33
- if (node.type === 'StringLiteral') {
34
- return node.value;
35
- }
36
- // Template literal with no interpolation (e.g., `./foo.css`)
37
- if (node.type === 'TemplateLiteral' &&
38
- node.expressions.length === 0 &&
39
- node.quasis.length === 1) {
40
- return node.quasis[0].value.cooked ?? node.quasis[0].value.raw;
41
- }
42
- return undefined;
19
+ if (!node) return void 0;
20
+ if (node.type === "Literal" && typeof node.value === "string") return node.value;
21
+ if (node.type === "StringLiteral") return node.value;
22
+ if (node.type === "TemplateLiteral" && node.expressions.length === 0 && node.quasis.length === 1) return node.quasis[0].value.cooked ?? node.quasis[0].value.raw;
43
23
  }
44
24
  /**
45
- * Parses TypeScript/JS source with OXC and collects `styleUrl`, `styleUrls`,
46
- * and `templateUrl` property values from Angular `@Component()` decorators
47
- * in a single AST pass.
48
- *
49
- * This replaces the previous ts-morph implementation — OXC parses natively
50
- * via Rust NAPI bindings, avoiding the overhead of spinning up a full
51
- * TypeScript `Project` for each file.
52
- */
25
+ * Parses TypeScript/JS source with OXC and collects `styleUrl`, `styleUrls`,
26
+ * and `templateUrl` property values from Angular `@Component()` decorators
27
+ * in a single AST pass.
28
+ *
29
+ * This replaces the previous ts-morph implementation — OXC parses natively
30
+ * via Rust NAPI bindings, avoiding the overhead of spinning up a full
31
+ * TypeScript `Project` for each file.
32
+ */
53
33
  function collectComponentUrls(code) {
54
- const { program } = parseSync('cmp.ts', code);
55
- const styleUrls = [];
56
- const templateUrls = [];
57
- const visitor = new Visitor({
58
- // The Visitor callback receives raw ESTree nodes. We use `any`
59
- // because OXC's AST includes non-standard node variants and the
60
- // project tsconfig enforces `noPropertyAccessFromIndexSignature`.
61
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
- Property(node) {
63
- if (node.key?.type !== 'Identifier')
64
- return;
65
- const name = node.key.name;
66
- if (name === 'styleUrls' && node.value?.type === 'ArrayExpression') {
67
- for (const el of node.value.elements) {
68
- const val = getStringValue(el);
69
- if (val !== undefined)
70
- styleUrls.push(val);
71
- }
72
- }
73
- if (name === 'styleUrl') {
74
- const val = getStringValue(node.value);
75
- if (val !== undefined)
76
- styleUrls.push(val);
77
- }
78
- if (name === 'templateUrl') {
79
- const val = getStringValue(node.value);
80
- if (val !== undefined)
81
- templateUrls.push(val);
82
- }
83
- },
84
- });
85
- visitor.visit(program);
86
- return { styleUrls, templateUrls };
34
+ const { program } = parseSync("cmp.ts", code);
35
+ const styleUrls = [];
36
+ const templateUrls = [];
37
+ new Visitor({ Property(node) {
38
+ if (node.key?.type !== "Identifier") return;
39
+ const name = node.key.name;
40
+ if (name === "styleUrls" && node.value?.type === "ArrayExpression") for (const el of node.value.elements) {
41
+ const val = getStringValue(el);
42
+ if (val !== void 0) styleUrls.push(val);
43
+ }
44
+ if (name === "styleUrl") {
45
+ const val = getStringValue(node.value);
46
+ if (val !== void 0) styleUrls.push(val);
47
+ }
48
+ if (name === "templateUrl") {
49
+ const val = getStringValue(node.value);
50
+ if (val !== void 0) templateUrls.push(val);
51
+ }
52
+ } }).visit(program);
53
+ return {
54
+ styleUrls,
55
+ templateUrls
56
+ };
87
57
  }
88
58
  /** Extract all `styleUrl` / `styleUrls` values from Angular component source. */
89
- export function getStyleUrls(code) {
90
- return collectComponentUrls(code).styleUrls;
59
+ function getStyleUrls(code) {
60
+ return collectComponentUrls(code).styleUrls;
91
61
  }
92
62
  /** Extract all `templateUrl` values from Angular component source. */
93
- export function getTemplateUrls(code) {
94
- return collectComponentUrls(code).templateUrls;
95
- }
96
- export class StyleUrlsResolver {
97
- // These resolvers may be called multiple times during the same
98
- // compilation for the same files. Caching is required because these
99
- // resolvers use synchronous system calls to the filesystem, which can
100
- // degrade performance when running compilations for multiple files.
101
- styleUrlsCache = new Map();
102
- resolve(code, id) {
103
- const matchedStyleUrls = getStyleUrls(code);
104
- const entry = this.styleUrlsCache.get(id);
105
- // We're using `matchedStyleUrls` as a key because the code may be changing continuously,
106
- // resulting in the resolver being called multiple times. While the code changes, the
107
- // `styleUrls` may remain constant, which means we should always return the previously
108
- // resolved style URLs.
109
- if (entry && entry.matchedStyleUrls === matchedStyleUrls) {
110
- return entry.styleUrls;
111
- }
112
- const styleUrls = matchedStyleUrls.map((styleUrlPath) => {
113
- return `${styleUrlPath}|${normalizePath(resolve(dirname(id), styleUrlPath))}`;
114
- });
115
- this.styleUrlsCache.set(id, { styleUrls, matchedStyleUrls });
116
- return styleUrls;
117
- }
118
- }
119
- export class TemplateUrlsResolver {
120
- templateUrlsCache = new Map();
121
- resolve(code, id) {
122
- const entry = this.templateUrlsCache.get(id);
123
- if (entry?.code === code) {
124
- return entry.templateUrlPaths;
125
- }
126
- const templateUrlPaths = getTemplateUrls(code).map((url) => `${url}|${normalizePath(resolve(dirname(id), url))}`);
127
- this.templateUrlsCache.set(id, { code, templateUrlPaths });
128
- return templateUrlPaths;
129
- }
63
+ function getTemplateUrls(code) {
64
+ return collectComponentUrls(code).templateUrls;
130
65
  }
66
+ var StyleUrlsResolver = class {
67
+ styleUrlsCache = /* @__PURE__ */ new Map();
68
+ resolve(code, id) {
69
+ const matchedStyleUrls = getStyleUrls(code);
70
+ const entry = this.styleUrlsCache.get(id);
71
+ if (entry && entry.matchedStyleUrls === matchedStyleUrls) return entry.styleUrls;
72
+ const styleUrls = matchedStyleUrls.map((styleUrlPath) => {
73
+ return `${styleUrlPath}|${normalizePath(resolve(dirname(id), styleUrlPath))}`;
74
+ });
75
+ this.styleUrlsCache.set(id, {
76
+ styleUrls,
77
+ matchedStyleUrls
78
+ });
79
+ return styleUrls;
80
+ }
81
+ };
82
+ var TemplateUrlsResolver = class {
83
+ templateUrlsCache = /* @__PURE__ */ new Map();
84
+ resolve(code, id) {
85
+ const entry = this.templateUrlsCache.get(id);
86
+ if (entry?.code === code) return entry.templateUrlPaths;
87
+ const templateUrlPaths = getTemplateUrls(code).map((url) => `${url}|${normalizePath(resolve(dirname(id), url))}`);
88
+ this.templateUrlsCache.set(id, {
89
+ code,
90
+ templateUrlPaths
91
+ });
92
+ return templateUrlPaths;
93
+ }
94
+ };
95
+ //#endregion
96
+ export { StyleUrlsResolver, TemplateUrlsResolver };
97
+
131
98
  //# sourceMappingURL=component-resolvers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"component-resolvers.js","sourceRoot":"","sources":["../../../../../packages/vite-plugin-angular/src/lib/component-resolvers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"component-resolvers.js","names":[],"sources":["../../../../../packages/vite-plugin-angular/src/lib/component-resolvers.ts"],"sourcesContent":["import { dirname, resolve } from 'node:path';\n// OXC parser (native Rust, NAPI-RS) replaces ts-morph for AST extraction.\n// It is ~10-50x faster for the narrow task of pulling property values from\n// Angular component decorators. The Visitor helper from Rolldown walks the\n// ESTree-compatible AST that OXC produces.\nimport { parseSync } from 'oxc-parser';\nimport { Visitor } from 'rolldown/utils';\nimport { normalizePath } from 'vite';\n\n// ---------------------------------------------------------------------------\n// AST helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extracts a string value from an ESTree AST node.\n *\n * Handles three forms that Angular decorators may use:\n * - `Literal` with a string value → `'./foo.css'` / `\"./foo.css\"`\n * - `StringLiteral` (OXC-specific) → same representation\n * - `TemplateLiteral` with zero expressions → `` `./foo.css` ``\n *\n * Uses `any` because OXC's AST mixes standard ESTree nodes with\n * OXC-specific variants (e.g. `StringLiteral`), and the project's\n * tsconfig enforces `noPropertyAccessFromIndexSignature`.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction getStringValue(node: any): string | undefined {\n if (!node) return undefined;\n // Standard ESTree Literal (string value)\n if (node.type === 'Literal' && typeof node.value === 'string') {\n return node.value;\n }\n // OXC-specific StringLiteral node\n if (node.type === 'StringLiteral') {\n return node.value;\n }\n // Template literal with no interpolation (e.g., `./foo.css`)\n if (\n node.type === 'TemplateLiteral' &&\n node.expressions.length === 0 &&\n node.quasis.length === 1\n ) {\n return node.quasis[0].value.cooked ?? node.quasis[0].value.raw;\n }\n return undefined;\n}\n\n/**\n * Parses TypeScript/JS source with OXC and collects `styleUrl`, `styleUrls`,\n * and `templateUrl` property values from Angular `@Component()` decorators\n * in a single AST pass.\n *\n * This replaces the previous ts-morph implementation — OXC parses natively\n * via Rust NAPI bindings, avoiding the overhead of spinning up a full\n * TypeScript `Project` for each file.\n */\nfunction collectComponentUrls(code: string): {\n styleUrls: string[];\n templateUrls: string[];\n} {\n const { program } = parseSync('cmp.ts', code);\n const styleUrls: string[] = [];\n const templateUrls: string[] = [];\n\n const visitor = new Visitor({\n // The Visitor callback receives raw ESTree nodes. We use `any`\n // because OXC's AST includes non-standard node variants and the\n // project tsconfig enforces `noPropertyAccessFromIndexSignature`.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Property(node: any) {\n if (node.key?.type !== 'Identifier') return;\n const name: string = node.key.name;\n\n if (name === 'styleUrls' && node.value?.type === 'ArrayExpression') {\n for (const el of node.value.elements) {\n const val = getStringValue(el);\n if (val !== undefined) styleUrls.push(val);\n }\n }\n\n if (name === 'styleUrl') {\n const val = getStringValue(node.value);\n if (val !== undefined) styleUrls.push(val);\n }\n\n if (name === 'templateUrl') {\n const val = getStringValue(node.value);\n if (val !== undefined) templateUrls.push(val);\n }\n },\n });\n visitor.visit(program);\n\n return { styleUrls, templateUrls };\n}\n\n/** Extract all `styleUrl` / `styleUrls` values from Angular component source. */\nexport function getStyleUrls(code: string): string[] {\n return collectComponentUrls(code).styleUrls;\n}\n\n/** Extract all `templateUrl` values from Angular component source. */\nexport function getTemplateUrls(code: string): string[] {\n return collectComponentUrls(code).templateUrls;\n}\n\n// ---------------------------------------------------------------------------\n// Resolver caches\n// ---------------------------------------------------------------------------\n\ninterface StyleUrlsCacheEntry {\n matchedStyleUrls: string[];\n styleUrls: string[];\n}\n\nexport class StyleUrlsResolver {\n // These resolvers may be called multiple times during the same\n // compilation for the same files. Caching is required because these\n // resolvers use synchronous system calls to the filesystem, which can\n // degrade performance when running compilations for multiple files.\n private readonly styleUrlsCache = new Map<string, StyleUrlsCacheEntry>();\n\n resolve(code: string, id: string): string[] {\n const matchedStyleUrls = getStyleUrls(code);\n const entry = this.styleUrlsCache.get(id);\n // We're using `matchedStyleUrls` as a key because the code may be changing continuously,\n // resulting in the resolver being called multiple times. While the code changes, the\n // `styleUrls` may remain constant, which means we should always return the previously\n // resolved style URLs.\n if (entry && entry.matchedStyleUrls === matchedStyleUrls) {\n return entry.styleUrls;\n }\n\n const styleUrls = matchedStyleUrls.map((styleUrlPath) => {\n return `${styleUrlPath}|${normalizePath(\n resolve(dirname(id), styleUrlPath),\n )}`;\n });\n\n this.styleUrlsCache.set(id, { styleUrls, matchedStyleUrls });\n return styleUrls;\n }\n}\n\ninterface TemplateUrlsCacheEntry {\n code: string;\n templateUrlPaths: string[];\n}\n\nexport class TemplateUrlsResolver {\n private readonly templateUrlsCache = new Map<\n string,\n TemplateUrlsCacheEntry\n >();\n\n resolve(code: string, id: string): string[] {\n const entry = this.templateUrlsCache.get(id);\n if (entry?.code === code) {\n return entry.templateUrlPaths;\n }\n\n const templateUrlPaths = getTemplateUrls(code).map(\n (url) => `${url}|${normalizePath(resolve(dirname(id), url))}`,\n );\n\n this.templateUrlsCache.set(id, { code, templateUrlPaths });\n return templateUrlPaths;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA0BA,SAAS,eAAe,MAA+B;AACrD,KAAI,CAAC,KAAM,QAAO,KAAA;AAElB,KAAI,KAAK,SAAS,aAAa,OAAO,KAAK,UAAU,SACnD,QAAO,KAAK;AAGd,KAAI,KAAK,SAAS,gBAChB,QAAO,KAAK;AAGd,KACE,KAAK,SAAS,qBACd,KAAK,YAAY,WAAW,KAC5B,KAAK,OAAO,WAAW,EAEvB,QAAO,KAAK,OAAO,GAAG,MAAM,UAAU,KAAK,OAAO,GAAG,MAAM;;;;;;;;;;;AAc/D,SAAS,qBAAqB,MAG5B;CACA,MAAM,EAAE,YAAY,UAAU,UAAU,KAAK;CAC7C,MAAM,YAAsB,EAAE;CAC9B,MAAM,eAAyB,EAAE;AAEjB,KAAI,QAAQ,EAK1B,SAAS,MAAW;AAClB,MAAI,KAAK,KAAK,SAAS,aAAc;EACrC,MAAM,OAAe,KAAK,IAAI;AAE9B,MAAI,SAAS,eAAe,KAAK,OAAO,SAAS,kBAC/C,MAAK,MAAM,MAAM,KAAK,MAAM,UAAU;GACpC,MAAM,MAAM,eAAe,GAAG;AAC9B,OAAI,QAAQ,KAAA,EAAW,WAAU,KAAK,IAAI;;AAI9C,MAAI,SAAS,YAAY;GACvB,MAAM,MAAM,eAAe,KAAK,MAAM;AACtC,OAAI,QAAQ,KAAA,EAAW,WAAU,KAAK,IAAI;;AAG5C,MAAI,SAAS,eAAe;GAC1B,MAAM,MAAM,eAAe,KAAK,MAAM;AACtC,OAAI,QAAQ,KAAA,EAAW,cAAa,KAAK,IAAI;;IAGlD,CAAC,CACM,MAAM,QAAQ;AAEtB,QAAO;EAAE;EAAW;EAAc;;;AAIpC,SAAgB,aAAa,MAAwB;AACnD,QAAO,qBAAqB,KAAK,CAAC;;;AAIpC,SAAgB,gBAAgB,MAAwB;AACtD,QAAO,qBAAqB,KAAK,CAAC;;AAYpC,IAAa,oBAAb,MAA+B;CAK7B,iCAAkC,IAAI,KAAkC;CAExE,QAAQ,MAAc,IAAsB;EAC1C,MAAM,mBAAmB,aAAa,KAAK;EAC3C,MAAM,QAAQ,KAAK,eAAe,IAAI,GAAG;AAKzC,MAAI,SAAS,MAAM,qBAAqB,iBACtC,QAAO,MAAM;EAGf,MAAM,YAAY,iBAAiB,KAAK,iBAAiB;AACvD,UAAO,GAAG,aAAa,GAAG,cACxB,QAAQ,QAAQ,GAAG,EAAE,aAAa,CACnC;IACD;AAEF,OAAK,eAAe,IAAI,IAAI;GAAE;GAAW;GAAkB,CAAC;AAC5D,SAAO;;;AASX,IAAa,uBAAb,MAAkC;CAChC,oCAAqC,IAAI,KAGtC;CAEH,QAAQ,MAAc,IAAsB;EAC1C,MAAM,QAAQ,KAAK,kBAAkB,IAAI,GAAG;AAC5C,MAAI,OAAO,SAAS,KAClB,QAAO,MAAM;EAGf,MAAM,mBAAmB,gBAAgB,KAAK,CAAC,KAC5C,QAAQ,GAAG,IAAI,GAAG,cAAc,QAAQ,QAAQ,GAAG,EAAE,IAAI,CAAC,GAC5D;AAED,OAAK,kBAAkB,IAAI,IAAI;GAAE;GAAM;GAAkB,CAAC;AAC1D,SAAO"}
package/src/lib/host.js CHANGED
@@ -1,108 +1,76 @@
1
- import { normalizePath } from 'vite';
2
- import { createHash } from 'node:crypto';
3
- import path from 'node:path';
4
- export function augmentHostWithResources(host, transform, options) {
5
- const resourceHost = host;
6
- resourceHost.readResource = async function (fileName) {
7
- const filePath = normalizePath(fileName);
8
- const content = this.readFile(filePath);
9
- if (content === undefined) {
10
- throw new Error('Unable to locate component resource: ' + fileName);
11
- }
12
- return content;
13
- };
14
- resourceHost.getModifiedResourceFiles = function () {
15
- return options?.sourceFileCache?.modifiedFiles;
16
- };
17
- resourceHost.transformResource = async function (data, context) {
18
- // Only style resources are supported currently
19
- if (context.type !== 'style') {
20
- return null;
21
- }
22
- if (options.inlineComponentStyles) {
23
- const id = createHash('sha256')
24
- .update(context.containingFile)
25
- .update(context.className)
26
- .update(String(context.order))
27
- .update(data)
28
- .digest('hex');
29
- const filename = id + '.' + options.inlineStylesExtension;
30
- options.inlineComponentStyles.set(filename, data);
31
- return { content: filename };
32
- }
33
- // Resource file only exists for external stylesheets
34
- const filename = context.resourceFile ??
35
- context.containingFile.replace('.ts', `.${options?.inlineStylesExtension}`);
36
- let stylesheetResult;
37
- try {
38
- stylesheetResult = await transform(data, `${filename}?direct`);
39
- }
40
- catch (e) {
41
- console.error(`${e}`);
42
- }
43
- return { content: stylesheetResult?.code || '' };
44
- };
45
- resourceHost.resourceNameToFileName = function (resourceName, containingFile) {
46
- const resolvedPath = path.join(path.dirname(containingFile), resourceName);
47
- // All resource names that have template file extensions are assumed to be templates
48
- if (!options.externalComponentStyles || !hasStyleExtension(resolvedPath)) {
49
- return resolvedPath;
50
- }
51
- // For external stylesheets, create a unique identifier and store the mapping
52
- let externalId = options.externalComponentStyles.get(resolvedPath);
53
- externalId ??= createHash('sha256').update(resolvedPath).digest('hex');
54
- const filename = externalId + path.extname(resolvedPath);
55
- options.externalComponentStyles.set(filename, resolvedPath);
56
- return filename;
57
- };
1
+ import path from "node:path";
2
+ import { normalizePath } from "vite";
3
+ import { createHash } from "node:crypto";
4
+ //#region packages/vite-plugin-angular/src/lib/host.ts
5
+ function augmentHostWithResources(host, transform, options) {
6
+ const resourceHost = host;
7
+ resourceHost.readResource = async function(fileName) {
8
+ const filePath = normalizePath(fileName);
9
+ const content = this.readFile(filePath);
10
+ if (content === void 0) throw new Error("Unable to locate component resource: " + fileName);
11
+ return content;
12
+ };
13
+ resourceHost.getModifiedResourceFiles = function() {
14
+ return options?.sourceFileCache?.modifiedFiles;
15
+ };
16
+ resourceHost.transformResource = async function(data, context) {
17
+ if (context.type !== "style") return null;
18
+ if (options.inlineComponentStyles) {
19
+ const filename = createHash("sha256").update(context.containingFile).update(context.className).update(String(context.order)).update(data).digest("hex") + "." + options.inlineStylesExtension;
20
+ options.inlineComponentStyles.set(filename, data);
21
+ return { content: filename };
22
+ }
23
+ const filename = context.resourceFile ?? context.containingFile.replace(".ts", `.${options?.inlineStylesExtension}`);
24
+ let stylesheetResult;
25
+ try {
26
+ stylesheetResult = await transform(data, `${filename}?direct`);
27
+ } catch (e) {
28
+ console.error(`${e}`);
29
+ }
30
+ return { content: stylesheetResult?.code || "" };
31
+ };
32
+ resourceHost.resourceNameToFileName = function(resourceName, containingFile) {
33
+ const resolvedPath = path.join(path.dirname(containingFile), resourceName);
34
+ if (!options.externalComponentStyles || !hasStyleExtension(resolvedPath)) return resolvedPath;
35
+ let externalId = options.externalComponentStyles.get(resolvedPath);
36
+ externalId ??= createHash("sha256").update(resolvedPath).digest("hex");
37
+ const filename = externalId + path.extname(resolvedPath);
38
+ options.externalComponentStyles.set(filename, resolvedPath);
39
+ return filename;
40
+ };
58
41
  }
59
- export function augmentProgramWithVersioning(program) {
60
- const baseGetSourceFiles = program.getSourceFiles;
61
- program.getSourceFiles = function (...parameters) {
62
- const files = baseGetSourceFiles(...parameters);
63
- for (const file of files) {
64
- file.version ??= createHash('sha256').update(file.text).digest('hex');
65
- }
66
- return files;
67
- };
42
+ function augmentProgramWithVersioning(program) {
43
+ const baseGetSourceFiles = program.getSourceFiles;
44
+ program.getSourceFiles = function(...parameters) {
45
+ const files = baseGetSourceFiles(...parameters);
46
+ for (const file of files) file.version ??= createHash("sha256").update(file.text).digest("hex");
47
+ return files;
48
+ };
68
49
  }
69
- export function augmentHostWithCaching(host, cache) {
70
- const baseGetSourceFile = host.getSourceFile;
71
- host.getSourceFile = function (fileName, languageVersion, onError, shouldCreateNewSourceFile, ...parameters) {
72
- if (!shouldCreateNewSourceFile && cache.has(fileName)) {
73
- return cache.get(fileName);
74
- }
75
- const file = baseGetSourceFile.call(host, fileName, languageVersion, onError, true, ...parameters);
76
- if (file) {
77
- cache.set(fileName, file);
78
- }
79
- return file;
80
- };
50
+ function augmentHostWithCaching(host, cache) {
51
+ const baseGetSourceFile = host.getSourceFile;
52
+ host.getSourceFile = function(fileName, languageVersion, onError, shouldCreateNewSourceFile, ...parameters) {
53
+ if (!shouldCreateNewSourceFile && cache.has(fileName)) return cache.get(fileName);
54
+ const file = baseGetSourceFile.call(host, fileName, languageVersion, onError, true, ...parameters);
55
+ if (file) cache.set(fileName, file);
56
+ return file;
57
+ };
81
58
  }
82
- export function mergeTransformers(first, second) {
83
- const result = {};
84
- if (first.before || second.before) {
85
- result.before = [...(first.before || []), ...(second.before || [])];
86
- }
87
- if (first.after || second.after) {
88
- result.after = [...(first.after || []), ...(second.after || [])];
89
- }
90
- if (first.afterDeclarations || second.afterDeclarations) {
91
- result.afterDeclarations = [
92
- ...(first.afterDeclarations || []),
93
- ...(second.afterDeclarations || []),
94
- ];
95
- }
96
- return result;
59
+ function mergeTransformers(first, second) {
60
+ const result = {};
61
+ if (first.before || second.before) result.before = [...first.before || [], ...second.before || []];
62
+ if (first.after || second.after) result.after = [...first.after || [], ...second.after || []];
63
+ if (first.afterDeclarations || second.afterDeclarations) result.afterDeclarations = [...first.afterDeclarations || [], ...second.afterDeclarations || []];
64
+ return result;
97
65
  }
98
66
  function hasStyleExtension(file) {
99
- const extension = path.extname(file).toLowerCase();
100
- switch (extension) {
101
- case '.css':
102
- case '.scss':
103
- return true;
104
- default:
105
- return false;
106
- }
67
+ switch (path.extname(file).toLowerCase()) {
68
+ case ".css":
69
+ case ".scss": return true;
70
+ default: return false;
71
+ }
107
72
  }
73
+ //#endregion
74
+ export { augmentHostWithCaching, augmentHostWithResources, augmentProgramWithVersioning, mergeTransformers };
75
+
108
76
  //# sourceMappingURL=host.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"host.js","sourceRoot":"","sources":["../../../../../packages/vite-plugin-angular/src/lib/host.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"host.js","names":[],"sources":["../../../../../packages/vite-plugin-angular/src/lib/host.ts"],"sourcesContent":["import type { CompilerHost } from '@angular/compiler-cli';\nimport { normalizePath } from 'vite';\n\nimport * as ts from 'typescript';\n\nimport { createHash } from 'node:crypto';\nimport path from 'node:path';\nimport type { SourceFileCache } from './utils/source-file-cache.js';\n\nexport function augmentHostWithResources(\n host: ts.CompilerHost,\n transform: (\n code: string,\n id: string,\n options?: { ssr?: boolean },\n ) => ReturnType<any> | null,\n options: {\n inlineStylesExtension: string;\n isProd?: boolean;\n inlineComponentStyles?: Map<string, string>;\n externalComponentStyles?: Map<string, string>;\n sourceFileCache?: SourceFileCache;\n },\n): void {\n const resourceHost = host as CompilerHost;\n\n resourceHost.readResource = async function (fileName: string) {\n const filePath = normalizePath(fileName);\n\n const content = (this as any).readFile(filePath);\n\n if (content === undefined) {\n throw new Error('Unable to locate component resource: ' + fileName);\n }\n\n return content;\n };\n\n resourceHost.getModifiedResourceFiles = function () {\n return options?.sourceFileCache?.modifiedFiles;\n };\n\n resourceHost.transformResource = async function (data, context) {\n // Only style resources are supported currently\n if (context.type !== 'style') {\n return null;\n }\n\n if (options.inlineComponentStyles) {\n const id = createHash('sha256')\n .update(context.containingFile)\n .update(context.className)\n .update(String(context.order))\n .update(data)\n .digest('hex');\n const filename = id + '.' + options.inlineStylesExtension;\n options.inlineComponentStyles.set(filename, data);\n return { content: filename };\n }\n\n // Resource file only exists for external stylesheets\n const filename =\n context.resourceFile ??\n context.containingFile.replace(\n '.ts',\n `.${options?.inlineStylesExtension}`,\n );\n\n let stylesheetResult;\n\n try {\n stylesheetResult = await transform(data, `${filename}?direct`);\n } catch (e) {\n console.error(`${e}`);\n }\n\n return { content: stylesheetResult?.code || '' };\n };\n\n resourceHost.resourceNameToFileName = function (\n resourceName,\n containingFile,\n ) {\n const resolvedPath = path.join(path.dirname(containingFile), resourceName);\n\n // All resource names that have template file extensions are assumed to be templates\n if (!options.externalComponentStyles || !hasStyleExtension(resolvedPath)) {\n return resolvedPath;\n }\n\n // For external stylesheets, create a unique identifier and store the mapping\n let externalId = options.externalComponentStyles.get(resolvedPath);\n externalId ??= createHash('sha256').update(resolvedPath).digest('hex');\n\n const filename = externalId + path.extname(resolvedPath);\n\n options.externalComponentStyles.set(filename, resolvedPath);\n\n return filename;\n };\n}\n\nexport function augmentProgramWithVersioning(program: ts.Program): void {\n const baseGetSourceFiles = program.getSourceFiles;\n program.getSourceFiles = function (...parameters) {\n const files: readonly (ts.SourceFile & { version?: string })[] =\n baseGetSourceFiles(...parameters);\n\n for (const file of files) {\n file.version ??= createHash('sha256').update(file.text).digest('hex');\n }\n\n return files;\n };\n}\n\nexport function augmentHostWithCaching(\n host: ts.CompilerHost,\n cache: Map<string, ts.SourceFile>,\n): void {\n const baseGetSourceFile = host.getSourceFile;\n host.getSourceFile = function (\n fileName,\n languageVersion,\n onError,\n shouldCreateNewSourceFile,\n ...parameters\n ) {\n if (!shouldCreateNewSourceFile && cache.has(fileName)) {\n return cache.get(fileName);\n }\n\n const file = baseGetSourceFile.call(\n host,\n fileName,\n languageVersion,\n onError,\n true,\n ...parameters,\n );\n\n if (file) {\n cache.set(fileName, file);\n }\n\n return file;\n };\n}\n\nexport function mergeTransformers(\n first: ts.CustomTransformers,\n second: ts.CustomTransformers,\n): ts.CustomTransformers {\n const result: ts.CustomTransformers = {};\n\n if (first.before || second.before) {\n result.before = [...(first.before || []), ...(second.before || [])];\n }\n\n if (first.after || second.after) {\n result.after = [...(first.after || []), ...(second.after || [])];\n }\n\n if (first.afterDeclarations || second.afterDeclarations) {\n result.afterDeclarations = [\n ...(first.afterDeclarations || []),\n ...(second.afterDeclarations || []),\n ];\n }\n\n return result;\n}\n\nfunction hasStyleExtension(file: string): boolean {\n const extension = path.extname(file).toLowerCase();\n\n switch (extension) {\n case '.css':\n case '.scss':\n return true;\n default:\n return false;\n }\n}\n"],"mappings":"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"}
@@ -1,65 +1,53 @@
1
- import { resolve } from 'node:path';
2
- import { normalizePath } from 'vite';
3
- const ANGULAR_COMPONENT_PREFIX = '/@ng/component';
4
- const FILE_PREFIX = 'file:';
5
- export function liveReloadPlugin({ classNames, fileEmitter, }) {
6
- return {
7
- name: 'analogjs-live-reload-plugin',
8
- apply: 'serve',
9
- configureServer(server) {
10
- const angularComponentMiddleware = async (req, res, next) => {
11
- if (req.url === undefined || res.writableEnded) {
12
- return;
13
- }
14
- if (!req.url.includes(ANGULAR_COMPONENT_PREFIX)) {
15
- next();
16
- return;
17
- }
18
- const requestUrl = new URL(req.url, 'http://localhost');
19
- const componentId = requestUrl.searchParams.get('c');
20
- if (!componentId) {
21
- res.statusCode = 400;
22
- res.end();
23
- return;
24
- }
25
- const [fileId] = decodeURIComponent(componentId).split('@');
26
- const resolvedId = normalizePath(resolve(process.cwd(), fileId));
27
- const invalidated = !!server.moduleGraph.getModuleById(resolvedId)
28
- ?.lastInvalidationTimestamp && classNames.get(resolvedId);
29
- // don't send an HMR update until the file has been invalidated
30
- if (!invalidated) {
31
- res.setHeader('Content-Type', 'text/javascript');
32
- res.setHeader('Cache-Control', 'no-cache');
33
- res.end('');
34
- return;
35
- }
36
- const result = fileEmitter(resolvedId);
37
- res.setHeader('Content-Type', 'text/javascript');
38
- res.setHeader('Cache-Control', 'no-cache');
39
- res.end(`${result?.hmrUpdateCode || ''}`);
40
- };
41
- server.middlewares.use(angularComponentMiddleware);
42
- },
43
- resolveId(id, _importer, options) {
44
- if (options?.ssr &&
45
- id.startsWith(FILE_PREFIX) &&
46
- id.includes(ANGULAR_COMPONENT_PREFIX)) {
47
- return `\0${id}`;
48
- }
49
- return undefined;
50
- },
51
- load(id, options) {
52
- if (options?.ssr && id.includes(ANGULAR_COMPONENT_PREFIX)) {
53
- const requestUrl = new URL(id.slice(1), 'http://localhost');
54
- const componentId = requestUrl.searchParams.get('c');
55
- if (!componentId) {
56
- return;
57
- }
58
- const result = fileEmitter(normalizePath(resolve(process.cwd(), decodeURIComponent(componentId).split('@')[0])));
59
- return result?.hmrUpdateCode || '';
60
- }
61
- return;
62
- },
63
- };
1
+ import { resolve } from "node:path";
2
+ import { normalizePath } from "vite";
3
+ //#region packages/vite-plugin-angular/src/lib/live-reload-plugin.ts
4
+ var ANGULAR_COMPONENT_PREFIX = "/@ng/component";
5
+ var FILE_PREFIX = "file:";
6
+ function liveReloadPlugin({ classNames, fileEmitter }) {
7
+ return {
8
+ name: "analogjs-live-reload-plugin",
9
+ apply: "serve",
10
+ configureServer(server) {
11
+ const angularComponentMiddleware = async (req, res, next) => {
12
+ if (req.url === void 0 || res.writableEnded) return;
13
+ if (!req.url.includes(ANGULAR_COMPONENT_PREFIX)) {
14
+ next();
15
+ return;
16
+ }
17
+ const componentId = new URL(req.url, "http://localhost").searchParams.get("c");
18
+ if (!componentId) {
19
+ res.statusCode = 400;
20
+ res.end();
21
+ return;
22
+ }
23
+ const [fileId] = decodeURIComponent(componentId).split("@");
24
+ const resolvedId = normalizePath(resolve(process.cwd(), fileId));
25
+ if (!(!!server.moduleGraph.getModuleById(resolvedId)?.lastInvalidationTimestamp && classNames.get(resolvedId))) {
26
+ res.setHeader("Content-Type", "text/javascript");
27
+ res.setHeader("Cache-Control", "no-cache");
28
+ res.end("");
29
+ return;
30
+ }
31
+ const result = fileEmitter(resolvedId);
32
+ res.setHeader("Content-Type", "text/javascript");
33
+ res.setHeader("Cache-Control", "no-cache");
34
+ res.end(`${result?.hmrUpdateCode || ""}`);
35
+ };
36
+ server.middlewares.use(angularComponentMiddleware);
37
+ },
38
+ resolveId(id, _importer, options) {
39
+ if (options?.ssr && id.startsWith(FILE_PREFIX) && id.includes(ANGULAR_COMPONENT_PREFIX)) return `\0${id}`;
40
+ },
41
+ load(id, options) {
42
+ if (options?.ssr && id.includes(ANGULAR_COMPONENT_PREFIX)) {
43
+ const componentId = new URL(id.slice(1), "http://localhost").searchParams.get("c");
44
+ if (!componentId) return;
45
+ return fileEmitter(normalizePath(resolve(process.cwd(), decodeURIComponent(componentId).split("@")[0])))?.hmrUpdateCode || "";
46
+ }
47
+ }
48
+ };
64
49
  }
50
+ //#endregion
51
+ export { liveReloadPlugin };
52
+
65
53
  //# sourceMappingURL=live-reload-plugin.js.map