@analogjs/platform 3.0.0-beta.7 → 3.0.0-beta.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@analogjs/platform",
3
- "version": "3.0.0-beta.7",
3
+ "version": "3.0.0-beta.9",
4
4
  "description": "The fullstack meta-framework for Angular",
5
5
  "type": "module",
6
6
  "author": "Brandon Roberts <robertsbt@gmail.com>",
@@ -31,7 +31,7 @@
31
31
  "url": "https://github.com/sponsors/brandonroberts"
32
32
  },
33
33
  "dependencies": {
34
- "@analogjs/vite-plugin-angular": "3.0.0-beta.7",
34
+ "@analogjs/vite-plugin-angular": "3.0.0-beta.9",
35
35
  "es-toolkit": "^1.45.1",
36
36
  "front-matter": "^4.0.2",
37
37
  "magic-string": "^0.30.21",
@@ -49,9 +49,9 @@
49
49
  "nitro": "3.0.260903-beta"
50
50
  },
51
51
  "peerDependencies": {
52
- "@nx/angular": "^23.2.0",
53
- "@nx/devkit": "^23.2.0",
54
- "@nx/vite": "^23.2.0",
52
+ "@nx/angular": "^23.2.0 || ^24.0.0",
53
+ "@nx/devkit": "^23.2.0 || ^24.0.0",
54
+ "@nx/vite": "^23.2.0 || ^24.0.0",
55
55
  "marked": "^18.0.0",
56
56
  "marked-gfm-heading-id": "^4.1.3",
57
57
  "marked-highlight": "^2.2.3",
@@ -4,6 +4,12 @@ import { readFileSync } from "node:fs";
4
4
  import * as vite from "vite";
5
5
  import { globSync } from "tinyglobby";
6
6
  //#region packages/platform/src/lib/content-plugin.ts
7
+ function toModuleValue(value) {
8
+ if (value instanceof Date) return `new Date(${JSON.stringify(value.toISOString())})`;
9
+ if (Array.isArray(value)) return `[${value.map(toModuleValue).join(",")}]`;
10
+ if (value && typeof value === "object") return `{${Object.entries(value).map(([key, entry]) => `${JSON.stringify(key)}:${toModuleValue(entry)}`).join(",")}}`;
11
+ return JSON.stringify(value) ?? "undefined";
12
+ }
7
13
  /**
8
14
  * Content plugin that provides markdown and content file processing for Analog.
9
15
  *
@@ -167,13 +173,13 @@ function contentPlugin({ highlighter, markedOptions, shikiOptions, prismOptions
167
173
  }
168
174
  }
169
175
  const fm = await import("front-matter");
170
- const { body, frontmatter } = (fm.default || fm)(readFileSync(id.split("?")[0], "utf8"));
176
+ const { body, attributes } = (fm.default || fm)(readFileSync(id.split("?")[0], "utf8"));
171
177
  const { getMarkedSetup } = await import("./content/marked/index.js");
172
178
  const mdContent = await getMarkedSetup({
173
179
  mangle: true,
174
180
  ...markedOptions || {}
175
181
  }, markedHighlighter).getMarkedInstance().parse(body);
176
- return `export default ${JSON.stringify(`---\n${frontmatter}\n---\n\n${mdContent}`)}`;
182
+ return `export default ${JSON.stringify(mdContent)};\nexport const metadata = ${toModuleValue(attributes)};`;
177
183
  }
178
184
  },
179
185
  ...contentDiscoveryPlugins
@@ -1 +1 @@
1
- {"version":3,"file":"content-plugin.js","names":[],"sources":["../../../src/lib/content-plugin.ts"],"sourcesContent":["import * as vite from 'vite';\nimport { readFileSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport { globSync } from 'tinyglobby';\n\nimport type { WithShikiHighlighterOptions } from './content/shiki/options.js';\nimport type { MarkedContentHighlighter } from './content/marked/marked-content-highlighter.js';\nimport type { WithPrismHighlighterOptions } from './content/prism/options.js';\nimport type { WithMarkedOptions } from './content/marked/index.js';\nimport type { Options } from './options.js';\nimport { getBundleOptionsKey } from './utils/rolldown.js';\n\ninterface Content {\n code: string;\n attributes: string;\n}\n\nexport type ContentPluginOptions = {\n highlighter?: 'shiki' | 'prism';\n markedOptions?: WithMarkedOptions;\n shikiOptions?: WithShikiHighlighterOptions;\n prismOptions?: WithPrismHighlighterOptions;\n};\n\n/**\n * Content plugin that provides markdown and content file processing for Analog.\n *\n * IMPORTANT: This plugin uses tinyglobby for file discovery.\n * Key pitfall with { dot: true }:\n * - Returns relative paths from cwd (e.g., \"apps/blog-app/src/content/...\")\n * - These paths CANNOT be used directly in ES module imports\n * - Relative paths without ./ or ../ are treated as package names\n * - Must convert to absolute paths for imports to work correctly\n */\nexport function contentPlugin(\n {\n highlighter,\n markedOptions,\n shikiOptions,\n prismOptions,\n }: ContentPluginOptions = {},\n options?: Options,\n): vite.Plugin[] {\n const cache = new Map<string, Content>();\n // The content list placeholder can be transformed several times during serve.\n // Caching the discovered markdown paths keeps those repeat passes cheap.\n let contentFilesListCache: string[] | undefined;\n\n let markedHighlighter: MarkedContentHighlighter;\n const workspaceRoot = vite.normalizePath(\n options?.workspaceRoot ?? process.env['NX_WORKSPACE_ROOT'] ?? process.cwd(),\n );\n let config: vite.UserConfig;\n let root: string;\n // Keep discovery and invalidation aligned by deriving both from the same\n // normalized content roots. That way external content dirs participate in\n // cache busting exactly the same way they participate in glob discovery.\n // Initialized once in the `config` hook after `root` is resolved — all\n // inputs (`root`, `workspaceRoot`, `options`) are stable after that point.\n let contentRootDirs: string[];\n const normalizeContentDir = (dir: string) => {\n const normalized = vite.normalizePath(\n dir.startsWith('/')\n ? `${workspaceRoot}${dir}`\n : resolve(workspaceRoot, dir),\n );\n return normalized.endsWith('/') ? normalized.slice(0, -1) : normalized;\n };\n const initContentRootDirs = () => {\n contentRootDirs = [\n vite.normalizePath(`${root}/src/content`),\n ...(options?.additionalContentDirs || []).map(normalizeContentDir),\n ];\n };\n const discoverContentFilesList = () => {\n contentFilesListCache ??= globSync(\n contentRootDirs.map((dir) => `${dir}/**/*.md`),\n { dot: true },\n );\n\n return contentFilesListCache;\n };\n const resolveContentModulePath = (module: string) =>\n vite.normalizePath(\n module.startsWith('/') ? module : `${workspaceRoot}/${module}`,\n );\n const getContentModuleKey = (module: string) => {\n const absolutePath = resolveContentModulePath(module);\n const relativeToRoot = vite.normalizePath(relative(root, absolutePath));\n // `startsWith(root)` is not safe here because sibling directories such as\n // `/apps/my-app-tools` also start with `/apps/my-app`. A relative path only\n // represents in-app content when it stays within `root`.\n const isInApp =\n !relativeToRoot.startsWith('..') && !relativeToRoot.startsWith('/');\n\n // Both branches prepend `/` so generated keys are always absolute-\n // looking (`/src/content/...` for in-app, `/libs/shared/...` for\n // workspace-external). Downstream consumers like content-files-token\n // rely on the leading `/` for slug extraction regexes.\n return isInApp\n ? `/${relativeToRoot}`\n : `/${vite.normalizePath(relative(workspaceRoot, absolutePath))}`;\n };\n\n const contentDiscoveryPlugins: vite.Plugin[] = [\n {\n name: 'analog-content-glob-routes',\n config(_config) {\n config = _config;\n root = vite.normalizePath(\n resolve(workspaceRoot, config.root || '.') || '.',\n );\n initContentRootDirs();\n },\n // Vite 8 / Rolldown \"filtered transform\" — the `filter.code` string\n // tells the bundler to skip this handler entirely for modules whose\n // source does not contain the substring, avoiding unnecessary JS→Rust\n // round-trips. The inner `code.includes()` guard is kept for Vite 7\n // compat where filters are not evaluated by the bundler.\n transform: {\n filter: {\n code: 'ANALOG_CONTENT_FILE_LIST',\n },\n handler(code) {\n if (code.includes('ANALOG_CONTENT_FILE_LIST')) {\n const contentFilesList = discoverContentFilesList();\n\n const eagerImports: string[] = [];\n\n contentFilesList.forEach((module, index) => {\n // CRITICAL: tinyglobby returns relative paths like \"apps/blog-app/src/content/file.md\"\n // These MUST be converted to absolute paths for ES module imports\n // Otherwise Node.js treats \"apps\" as a package name and throws \"Cannot find package 'apps'\"\n const absolutePath = resolveContentModulePath(module);\n eagerImports.push(\n `import { default as analog_module_${index} } from \"${absolutePath}?analog-content-list=true\";`,\n );\n });\n\n // Match just the assignment (not the declaration) so the rewrite\n // works whether the source uses `const`, `let`, `var`, or\n // `export const` — including the post-Rolldown `var X = {};`\n // form — without destroying the declaration that keeps the\n // module binding exported.\n let result = code.replace(\n /ANALOG_CONTENT_FILE_LIST\\s*=\\s*\\{\\s*\\}/,\n `ANALOG_CONTENT_FILE_LIST = {${contentFilesList.map(\n (module, index) =>\n `\"${getContentModuleKey(module)}\": analog_module_${index}`,\n )}}`,\n );\n\n if (!code.includes('analog_module_')) {\n result = `${eagerImports.join('\\n')}\\n${result}`;\n }\n\n return {\n code: result,\n map: { mappings: '' },\n };\n }\n\n return;\n },\n },\n },\n {\n name: 'analogjs-invalidate-content-dirs',\n configureServer(server) {\n function invalidateContent(path: string) {\n const normalizedPath = vite.normalizePath(path);\n const isContentPath = contentRootDirs.some(\n (dir) =>\n normalizedPath === dir || normalizedPath.startsWith(`${dir}/`),\n );\n\n if (isContentPath) {\n // The file set only changes on add/remove because this watcher is\n // intentionally scoped to those events. Clear the list cache so the\n // next transform sees the updated directory contents.\n contentFilesListCache = undefined;\n server.moduleGraph.fileToModulesMap.forEach((mods) => {\n mods.forEach((mod) => {\n if (\n mod.id?.includes('analogjs') &&\n mod.id?.includes('content')\n ) {\n server.moduleGraph.invalidateModule(mod);\n\n mod.importers.forEach((imp) => {\n server.moduleGraph.invalidateModule(imp);\n });\n }\n });\n });\n\n server.ws.send('analog:debug-full-reload', {\n plugin: 'platform:content-plugin',\n reason: 'content-file-set-changed',\n path: normalizedPath,\n });\n server.ws.send({\n type: 'full-reload',\n });\n }\n }\n\n server.watcher.on('add', invalidateContent);\n server.watcher.on('unlink', invalidateContent);\n },\n },\n ];\n\n if (!highlighter) {\n return [\n {\n name: 'analogjs-external-content',\n config() {\n const bundleOptionsKey = getBundleOptionsKey();\n return {\n build: {\n [bundleOptionsKey]: {\n external: ['@analogjs/content'],\n },\n },\n };\n },\n },\n {\n name: 'analogjs-exclude-content-import',\n transform: {\n filter: {\n code: '@analogjs/content',\n },\n handler(code) {\n /**\n * Remove the package so it doesn't get\n * referenced when building for serverless\n * functions.\n */\n if (code.includes(`import('@analogjs/content')`)) {\n return {\n code: code.replace(\n `import('@analogjs/content')`,\n 'Promise.resolve({})',\n ),\n };\n }\n\n return;\n },\n },\n },\n ...contentDiscoveryPlugins,\n ];\n }\n\n return [\n {\n name: 'analogjs-content-frontmatter',\n // Filter by module ID so only `?analog-content-list=true` virtual\n // imports enter the handler. Returns `moduleSideEffects: false` so\n // Rolldown can tree-shake unused content list entries.\n transform: {\n filter: {\n id: /analog-content-list=true/,\n },\n async handler(code, id) {\n const cachedContent = cache.get(id);\n // There's no reason to run `readFileSync` and frontmatter parsing if the\n // `transform` hook is called with the same code. In such cases, we can simply\n // return the cached attributes, which is faster than repeatedly reading files\n // synchronously during the build process.\n if (cachedContent?.code === code) {\n return {\n code: `export default ${cachedContent.attributes}`,\n moduleSideEffects: false,\n };\n }\n\n const fm: any = await import('front-matter');\n // The `default` property will be available in CommonJS environment, for instance,\n // when running unit tests. It's safe to retrieve `default` first, since we still\n // fallback to the original implementation.\n const frontmatter = fm.default || fm;\n const fileContents = readFileSync(id.split('?')[0], 'utf8');\n const { attributes } = frontmatter(fileContents);\n const content = {\n code,\n attributes: JSON.stringify(attributes),\n };\n cache.set(id, content);\n\n return {\n code: `export default ${content.attributes}`,\n moduleSideEffects: false,\n };\n },\n },\n },\n {\n name: 'analogjs-content-file',\n enforce: 'post',\n async load(id) {\n if (!id.includes('analog-content-file=true')) {\n return;\n }\n\n if (!markedHighlighter) {\n if (highlighter === 'shiki') {\n const { getShikiHighlighter } =\n await import('./content/shiki/index.js');\n markedHighlighter = getShikiHighlighter(shikiOptions);\n } else {\n const { getPrismHighlighter } =\n await import('./content/prism/index.js');\n markedHighlighter = getPrismHighlighter();\n\n const langs = [\n 'bash',\n 'css',\n 'javascript',\n 'json',\n 'markup',\n 'typescript',\n ];\n\n if (\n Array.isArray(prismOptions?.additionalLangs) &&\n prismOptions?.additionalLangs?.length > 0\n ) {\n langs.push(...prismOptions.additionalLangs);\n }\n\n const loadLanguages = await import('prismjs/components/index.js');\n\n (\n loadLanguages as unknown as { default: (...args: any[]) => any }\n ).default(langs);\n }\n }\n\n const fm: any = await import('front-matter');\n // The `default` property will be available in CommonJS environment, for instance,\n // when running unit tests. It's safe to retrieve `default` first, since we still\n // fallback to the original implementation.\n const frontmatterFn = fm.default || fm;\n const fileContents = readFileSync(id.split('?')[0], 'utf8');\n const { body, frontmatter } = frontmatterFn(fileContents);\n\n // parse markdown and highlight\n const { getMarkedSetup } = await import('./content/marked/index.js');\n const markedSetupService = getMarkedSetup(\n { mangle: true, ...(markedOptions || {}) },\n markedHighlighter,\n );\n const mdContent = (await markedSetupService\n .getMarkedInstance()\n .parse(body)) as unknown as string;\n\n return `export default ${JSON.stringify(\n `---\\n${frontmatter}\\n---\\n\\n${mdContent}`,\n )}`;\n },\n },\n ...contentDiscoveryPlugins,\n ];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"content-plugin.js","names":[],"sources":["../../../src/lib/content-plugin.ts"],"sourcesContent":["import * as vite from 'vite';\nimport { readFileSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport { globSync } from 'tinyglobby';\n\nimport type { WithShikiHighlighterOptions } from './content/shiki/options.js';\nimport type { MarkedContentHighlighter } from './content/marked/marked-content-highlighter.js';\nimport type { WithPrismHighlighterOptions } from './content/prism/options.js';\nimport type { WithMarkedOptions } from './content/marked/index.js';\nimport type { Options } from './options.js';\nimport { getBundleOptionsKey } from './utils/rolldown.js';\n\ninterface Content {\n code: string;\n attributes: string;\n}\n\n// Serializes parsed frontmatter as a JS expression, keeping YAML timestamps as Dates.\nfunction toModuleValue(value: unknown): string {\n if (value instanceof Date) {\n return `new Date(${JSON.stringify(value.toISOString())})`;\n }\n if (Array.isArray(value)) {\n return `[${value.map(toModuleValue).join(',')}]`;\n }\n if (value && typeof value === 'object') {\n return `{${Object.entries(value)\n .map(([key, entry]) => `${JSON.stringify(key)}:${toModuleValue(entry)}`)\n .join(',')}}`;\n }\n return JSON.stringify(value) ?? 'undefined';\n}\n\nexport type ContentPluginOptions = {\n highlighter?: 'shiki' | 'prism';\n markedOptions?: WithMarkedOptions;\n shikiOptions?: WithShikiHighlighterOptions;\n prismOptions?: WithPrismHighlighterOptions;\n};\n\n/**\n * Content plugin that provides markdown and content file processing for Analog.\n *\n * IMPORTANT: This plugin uses tinyglobby for file discovery.\n * Key pitfall with { dot: true }:\n * - Returns relative paths from cwd (e.g., \"apps/blog-app/src/content/...\")\n * - These paths CANNOT be used directly in ES module imports\n * - Relative paths without ./ or ../ are treated as package names\n * - Must convert to absolute paths for imports to work correctly\n */\nexport function contentPlugin(\n {\n highlighter,\n markedOptions,\n shikiOptions,\n prismOptions,\n }: ContentPluginOptions = {},\n options?: Options,\n): vite.Plugin[] {\n const cache = new Map<string, Content>();\n // The content list placeholder can be transformed several times during serve.\n // Caching the discovered markdown paths keeps those repeat passes cheap.\n let contentFilesListCache: string[] | undefined;\n\n let markedHighlighter: MarkedContentHighlighter;\n const workspaceRoot = vite.normalizePath(\n options?.workspaceRoot ?? process.env['NX_WORKSPACE_ROOT'] ?? process.cwd(),\n );\n let config: vite.UserConfig;\n let root: string;\n // Keep discovery and invalidation aligned by deriving both from the same\n // normalized content roots. That way external content dirs participate in\n // cache busting exactly the same way they participate in glob discovery.\n // Initialized once in the `config` hook after `root` is resolved — all\n // inputs (`root`, `workspaceRoot`, `options`) are stable after that point.\n let contentRootDirs: string[];\n const normalizeContentDir = (dir: string) => {\n const normalized = vite.normalizePath(\n dir.startsWith('/')\n ? `${workspaceRoot}${dir}`\n : resolve(workspaceRoot, dir),\n );\n return normalized.endsWith('/') ? normalized.slice(0, -1) : normalized;\n };\n const initContentRootDirs = () => {\n contentRootDirs = [\n vite.normalizePath(`${root}/src/content`),\n ...(options?.additionalContentDirs || []).map(normalizeContentDir),\n ];\n };\n const discoverContentFilesList = () => {\n contentFilesListCache ??= globSync(\n contentRootDirs.map((dir) => `${dir}/**/*.md`),\n { dot: true },\n );\n\n return contentFilesListCache;\n };\n const resolveContentModulePath = (module: string) =>\n vite.normalizePath(\n module.startsWith('/') ? module : `${workspaceRoot}/${module}`,\n );\n const getContentModuleKey = (module: string) => {\n const absolutePath = resolveContentModulePath(module);\n const relativeToRoot = vite.normalizePath(relative(root, absolutePath));\n // `startsWith(root)` is not safe here because sibling directories such as\n // `/apps/my-app-tools` also start with `/apps/my-app`. A relative path only\n // represents in-app content when it stays within `root`.\n const isInApp =\n !relativeToRoot.startsWith('..') && !relativeToRoot.startsWith('/');\n\n // Both branches prepend `/` so generated keys are always absolute-\n // looking (`/src/content/...` for in-app, `/libs/shared/...` for\n // workspace-external). Downstream consumers like content-files-token\n // rely on the leading `/` for slug extraction regexes.\n return isInApp\n ? `/${relativeToRoot}`\n : `/${vite.normalizePath(relative(workspaceRoot, absolutePath))}`;\n };\n\n const contentDiscoveryPlugins: vite.Plugin[] = [\n {\n name: 'analog-content-glob-routes',\n config(_config) {\n config = _config;\n root = vite.normalizePath(\n resolve(workspaceRoot, config.root || '.') || '.',\n );\n initContentRootDirs();\n },\n // Vite 8 / Rolldown \"filtered transform\" — the `filter.code` string\n // tells the bundler to skip this handler entirely for modules whose\n // source does not contain the substring, avoiding unnecessary JS→Rust\n // round-trips. The inner `code.includes()` guard is kept for Vite 7\n // compat where filters are not evaluated by the bundler.\n transform: {\n filter: {\n code: 'ANALOG_CONTENT_FILE_LIST',\n },\n handler(code) {\n if (code.includes('ANALOG_CONTENT_FILE_LIST')) {\n const contentFilesList = discoverContentFilesList();\n\n const eagerImports: string[] = [];\n\n contentFilesList.forEach((module, index) => {\n // CRITICAL: tinyglobby returns relative paths like \"apps/blog-app/src/content/file.md\"\n // These MUST be converted to absolute paths for ES module imports\n // Otherwise Node.js treats \"apps\" as a package name and throws \"Cannot find package 'apps'\"\n const absolutePath = resolveContentModulePath(module);\n eagerImports.push(\n `import { default as analog_module_${index} } from \"${absolutePath}?analog-content-list=true\";`,\n );\n });\n\n // Match just the assignment (not the declaration) so the rewrite\n // works whether the source uses `const`, `let`, `var`, or\n // `export const` — including the post-Rolldown `var X = {};`\n // form — without destroying the declaration that keeps the\n // module binding exported.\n let result = code.replace(\n /ANALOG_CONTENT_FILE_LIST\\s*=\\s*\\{\\s*\\}/,\n `ANALOG_CONTENT_FILE_LIST = {${contentFilesList.map(\n (module, index) =>\n `\"${getContentModuleKey(module)}\": analog_module_${index}`,\n )}}`,\n );\n\n if (!code.includes('analog_module_')) {\n result = `${eagerImports.join('\\n')}\\n${result}`;\n }\n\n return {\n code: result,\n map: { mappings: '' },\n };\n }\n\n return;\n },\n },\n },\n {\n name: 'analogjs-invalidate-content-dirs',\n configureServer(server) {\n function invalidateContent(path: string) {\n const normalizedPath = vite.normalizePath(path);\n const isContentPath = contentRootDirs.some(\n (dir) =>\n normalizedPath === dir || normalizedPath.startsWith(`${dir}/`),\n );\n\n if (isContentPath) {\n // The file set only changes on add/remove because this watcher is\n // intentionally scoped to those events. Clear the list cache so the\n // next transform sees the updated directory contents.\n contentFilesListCache = undefined;\n server.moduleGraph.fileToModulesMap.forEach((mods) => {\n mods.forEach((mod) => {\n if (\n mod.id?.includes('analogjs') &&\n mod.id?.includes('content')\n ) {\n server.moduleGraph.invalidateModule(mod);\n\n mod.importers.forEach((imp) => {\n server.moduleGraph.invalidateModule(imp);\n });\n }\n });\n });\n\n server.ws.send('analog:debug-full-reload', {\n plugin: 'platform:content-plugin',\n reason: 'content-file-set-changed',\n path: normalizedPath,\n });\n server.ws.send({\n type: 'full-reload',\n });\n }\n }\n\n server.watcher.on('add', invalidateContent);\n server.watcher.on('unlink', invalidateContent);\n },\n },\n ];\n\n if (!highlighter) {\n return [\n {\n name: 'analogjs-external-content',\n config() {\n const bundleOptionsKey = getBundleOptionsKey();\n return {\n build: {\n [bundleOptionsKey]: {\n external: ['@analogjs/content'],\n },\n },\n };\n },\n },\n {\n name: 'analogjs-exclude-content-import',\n transform: {\n filter: {\n code: '@analogjs/content',\n },\n handler(code) {\n /**\n * Remove the package so it doesn't get\n * referenced when building for serverless\n * functions.\n */\n if (code.includes(`import('@analogjs/content')`)) {\n return {\n code: code.replace(\n `import('@analogjs/content')`,\n 'Promise.resolve({})',\n ),\n };\n }\n\n return;\n },\n },\n },\n ...contentDiscoveryPlugins,\n ];\n }\n\n return [\n {\n name: 'analogjs-content-frontmatter',\n // Filter by module ID so only `?analog-content-list=true` virtual\n // imports enter the handler. Returns `moduleSideEffects: false` so\n // Rolldown can tree-shake unused content list entries.\n transform: {\n filter: {\n id: /analog-content-list=true/,\n },\n async handler(code, id) {\n const cachedContent = cache.get(id);\n // There's no reason to run `readFileSync` and frontmatter parsing if the\n // `transform` hook is called with the same code. In such cases, we can simply\n // return the cached attributes, which is faster than repeatedly reading files\n // synchronously during the build process.\n if (cachedContent?.code === code) {\n return {\n code: `export default ${cachedContent.attributes}`,\n moduleSideEffects: false,\n };\n }\n\n const fm: any = await import('front-matter');\n // The `default` property will be available in CommonJS environment, for instance,\n // when running unit tests. It's safe to retrieve `default` first, since we still\n // fallback to the original implementation.\n const frontmatter = fm.default || fm;\n const fileContents = readFileSync(id.split('?')[0], 'utf8');\n const { attributes } = frontmatter(fileContents);\n const content = {\n code,\n attributes: JSON.stringify(attributes),\n };\n cache.set(id, content);\n\n return {\n code: `export default ${content.attributes}`,\n moduleSideEffects: false,\n };\n },\n },\n },\n {\n name: 'analogjs-content-file',\n enforce: 'post',\n async load(id) {\n if (!id.includes('analog-content-file=true')) {\n return;\n }\n\n if (!markedHighlighter) {\n if (highlighter === 'shiki') {\n const { getShikiHighlighter } =\n await import('./content/shiki/index.js');\n markedHighlighter = getShikiHighlighter(shikiOptions);\n } else {\n const { getPrismHighlighter } =\n await import('./content/prism/index.js');\n markedHighlighter = getPrismHighlighter();\n\n const langs = [\n 'bash',\n 'css',\n 'javascript',\n 'json',\n 'markup',\n 'typescript',\n ];\n\n if (\n Array.isArray(prismOptions?.additionalLangs) &&\n prismOptions?.additionalLangs?.length > 0\n ) {\n langs.push(...prismOptions.additionalLangs);\n }\n\n const loadLanguages = await import('prismjs/components/index.js');\n\n (\n loadLanguages as unknown as { default: (...args: any[]) => any }\n ).default(langs);\n }\n }\n\n const fm: any = await import('front-matter');\n // The `default` property will be available in CommonJS environment, for instance,\n // when running unit tests. It's safe to retrieve `default` first, since we still\n // fallback to the original implementation.\n const frontmatterFn = fm.default || fm;\n const fileContents = readFileSync(id.split('?')[0], 'utf8');\n const { body, attributes } = frontmatterFn(fileContents);\n\n // parse markdown and highlight\n const { getMarkedSetup } = await import('./content/marked/index.js');\n const markedSetupService = getMarkedSetup(\n { mangle: true, ...(markedOptions || {}) },\n markedHighlighter,\n );\n const mdContent = (await markedSetupService\n .getMarkedInstance()\n .parse(body)) as unknown as string;\n\n return `export default ${JSON.stringify(mdContent)};\\nexport const metadata = ${toModuleValue(attributes)};`;\n },\n },\n ...contentDiscoveryPlugins,\n ];\n}\n"],"mappings":"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"}
@@ -10,12 +10,5 @@
10
10
  "schema": "./src/builders/vite/schema.json",
11
11
  "description": "Build with Vite."
12
12
  }
13
- },
14
- "executors": {
15
- "vite-dev-server": {
16
- "implementation": "./src/executors/vite-dev-server/vite-dev-server.impl",
17
- "schema": "./src/executors/vite-dev-server/schema.json",
18
- "description": "Vite dev server."
19
- }
20
13
  }
21
14
  }
@@ -5,7 +5,8 @@ let _nx_devkit = require("@nx/devkit");
5
5
  function addAnalogDependencies(tree, angularVersion, vitest, nxVersion) {
6
6
  const devDependencies = require_dev_dependencies.getAnalogDevDependencies(angularVersion);
7
7
  const dependencies = require_dependencies.getAnalogDependencies(angularVersion);
8
- if (!nxVersion) delete devDependencies["@nx/vite"];
8
+ if (nxVersion) devDependencies["@nx/vite"] = `^${nxVersion}`;
9
+ else delete devDependencies["@nx/vite"];
9
10
  if (!vitest) {
10
11
  delete devDependencies["vitest"];
11
12
  delete devDependencies["@vitest/coverage-v8"];
@@ -1 +1 @@
1
- {"version":3,"file":"add-analog-dependencies.js","names":[],"sources":["../../../../../../../../../nx-plugin/src/generators/init/lib/add-analog-dependencies.ts"],"sourcesContent":["import { addDependenciesToPackageJson, Tree } from '@nx/devkit';\n\nimport { getAnalogDevDependencies } from '../../../utils/versions/dev-dependencies';\nimport { getAnalogDependencies } from '../../../utils/versions/dependencies';\n\nexport function addAnalogDependencies(\n tree: Tree,\n angularVersion: string,\n vitest: boolean,\n nxVersion?: string,\n): void {\n const devDependencies: Record<string, string> =\n getAnalogDevDependencies(angularVersion);\n const dependencies = getAnalogDependencies(angularVersion);\n\n if (!nxVersion) {\n delete devDependencies['@nx/vite'];\n }\n\n if (!vitest) {\n delete devDependencies['vitest'];\n delete devDependencies['@vitest/coverage-v8'];\n delete devDependencies['@vitest/ui'];\n }\n\n addDependenciesToPackageJson(\n tree,\n {\n ...dependencies,\n '@angular/platform-server': `^${angularVersion}`,\n },\n devDependencies,\n );\n}\n"],"mappings":";;;;AAKA,SAAgB,sBACd,MACA,gBACA,QACA,WACM;CACN,MAAM,kBACJ,yBAAA,yBAAyB,cAAc;CACzC,MAAM,eAAe,qBAAA,sBAAsB,cAAc;CAEzD,IAAI,CAAC,WACH,OAAO,gBAAgB;CAGzB,IAAI,CAAC,QAAQ;EACX,OAAO,gBAAgB;EACvB,OAAO,gBAAgB;EACvB,OAAO,gBAAgB;CACzB;CAEA,CAAA,GAAA,WAAA,6BAAA,CACE,MACA;EACE,GAAG;EACH,4BAA4B,IAAI;CAClC,GACA,eACF;AACF"}
1
+ {"version":3,"file":"add-analog-dependencies.js","names":[],"sources":["../../../../../../../../../nx-plugin/src/generators/init/lib/add-analog-dependencies.ts"],"sourcesContent":["import { addDependenciesToPackageJson, Tree } from '@nx/devkit';\n\nimport { getAnalogDevDependencies } from '../../../utils/versions/dev-dependencies';\nimport { getAnalogDependencies } from '../../../utils/versions/dependencies';\n\nexport function addAnalogDependencies(\n tree: Tree,\n angularVersion: string,\n vitest: boolean,\n nxVersion?: string,\n): void {\n const devDependencies: Record<string, string> =\n getAnalogDevDependencies(angularVersion);\n const dependencies = getAnalogDependencies(angularVersion);\n\n if (nxVersion) {\n devDependencies['@nx/vite'] = `^${nxVersion}`;\n } else {\n delete devDependencies['@nx/vite'];\n }\n\n if (!vitest) {\n delete devDependencies['vitest'];\n delete devDependencies['@vitest/coverage-v8'];\n delete devDependencies['@vitest/ui'];\n }\n\n addDependenciesToPackageJson(\n tree,\n {\n ...dependencies,\n '@angular/platform-server': `^${angularVersion}`,\n },\n devDependencies,\n );\n}\n"],"mappings":";;;;AAKA,SAAgB,sBACd,MACA,gBACA,QACA,WACM;CACN,MAAM,kBACJ,yBAAA,yBAAyB,cAAc;CACzC,MAAM,eAAe,qBAAA,sBAAsB,cAAc;CAEzD,IAAI,WACF,gBAAgB,cAAc,IAAI;MAElC,OAAO,gBAAgB;CAGzB,IAAI,CAAC,QAAQ;EACX,OAAO,gBAAgB;EACvB,OAAO,gBAAgB;EACvB,OAAO,gBAAgB;CACzB;CAEA,CAAA,GAAA,WAAA,6BAAA,CACE,MACA;EACE,GAAG;EACH,4BAA4B,IAAI;CAClC,GACA,eACF;AACF"}
@@ -1,13 +1,13 @@
1
- export declare const ANALOG_JS_ROUTER = "^3.0.0-beta.7";
2
- export declare const ANALOG_JS_CONTENT = "^3.0.0-beta.7";
1
+ export declare const ANALOG_JS_ROUTER = "^3.0.0-beta.9";
2
+ export declare const ANALOG_JS_CONTENT = "^3.0.0-beta.9";
3
3
  export declare const MARKED = "^18.0.0";
4
4
  export declare const MARKED_GFM_HEADING_ID = "^4.1.1";
5
5
  export declare const MARKED_HIGHLIGHT = "^2.2.1";
6
6
  export declare const MARKED_MANGLE = "^1.1.10";
7
7
  export declare const PRISMJS = "^1.29.0";
8
- export declare const ANALOG_JS_PLATFORM = "^3.0.0-beta.7";
9
- export declare const ANALOG_JS_VITE_PLUGIN_ANGULAR = "^3.0.0-beta.7";
10
- export declare const ANALOG_JS_VITEST_ANGULAR = "^3.0.0-beta.7";
8
+ export declare const ANALOG_JS_PLATFORM = "^3.0.0-beta.9";
9
+ export declare const ANALOG_JS_VITE_PLUGIN_ANGULAR = "^3.0.0-beta.9";
10
+ export declare const ANALOG_JS_VITEST_ANGULAR = "^3.0.0-beta.9";
11
11
  export declare const JSDOM = "^22.0.0";
12
12
  export declare const VITE_TSCONFIG_PATHS = "^4.2.0";
13
13
  export declare const VITE = "^8.0.0";
@@ -1,14 +1,14 @@
1
1
  //#region packages/nx-plugin/src/utils/versions/versions.ts
2
- var ANALOG_JS_ROUTER = "^3.0.0-beta.7";
3
- var ANALOG_JS_CONTENT = "^3.0.0-beta.7";
2
+ var ANALOG_JS_ROUTER = "^3.0.0-beta.9";
3
+ var ANALOG_JS_CONTENT = "^3.0.0-beta.9";
4
4
  var MARKED = "^18.0.0";
5
5
  var MARKED_GFM_HEADING_ID = "^4.1.1";
6
6
  var MARKED_HIGHLIGHT = "^2.2.1";
7
7
  var MARKED_MANGLE = "^1.1.10";
8
8
  var PRISMJS = "^1.29.0";
9
- var ANALOG_JS_PLATFORM = "^3.0.0-beta.7";
10
- var ANALOG_JS_VITE_PLUGIN_ANGULAR = "^3.0.0-beta.7";
11
- var ANALOG_JS_VITEST_ANGULAR = "^3.0.0-beta.7";
9
+ var ANALOG_JS_PLATFORM = "^3.0.0-beta.9";
10
+ var ANALOG_JS_VITE_PLUGIN_ANGULAR = "^3.0.0-beta.9";
11
+ var ANALOG_JS_VITEST_ANGULAR = "^3.0.0-beta.9";
12
12
  var JSDOM = "^22.0.0";
13
13
  var VITE_TSCONFIG_PATHS = "^4.2.0";
14
14
  var VITE = "^8.0.0";
@@ -1 +1 @@
1
- {"version":3,"file":"versions.js","names":[],"sources":["../../../../../../../../nx-plugin/src/utils/versions/versions.ts"],"sourcesContent":["// dependencies\nexport const ANALOG_JS_ROUTER = '^3.0.0-beta.7';\nexport const ANALOG_JS_CONTENT = '^3.0.0-beta.7';\nexport const MARKED = '^18.0.0';\nexport const MARKED_GFM_HEADING_ID = '^4.1.1';\nexport const MARKED_HIGHLIGHT = '^2.2.1';\nexport const MARKED_MANGLE = '^1.1.10';\nexport const PRISMJS = '^1.29.0';\n\n// devDependencies\nexport const ANALOG_JS_PLATFORM = '^3.0.0-beta.7';\nexport const ANALOG_JS_VITE_PLUGIN_ANGULAR = '^3.0.0-beta.7';\nexport const ANALOG_JS_VITEST_ANGULAR = '^3.0.0-beta.7';\nexport const JSDOM = '^22.0.0';\nexport const VITE_TSCONFIG_PATHS = '^4.2.0';\nexport const VITE = '^8.0.0';\nexport const VITEST = '^5.0.0';\nexport const NX = '^23.2.0';\n"],"mappings":";AACA,IAAa,mBAAmB;AAChC,IAAa,oBAAoB;AACjC,IAAa,SAAS;AACtB,IAAa,wBAAwB;AACrC,IAAa,mBAAmB;AAChC,IAAa,gBAAgB;AAC7B,IAAa,UAAU;AAGvB,IAAa,qBAAqB;AAClC,IAAa,gCAAgC;AAC7C,IAAa,2BAA2B;AACxC,IAAa,QAAQ;AACrB,IAAa,sBAAsB;AACnC,IAAa,OAAO;AACpB,IAAa,SAAS;AACtB,IAAa,KAAK"}
1
+ {"version":3,"file":"versions.js","names":[],"sources":["../../../../../../../../nx-plugin/src/utils/versions/versions.ts"],"sourcesContent":["// dependencies\nexport const ANALOG_JS_ROUTER = '^3.0.0-beta.9';\nexport const ANALOG_JS_CONTENT = '^3.0.0-beta.9';\nexport const MARKED = '^18.0.0';\nexport const MARKED_GFM_HEADING_ID = '^4.1.1';\nexport const MARKED_HIGHLIGHT = '^2.2.1';\nexport const MARKED_MANGLE = '^1.1.10';\nexport const PRISMJS = '^1.29.0';\n\n// devDependencies\nexport const ANALOG_JS_PLATFORM = '^3.0.0-beta.9';\nexport const ANALOG_JS_VITE_PLUGIN_ANGULAR = '^3.0.0-beta.9';\nexport const ANALOG_JS_VITEST_ANGULAR = '^3.0.0-beta.9';\nexport const JSDOM = '^22.0.0';\nexport const VITE_TSCONFIG_PATHS = '^4.2.0';\nexport const VITE = '^8.0.0';\nexport const VITEST = '^5.0.0';\nexport const NX = '^23.2.0';\n"],"mappings":";AACA,IAAa,mBAAmB;AAChC,IAAa,oBAAoB;AACjC,IAAa,SAAS;AACtB,IAAa,wBAAwB;AACrC,IAAa,mBAAmB;AAChC,IAAa,gBAAgB;AAC7B,IAAa,UAAU;AAGvB,IAAa,qBAAqB;AAClC,IAAa,gCAAgC;AAC7C,IAAa,2BAA2B;AACxC,IAAa,QAAQ;AACrB,IAAa,sBAAsB;AACnC,IAAa,OAAO;AACpB,IAAa,SAAS;AACtB,IAAa,KAAK"}
@@ -192,7 +192,7 @@ function routerPlugin(options) {
192
192
  `);
193
193
  result = result.replace("ANALOG_CONTENT_ROUTE_FILES = {};", `
194
194
  ANALOG_CONTENT_ROUTE_FILES = {${contentRouteFiles.map((module) => {
195
- return `"${getModuleKey(module)}": () => import('${module}?analog-content-file=true').then(m => m.default)`;
195
+ return `"${getModuleKey(module)}": () => import('${module}?analog-content-file=true')`;
196
196
  })}};
197
197
  `);
198
198
  result = result.replace("ANALOG_CONTENT_FILE_COUNT = 0", `ANALOG_CONTENT_FILE_COUNT = ${contentRouteFiles.length}`);
@@ -1 +1 @@
1
- {"version":3,"file":"router-plugin.js","names":[],"sources":["../../../src/lib/router-plugin.ts"],"sourcesContent":["import { normalizePath, Plugin, UserConfig, ViteDevServer } from 'vite';\nimport { globSync } from 'tinyglobby';\nimport { readFileSync } from 'node:fs';\nimport { isAbsolute, relative, resolve } from 'node:path';\n\nimport { Options } from './options.js';\nimport {\n analyzeAnalogRouteFile,\n formatAnalogRouteIdiomDiagnostic,\n} from './route-idiom-diagnostics.js';\n\n/**\n * Router plugin that handles route file discovery and hot module replacement.\n *\n * This plugin provides three main functionalities:\n * 1. Route invalidation when files are added/deleted (HMR workaround)\n * 2. Dynamic route file discovery and import generation\n * 3. Content route file discovery for markdown and Analog content\n *\n * @param options Configuration options for the router plugin\n * @returns Array of Vite plugins for route handling\n *\n * IMPORTANT: This plugin uses tinyglobby for file discovery.\n * Key behavior with { dot: true, absolute: true }:\n * - Returns absolute paths for ALL discovered files\n * - Path normalization is required to match expected output format\n * - Files within project root must use relative paths in object keys\n * - Files outside project root keep absolute paths in object keys\n */\nexport function routerPlugin(options?: Options): Plugin[] {\n const workspaceRoot = normalizePath(\n options?.workspaceRoot ?? process.env['NX_WORKSPACE_ROOT'] ?? process.cwd(),\n );\n let config: UserConfig;\n let root: string;\n // Option dirs are workspace-relative, often written with a leading `/`.\n // Normalize them once into absolute workspace paths so watcher events,\n // glob patterns, and key generation all compare against the same shape.\n const normalizeWatchedDir = (dir: string) => {\n const normalizedDir = normalizePath(\n dir.startsWith(`${workspaceRoot}/`) || dir === workspaceRoot\n ? dir\n : dir.startsWith('/')\n ? `${workspaceRoot}${dir}`\n : resolve(workspaceRoot, dir),\n );\n return normalizedDir.endsWith('/')\n ? normalizedDir.slice(0, -1)\n : normalizedDir;\n };\n // Computed eagerly — these depend only on `options` and `workspaceRoot`,\n // both of which are fixed at construction time.\n const additionalPagesDirs = (options?.additionalPagesDirs || []).map((dir) =>\n normalizeWatchedDir(dir),\n );\n const additionalContentDirs = (options?.additionalContentDirs || []).map(\n (dir) => normalizeWatchedDir(dir),\n );\n // Returns every directory that can contain route-like files. The root-\n // relative entries are only available after the Vite `config` hook sets\n // `root`. The short-form fallbacks (`/src/app/pages`, etc.) let watcher\n // events match before `config` runs — they cover the common convention\n // where paths start with these prefixes.\n const getRouteLikeDirs = () => [\n ...(root\n ? [\n normalizeWatchedDir(`${root}/src/app/pages`),\n normalizeWatchedDir(`${root}/src/content`),\n ]\n : []),\n '/src/app/pages',\n '/src/content',\n ...additionalPagesDirs,\n ...additionalContentDirs,\n ];\n // These lists are used repeatedly by transform hooks during serve. Keeping\n // them warm avoids a full glob on every route/content invalidation.\n let routeFilesCache: string[] | undefined;\n let pageRouteFilesCache: string[] | undefined;\n let contentRouteFilesCache: string[] | undefined;\n let endpointFilesCache: string[] | undefined;\n const routeDiagnosticCache = new Map<string, string>();\n const isRouteLikeFile = (path: string) => {\n // Watcher paths from chokidar are already absolute — `normalizePath`\n // (forward-slash only) is sufficient; `resolve()` would be a no-op.\n const normalizedPath = normalizePath(path);\n\n return getRouteLikeDirs().some(\n (dir) => normalizedPath === dir || normalizedPath.startsWith(`${dir}/`),\n );\n };\n const discoverRouteFiles = () => {\n routeFilesCache ??= globSync(\n [\n `${root}/src/app/pages/**/*.page.ts`,\n ...additionalPagesDirs.map((dir) => `${dir}/**/*.page.ts`),\n ],\n { dot: true, absolute: true },\n );\n\n return routeFilesCache;\n };\n const discoverContentRouteFiles = () => {\n contentRouteFilesCache ??= globSync(\n [\n `${root}/src/app/pages/**/*.md`,\n `${root}/src/content/**/*.md`,\n ...additionalContentDirs.map((dir) => `${dir}/**/*.md`),\n ],\n { dot: true, absolute: true },\n );\n\n return contentRouteFilesCache;\n };\n const discoverEndpointFiles = () => {\n endpointFilesCache ??= globSync(\n [\n `${root}/src/app/pages/**/*.server.ts`,\n ...additionalPagesDirs.map((dir) => `${dir}/**/*.server.ts`),\n ],\n { dot: true, absolute: true },\n );\n\n return endpointFilesCache;\n };\n const discoverPageRouteFiles = () => {\n pageRouteFilesCache ??= discoverRouteFiles().filter((file) =>\n file.endsWith('.page.ts'),\n );\n\n return pageRouteFilesCache;\n };\n const invalidateDiscoveryCaches = () => {\n routeFilesCache = undefined;\n pageRouteFilesCache = undefined;\n contentRouteFilesCache = undefined;\n endpointFilesCache = undefined;\n };\n const reportRouteDiagnostics = (path: string) => {\n if (!path.endsWith('.page.ts')) {\n return;\n }\n\n try {\n const code = readFileSync(path, 'utf-8');\n const routeFiles = discoverPageRouteFiles();\n const diagnostics = analyzeAnalogRouteFile({\n filename: path,\n code,\n routeFiles,\n });\n\n const rendered = diagnostics.map((diagnostic) =>\n formatAnalogRouteIdiomDiagnostic(diagnostic, path, workspaceRoot),\n );\n const fingerprint = rendered.join('\\n\\n');\n\n if (!fingerprint) {\n routeDiagnosticCache.delete(path);\n return;\n }\n\n if (routeDiagnosticCache.get(path) === fingerprint) {\n return;\n }\n\n routeDiagnosticCache.set(path, fingerprint);\n rendered.forEach((message) => console.warn(message));\n } catch {\n routeDiagnosticCache.delete(path);\n }\n };\n const getModuleKey = (module: string) => {\n // Before config sets `root`, fall back to workspace-relative keys.\n if (!root) {\n return `/${normalizePath(relative(workspaceRoot, module))}`;\n }\n\n const relToRoot = normalizePath(relative(root, module));\n // Use true path containment instead of a raw prefix check so siblings like\n // `/apps/my-app-tools/...` are not mistaken for files inside `/apps/my-app`.\n const isInRoot = !relToRoot.startsWith('..') && !isAbsolute(relToRoot);\n\n if (isInRoot) {\n return `/${relToRoot}`;\n }\n\n return `/${normalizePath(relative(workspaceRoot, module))}`;\n };\n const invalidateFileModules = (server: ViteDevServer, path: string) => {\n const normalizedPath = normalizePath(path);\n // A newly added page can be discovered before its final contents settle.\n // Invalidate the page module itself so later edits don't keep serving the\n // first incomplete transform from Vite's module graph.\n const fileModules =\n server.moduleGraph.getModulesByFile?.(normalizedPath) ??\n server.moduleGraph.fileToModulesMap.get(normalizedPath);\n\n fileModules?.forEach((mod) => {\n server.moduleGraph.invalidateModule(mod);\n\n mod.importers.forEach((imp) => {\n server.moduleGraph.invalidateModule(imp);\n });\n });\n };\n\n return [\n {\n name: 'analogjs-router-invalidate-routes',\n configureServer(server) {\n /**\n * Invalidates route modules when files are added or deleted.\n * This is a workaround for Vite's HMR limitations with dynamic imports.\n *\n * @param path The file path that was added or deleted\n */\n function invalidateRoutes(\n path: string,\n event: 'add' | 'change' | 'unlink',\n ) {\n if (!isRouteLikeFile(path)) {\n return;\n }\n\n // Add/remove changes the route graph shape, so the discovery caches\n // must be rebuilt. Plain edits can keep using the current file set.\n if (event !== 'change') {\n invalidateDiscoveryCaches();\n }\n\n if (event === 'change') {\n reportRouteDiagnostics(path);\n } else if (event === 'unlink') {\n routeDiagnosticCache.delete(path);\n discoverPageRouteFiles().forEach((file) =>\n reportRouteDiagnostics(file),\n );\n } else {\n discoverPageRouteFiles().forEach((file) =>\n reportRouteDiagnostics(file),\n );\n }\n\n invalidateFileModules(server, path);\n\n // For an in-place edit we only need module invalidation. Keeping the\n // app alive here lets Angular/Vite attempt the narrower HMR path.\n if (event === 'change') {\n return;\n }\n\n server.moduleGraph.fileToModulesMap.forEach((mods) => {\n mods.forEach((mod) => {\n if (mod.id?.includes('analogjs') && mod.id?.includes('fesm')) {\n server.moduleGraph.invalidateModule(mod);\n\n mod.importers.forEach((imp) => {\n server.moduleGraph.invalidateModule(imp);\n });\n }\n });\n });\n\n server.ws.send('analog:debug-full-reload', {\n plugin: 'platform:router-plugin',\n reason: 'route-graph-shape-changed',\n event,\n path,\n });\n server.ws.send({\n type: 'full-reload',\n });\n }\n\n server.watcher.on('add', (path) => invalidateRoutes(path, 'add'));\n server.watcher.on('change', (path) => invalidateRoutes(path, 'change'));\n server.watcher.on('unlink', (path) => invalidateRoutes(path, 'unlink'));\n\n // Vite's watcher only covers the app root by default.\n // additionalPagesDirs / additionalContentDirs live outside the\n // root (e.g. libs/shared/feature in a monorepo), so file\n // add/rename/delete events are never fired for them. Explicitly\n // add these directories to chokidar so route invalidation works.\n for (const dir of [...additionalPagesDirs, ...additionalContentDirs]) {\n server.watcher.add(dir);\n }\n\n discoverPageRouteFiles().forEach((file) =>\n reportRouteDiagnostics(file),\n );\n },\n },\n {\n name: 'analog-glob-routes',\n // enforce: 'post' ensures this transform runs AFTER the Angular compiler\n // plugin, which replaces module content with its own compiled output.\n // Without this, the Angular plugin would overwrite the route replacements.\n enforce: 'post',\n config(_config) {\n config = _config;\n root = normalizePath(resolve(workspaceRoot, config.root || '.') || '.');\n },\n /**\n * Transforms code to replace ANALOG_ROUTE_FILES and ANALOG_CONTENT_ROUTE_FILES\n * placeholders with actual dynamic imports of discovered route and content files.\n *\n * @param code The source code to transform\n * @returns Transformed code with dynamic imports or undefined if no transformation needed\n */\n // Vite 8 / Rolldown filtered transform: the `filter.code` substring\n // pre-filter lets the bundler skip modules that don't contain the\n // marker. '_ROUTE_FILES' is a common substring of both\n // 'ANALOG_ROUTE_FILES' and 'ANALOG_CONTENT_ROUTE_FILES'.\n //\n // IMPORTANT: Do NOT change this to 'ANALOG_ROUTE_FILES' — that is NOT\n // a substring of 'ANALOG_CONTENT_ROUTE_FILES' (they diverge at\n // position 7: 'ANALOG_C...' vs 'ANALOG_R...'). When tsconfig path\n // aliases resolve @analogjs/router and @analogjs/router/content to\n // separate source files, each variable lives in its own module and\n // the filter must match both independently.\n transform: {\n filter: {\n code: '_ROUTE_FILES',\n },\n handler(code) {\n if (\n code.includes('ANALOG_ROUTE_FILES') ||\n code.includes('ANALOG_CONTENT_ROUTE_FILES')\n ) {\n // Discover route files using tinyglobby\n // NOTE: { absolute: true } returns absolute paths for ALL files\n const routeFiles = discoverRouteFiles();\n\n // Discover content files using tinyglobby\n const contentRouteFiles = discoverContentRouteFiles();\n\n let result = code.replace(\n 'ANALOG_ROUTE_FILES = {};',\n `\n ANALOG_ROUTE_FILES = {${routeFiles.map((module) => {\n // Keys are app-root-relative for in-app files,\n // workspace-relative for library files (additionalPagesDirs).\n // import() keeps absolute paths for Vite's module resolution.\n const key = getModuleKey(module);\n return `\"${key}\": () => import('${module}')`;\n })}};\n `,\n );\n\n result = result.replace(\n 'ANALOG_CONTENT_ROUTE_FILES = {};',\n `\n ANALOG_CONTENT_ROUTE_FILES = {${contentRouteFiles.map((module) => {\n const key = getModuleKey(module);\n return `\"${key}\": () => import('${module}?analog-content-file=true').then(m => m.default)`;\n })}};\n `,\n );\n\n result = result.replace(\n 'ANALOG_CONTENT_FILE_COUNT = 0',\n `ANALOG_CONTENT_FILE_COUNT = ${contentRouteFiles.length}`,\n );\n\n return {\n code: result,\n map: { mappings: '' },\n };\n }\n\n return;\n },\n },\n },\n {\n name: 'analog-glob-endpoints',\n // enforce: 'post' ensures this transform runs AFTER the Angular compiler\n // plugin, which replaces module content with its own compiled output.\n // Without this, the Angular plugin would overwrite the endpoint replacements.\n enforce: 'post',\n /**\n * Transforms code to replace ANALOG_PAGE_ENDPOINTS placeholder\n * with actual dynamic imports of discovered server endpoint files.\n *\n * @param code The source code to transform\n * @returns Transformed code with dynamic imports or undefined if no transformation needed\n */\n transform: {\n filter: {\n code: 'ANALOG_PAGE_ENDPOINTS',\n },\n handler(code) {\n if (code.includes('ANALOG_PAGE_ENDPOINTS')) {\n // Discover server endpoint files using tinyglobby\n const endpointFiles = discoverEndpointFiles();\n\n const result = code.replace(\n 'ANALOG_PAGE_ENDPOINTS = {};',\n `\n ANALOG_PAGE_ENDPOINTS = {${endpointFiles.map((module) => {\n const key = getModuleKey(module);\n return `\"${key}\": () => import('${module}')`;\n })}};\n `,\n );\n\n return {\n code: result,\n map: { mappings: '' },\n };\n }\n\n return;\n },\n },\n },\n ];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"router-plugin.js","names":[],"sources":["../../../src/lib/router-plugin.ts"],"sourcesContent":["import { normalizePath, Plugin, UserConfig, ViteDevServer } from 'vite';\nimport { globSync } from 'tinyglobby';\nimport { readFileSync } from 'node:fs';\nimport { isAbsolute, relative, resolve } from 'node:path';\n\nimport { Options } from './options.js';\nimport {\n analyzeAnalogRouteFile,\n formatAnalogRouteIdiomDiagnostic,\n} from './route-idiom-diagnostics.js';\n\n/**\n * Router plugin that handles route file discovery and hot module replacement.\n *\n * This plugin provides three main functionalities:\n * 1. Route invalidation when files are added/deleted (HMR workaround)\n * 2. Dynamic route file discovery and import generation\n * 3. Content route file discovery for markdown and Analog content\n *\n * @param options Configuration options for the router plugin\n * @returns Array of Vite plugins for route handling\n *\n * IMPORTANT: This plugin uses tinyglobby for file discovery.\n * Key behavior with { dot: true, absolute: true }:\n * - Returns absolute paths for ALL discovered files\n * - Path normalization is required to match expected output format\n * - Files within project root must use relative paths in object keys\n * - Files outside project root keep absolute paths in object keys\n */\nexport function routerPlugin(options?: Options): Plugin[] {\n const workspaceRoot = normalizePath(\n options?.workspaceRoot ?? process.env['NX_WORKSPACE_ROOT'] ?? process.cwd(),\n );\n let config: UserConfig;\n let root: string;\n // Option dirs are workspace-relative, often written with a leading `/`.\n // Normalize them once into absolute workspace paths so watcher events,\n // glob patterns, and key generation all compare against the same shape.\n const normalizeWatchedDir = (dir: string) => {\n const normalizedDir = normalizePath(\n dir.startsWith(`${workspaceRoot}/`) || dir === workspaceRoot\n ? dir\n : dir.startsWith('/')\n ? `${workspaceRoot}${dir}`\n : resolve(workspaceRoot, dir),\n );\n return normalizedDir.endsWith('/')\n ? normalizedDir.slice(0, -1)\n : normalizedDir;\n };\n // Computed eagerly — these depend only on `options` and `workspaceRoot`,\n // both of which are fixed at construction time.\n const additionalPagesDirs = (options?.additionalPagesDirs || []).map((dir) =>\n normalizeWatchedDir(dir),\n );\n const additionalContentDirs = (options?.additionalContentDirs || []).map(\n (dir) => normalizeWatchedDir(dir),\n );\n // Returns every directory that can contain route-like files. The root-\n // relative entries are only available after the Vite `config` hook sets\n // `root`. The short-form fallbacks (`/src/app/pages`, etc.) let watcher\n // events match before `config` runs — they cover the common convention\n // where paths start with these prefixes.\n const getRouteLikeDirs = () => [\n ...(root\n ? [\n normalizeWatchedDir(`${root}/src/app/pages`),\n normalizeWatchedDir(`${root}/src/content`),\n ]\n : []),\n '/src/app/pages',\n '/src/content',\n ...additionalPagesDirs,\n ...additionalContentDirs,\n ];\n // These lists are used repeatedly by transform hooks during serve. Keeping\n // them warm avoids a full glob on every route/content invalidation.\n let routeFilesCache: string[] | undefined;\n let pageRouteFilesCache: string[] | undefined;\n let contentRouteFilesCache: string[] | undefined;\n let endpointFilesCache: string[] | undefined;\n const routeDiagnosticCache = new Map<string, string>();\n const isRouteLikeFile = (path: string) => {\n // Watcher paths from chokidar are already absolute — `normalizePath`\n // (forward-slash only) is sufficient; `resolve()` would be a no-op.\n const normalizedPath = normalizePath(path);\n\n return getRouteLikeDirs().some(\n (dir) => normalizedPath === dir || normalizedPath.startsWith(`${dir}/`),\n );\n };\n const discoverRouteFiles = () => {\n routeFilesCache ??= globSync(\n [\n `${root}/src/app/pages/**/*.page.ts`,\n ...additionalPagesDirs.map((dir) => `${dir}/**/*.page.ts`),\n ],\n { dot: true, absolute: true },\n );\n\n return routeFilesCache;\n };\n const discoverContentRouteFiles = () => {\n contentRouteFilesCache ??= globSync(\n [\n `${root}/src/app/pages/**/*.md`,\n `${root}/src/content/**/*.md`,\n ...additionalContentDirs.map((dir) => `${dir}/**/*.md`),\n ],\n { dot: true, absolute: true },\n );\n\n return contentRouteFilesCache;\n };\n const discoverEndpointFiles = () => {\n endpointFilesCache ??= globSync(\n [\n `${root}/src/app/pages/**/*.server.ts`,\n ...additionalPagesDirs.map((dir) => `${dir}/**/*.server.ts`),\n ],\n { dot: true, absolute: true },\n );\n\n return endpointFilesCache;\n };\n const discoverPageRouteFiles = () => {\n pageRouteFilesCache ??= discoverRouteFiles().filter((file) =>\n file.endsWith('.page.ts'),\n );\n\n return pageRouteFilesCache;\n };\n const invalidateDiscoveryCaches = () => {\n routeFilesCache = undefined;\n pageRouteFilesCache = undefined;\n contentRouteFilesCache = undefined;\n endpointFilesCache = undefined;\n };\n const reportRouteDiagnostics = (path: string) => {\n if (!path.endsWith('.page.ts')) {\n return;\n }\n\n try {\n const code = readFileSync(path, 'utf-8');\n const routeFiles = discoverPageRouteFiles();\n const diagnostics = analyzeAnalogRouteFile({\n filename: path,\n code,\n routeFiles,\n });\n\n const rendered = diagnostics.map((diagnostic) =>\n formatAnalogRouteIdiomDiagnostic(diagnostic, path, workspaceRoot),\n );\n const fingerprint = rendered.join('\\n\\n');\n\n if (!fingerprint) {\n routeDiagnosticCache.delete(path);\n return;\n }\n\n if (routeDiagnosticCache.get(path) === fingerprint) {\n return;\n }\n\n routeDiagnosticCache.set(path, fingerprint);\n rendered.forEach((message) => console.warn(message));\n } catch {\n routeDiagnosticCache.delete(path);\n }\n };\n const getModuleKey = (module: string) => {\n // Before config sets `root`, fall back to workspace-relative keys.\n if (!root) {\n return `/${normalizePath(relative(workspaceRoot, module))}`;\n }\n\n const relToRoot = normalizePath(relative(root, module));\n // Use true path containment instead of a raw prefix check so siblings like\n // `/apps/my-app-tools/...` are not mistaken for files inside `/apps/my-app`.\n const isInRoot = !relToRoot.startsWith('..') && !isAbsolute(relToRoot);\n\n if (isInRoot) {\n return `/${relToRoot}`;\n }\n\n return `/${normalizePath(relative(workspaceRoot, module))}`;\n };\n const invalidateFileModules = (server: ViteDevServer, path: string) => {\n const normalizedPath = normalizePath(path);\n // A newly added page can be discovered before its final contents settle.\n // Invalidate the page module itself so later edits don't keep serving the\n // first incomplete transform from Vite's module graph.\n const fileModules =\n server.moduleGraph.getModulesByFile?.(normalizedPath) ??\n server.moduleGraph.fileToModulesMap.get(normalizedPath);\n\n fileModules?.forEach((mod) => {\n server.moduleGraph.invalidateModule(mod);\n\n mod.importers.forEach((imp) => {\n server.moduleGraph.invalidateModule(imp);\n });\n });\n };\n\n return [\n {\n name: 'analogjs-router-invalidate-routes',\n configureServer(server) {\n /**\n * Invalidates route modules when files are added or deleted.\n * This is a workaround for Vite's HMR limitations with dynamic imports.\n *\n * @param path The file path that was added or deleted\n */\n function invalidateRoutes(\n path: string,\n event: 'add' | 'change' | 'unlink',\n ) {\n if (!isRouteLikeFile(path)) {\n return;\n }\n\n // Add/remove changes the route graph shape, so the discovery caches\n // must be rebuilt. Plain edits can keep using the current file set.\n if (event !== 'change') {\n invalidateDiscoveryCaches();\n }\n\n if (event === 'change') {\n reportRouteDiagnostics(path);\n } else if (event === 'unlink') {\n routeDiagnosticCache.delete(path);\n discoverPageRouteFiles().forEach((file) =>\n reportRouteDiagnostics(file),\n );\n } else {\n discoverPageRouteFiles().forEach((file) =>\n reportRouteDiagnostics(file),\n );\n }\n\n invalidateFileModules(server, path);\n\n // For an in-place edit we only need module invalidation. Keeping the\n // app alive here lets Angular/Vite attempt the narrower HMR path.\n if (event === 'change') {\n return;\n }\n\n server.moduleGraph.fileToModulesMap.forEach((mods) => {\n mods.forEach((mod) => {\n if (mod.id?.includes('analogjs') && mod.id?.includes('fesm')) {\n server.moduleGraph.invalidateModule(mod);\n\n mod.importers.forEach((imp) => {\n server.moduleGraph.invalidateModule(imp);\n });\n }\n });\n });\n\n server.ws.send('analog:debug-full-reload', {\n plugin: 'platform:router-plugin',\n reason: 'route-graph-shape-changed',\n event,\n path,\n });\n server.ws.send({\n type: 'full-reload',\n });\n }\n\n server.watcher.on('add', (path) => invalidateRoutes(path, 'add'));\n server.watcher.on('change', (path) => invalidateRoutes(path, 'change'));\n server.watcher.on('unlink', (path) => invalidateRoutes(path, 'unlink'));\n\n // Vite's watcher only covers the app root by default.\n // additionalPagesDirs / additionalContentDirs live outside the\n // root (e.g. libs/shared/feature in a monorepo), so file\n // add/rename/delete events are never fired for them. Explicitly\n // add these directories to chokidar so route invalidation works.\n for (const dir of [...additionalPagesDirs, ...additionalContentDirs]) {\n server.watcher.add(dir);\n }\n\n discoverPageRouteFiles().forEach((file) =>\n reportRouteDiagnostics(file),\n );\n },\n },\n {\n name: 'analog-glob-routes',\n // enforce: 'post' ensures this transform runs AFTER the Angular compiler\n // plugin, which replaces module content with its own compiled output.\n // Without this, the Angular plugin would overwrite the route replacements.\n enforce: 'post',\n config(_config) {\n config = _config;\n root = normalizePath(resolve(workspaceRoot, config.root || '.') || '.');\n },\n /**\n * Transforms code to replace ANALOG_ROUTE_FILES and ANALOG_CONTENT_ROUTE_FILES\n * placeholders with actual dynamic imports of discovered route and content files.\n *\n * @param code The source code to transform\n * @returns Transformed code with dynamic imports or undefined if no transformation needed\n */\n // Vite 8 / Rolldown filtered transform: the `filter.code` substring\n // pre-filter lets the bundler skip modules that don't contain the\n // marker. '_ROUTE_FILES' is a common substring of both\n // 'ANALOG_ROUTE_FILES' and 'ANALOG_CONTENT_ROUTE_FILES'.\n //\n // IMPORTANT: Do NOT change this to 'ANALOG_ROUTE_FILES' — that is NOT\n // a substring of 'ANALOG_CONTENT_ROUTE_FILES' (they diverge at\n // position 7: 'ANALOG_C...' vs 'ANALOG_R...'). When tsconfig path\n // aliases resolve @analogjs/router and @analogjs/router/content to\n // separate source files, each variable lives in its own module and\n // the filter must match both independently.\n transform: {\n filter: {\n code: '_ROUTE_FILES',\n },\n handler(code) {\n if (\n code.includes('ANALOG_ROUTE_FILES') ||\n code.includes('ANALOG_CONTENT_ROUTE_FILES')\n ) {\n // Discover route files using tinyglobby\n // NOTE: { absolute: true } returns absolute paths for ALL files\n const routeFiles = discoverRouteFiles();\n\n // Discover content files using tinyglobby\n const contentRouteFiles = discoverContentRouteFiles();\n\n let result = code.replace(\n 'ANALOG_ROUTE_FILES = {};',\n `\n ANALOG_ROUTE_FILES = {${routeFiles.map((module) => {\n // Keys are app-root-relative for in-app files,\n // workspace-relative for library files (additionalPagesDirs).\n // import() keeps absolute paths for Vite's module resolution.\n const key = getModuleKey(module);\n return `\"${key}\": () => import('${module}')`;\n })}};\n `,\n );\n\n result = result.replace(\n 'ANALOG_CONTENT_ROUTE_FILES = {};',\n `\n ANALOG_CONTENT_ROUTE_FILES = {${contentRouteFiles.map((module) => {\n const key = getModuleKey(module);\n return `\"${key}\": () => import('${module}?analog-content-file=true')`;\n })}};\n `,\n );\n\n result = result.replace(\n 'ANALOG_CONTENT_FILE_COUNT = 0',\n `ANALOG_CONTENT_FILE_COUNT = ${contentRouteFiles.length}`,\n );\n\n return {\n code: result,\n map: { mappings: '' },\n };\n }\n\n return;\n },\n },\n },\n {\n name: 'analog-glob-endpoints',\n // enforce: 'post' ensures this transform runs AFTER the Angular compiler\n // plugin, which replaces module content with its own compiled output.\n // Without this, the Angular plugin would overwrite the endpoint replacements.\n enforce: 'post',\n /**\n * Transforms code to replace ANALOG_PAGE_ENDPOINTS placeholder\n * with actual dynamic imports of discovered server endpoint files.\n *\n * @param code The source code to transform\n * @returns Transformed code with dynamic imports or undefined if no transformation needed\n */\n transform: {\n filter: {\n code: 'ANALOG_PAGE_ENDPOINTS',\n },\n handler(code) {\n if (code.includes('ANALOG_PAGE_ENDPOINTS')) {\n // Discover server endpoint files using tinyglobby\n const endpointFiles = discoverEndpointFiles();\n\n const result = code.replace(\n 'ANALOG_PAGE_ENDPOINTS = {};',\n `\n ANALOG_PAGE_ENDPOINTS = {${endpointFiles.map((module) => {\n const key = getModuleKey(module);\n return `\"${key}\": () => import('${module}')`;\n })}};\n `,\n );\n\n return {\n code: result,\n map: { mappings: '' },\n };\n }\n\n return;\n },\n },\n },\n ];\n}\n"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import { convertNxExecutor } from "@nx/devkit";
2
- declare const compat: ReturnType<typeof convertNxExecutor>;
3
- export default compat;
@@ -1,7 +0,0 @@
1
- const require_src_executors_vite_dev_server_vite_dev_server_impl = require("./vite-dev-server.impl.js");
2
- //#region packages/nx-plugin/src/executors/vite-dev-server/compat.ts
3
- var compat = (0, require("@nx/devkit").convertNxExecutor)(require_src_executors_vite_dev_server_vite_dev_server_impl);
4
- //#endregion
5
- module.exports = compat;
6
-
7
- //# sourceMappingURL=compat.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compat.js","names":[],"sources":["../../../../../../../../nx-plugin/src/executors/vite-dev-server/compat.ts"],"sourcesContent":["import { convertNxExecutor } from '@nx/devkit';\n\nimport viteDevServerExecutor from './vite-dev-server.impl';\n\nconst compat: ReturnType<typeof convertNxExecutor> = convertNxExecutor(\n viteDevServerExecutor,\n);\nexport default compat;\n"],"mappings":";;AAIA,IAAM,UAAA,uBAA+C,CAAA,CAAA,kBAAA,CACnD,0DACF"}
@@ -1 +0,0 @@
1
- export type { ViteDevServerExecutorOptions } from '@nx/vite/executors';
@@ -1,101 +0,0 @@
1
- {
2
- "version": 2,
3
- "outputCapture": "direct-nodejs",
4
- "title": "Vite Dev Server",
5
- "cli": "nx",
6
- "description": "Starts a dev server using Vite.",
7
- "type": "object",
8
- "presets": [
9
- {
10
- "name": "Default minimum setup",
11
- "keys": ["buildTarget"]
12
- },
13
- {
14
- "name": "Using a Different Port",
15
- "keys": ["buildTarget", "port"]
16
- }
17
- ],
18
- "properties": {
19
- "buildTarget": {
20
- "type": "string",
21
- "description": "Target which builds the application. Only used to retrieve the configuration as the dev-server does not build the code.",
22
- "x-priority": "important"
23
- },
24
- "buildLibsFromSource": {
25
- "type": "boolean",
26
- "description": "Read buildable libraries from source instead of building them separately.",
27
- "default": true
28
- },
29
- "proxyConfig": {
30
- "type": "string",
31
- "description": "Path to the proxy configuration file.",
32
- "x-completion-type": "file"
33
- },
34
- "port": {
35
- "type": "number",
36
- "description": "Port to listen on.",
37
- "x-priority": "important"
38
- },
39
- "host": {
40
- "description": "Specify which IP addresses the server should listen on.",
41
- "oneOf": [
42
- {
43
- "type": "boolean"
44
- },
45
- {
46
- "type": "string"
47
- }
48
- ]
49
- },
50
- "https": {
51
- "oneOf": [
52
- {
53
- "type": "boolean"
54
- },
55
- {
56
- "type": "object"
57
- }
58
- ],
59
- "description": "Serve using HTTPS. https://vitejs.dev/config/server-options.html#server-https"
60
- },
61
- "hmr": {
62
- "description": "Enable hot module replacement. For more options, use the 'hmr' option in the Vite configuration file.",
63
- "type": "boolean"
64
- },
65
- "open": {
66
- "description": "Automatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname.",
67
- "oneOf": [
68
- {
69
- "type": "boolean"
70
- },
71
- {
72
- "type": "string"
73
- }
74
- ]
75
- },
76
- "cors": {
77
- "description": "Configure CORS for the dev server.",
78
- "type": "boolean"
79
- },
80
- "logLevel": {
81
- "type": "string",
82
- "description": "Adjust console output verbosity.",
83
- "enum": ["info", "warn", "error", "silent"]
84
- },
85
- "mode": {
86
- "type": "string",
87
- "description": "Mode to run the server in."
88
- },
89
- "clearScreen": {
90
- "description": "Set to false to prevent Vite from clearing the terminal screen when logging certain messages.",
91
- "type": "boolean"
92
- },
93
- "force": {
94
- "description": "Force the optimizer to ignore the cache and re-bundle",
95
- "type": "boolean"
96
- }
97
- },
98
- "definitions": {},
99
- "required": ["buildTarget"],
100
- "examplesFile": "../../../docs/dev-server-examples.md"
101
- }
@@ -1,2 +0,0 @@
1
- import { viteDevServerExecutor } from "@nx/vite/executors";
2
- export default viteDevServerExecutor;
@@ -1,6 +0,0 @@
1
- //#region packages/nx-plugin/src/executors/vite-dev-server/vite-dev-server.impl.ts
2
- var vite_dev_server_impl_default = require("@nx/vite/executors").viteDevServerExecutor;
3
- //#endregion
4
- module.exports = vite_dev_server_impl_default;
5
-
6
- //# sourceMappingURL=vite-dev-server.impl.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"vite-dev-server.impl.js","names":[],"sources":["../../../../../../../../nx-plugin/src/executors/vite-dev-server/vite-dev-server.impl.ts"],"sourcesContent":["import { viteDevServerExecutor } from '@nx/vite/executors';\n\nexport default viteDevServerExecutor;\n"],"mappings":";AAEA,IAAA,2DAAe,CAAA,CAAA"}