@absolutejs/absolute 0.20.0-beta.178 → 0.20.0-beta.179

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/CHANGELOG.md CHANGED
@@ -6,6 +6,17 @@ This file is generated by `absolute-changelog` from the entries in
6
6
  `changelog/`. Edit an entry, not this file — and add new ones under
7
7
  `changelog/unreleased/`.
8
8
 
9
+ ## 0.20.0-beta.179 — 2026-11-14
10
+
11
+ ### Fixed
12
+
13
+ - **`absolute add <framework>` installs the same packages and versions as the create-absolutejs scaffold, including vue-router for Vue**
14
+ `absolute add vue` now installs vue-router, so a Vue page that exports `routes` builds instead of failing with "Could not resolve: vue-router". Every `absolute add <framework>` now installs the same packages at the same versions as a project created with create-absolutejs: React 19.3.0 with react-refresh, Angular 21.2.24 including @angular/router, Svelte 5.57.1 with svelte2tsx, Vue 3.5.43, and @absolutejs/scoped-state for HTMX. `absolute remove <framework> --prune` uninstalls that same list.
15
+ - **Vue and Svelte islands can import shared modules by a relative path outside the islands directory**
16
+ A Vue island that imported a module by a relative path, such as `import { counterStore } from '../shared/counterStore'`, failed `absolute dev` and `absolute build` with "Cannot find module '../shared/counterStore'". The island's server render is compiled into `.absolutejs/islands/vue/`, and only relative `.vue` imports were rewritten for that location, so every other relative import resolved against the generated file instead of the island's source. Every relative import in a Vue island's server module now resolves from the island's source file, the way it does in the browser bundle. Svelte islands already rewrote these imports, but replaced the specifier anywhere it appeared as text, so an island that imported both `../shared` and `../shared/counterStore` had the second import corrupted; they now replace only the exact quoted specifier.
17
+ - **Vue pages with only a plain `<script>` (like the README's defineRoutes sample) no longer fail with "script is not defined"**
18
+ A Vue page whose only script block is a plain `<script>` without `export default` (such as the README's router page: `export const routes = defineRoutes([...])` with `<template><RouterView /></template>`) answered every request with 500 "ReferenceError: script is not defined" in production, and failed the same way in dev. The compilers relied on rewriting `export default` to name the component, so a page with no default export never declared it. Such pages now compile to an empty component with their template, in both the production build and the dev server. `RouterView` and `RouterLink` work in these templates without an import, because the page installs vue-router on the app. Pages with `<script setup>`, with both blocks, with `export default defineComponent(...)`, or with no script at all keep working.
19
+
9
20
  ## 0.20.0-beta.178 — 2026-11-14
10
21
 
11
22
  ### Fixed
package/changelog.json CHANGED
@@ -2,6 +2,27 @@
2
2
  "contract": 1,
3
3
  "name": "@absolutejs/absolute",
4
4
  "releases": [
5
+ {
6
+ "changes": [
7
+ {
8
+ "detail": "`absolute add vue` now installs vue-router, so a Vue page that exports `routes` builds instead of failing with \"Could not resolve: vue-router\". Every `absolute add <framework>` now installs the same packages at the same versions as a project created with create-absolutejs: React 19.3.0 with react-refresh, Angular 21.2.24 including @angular/router, Svelte 5.57.1 with svelte2tsx, Vue 3.5.43, and @absolutejs/scoped-state for HTMX. `absolute remove <framework> --prune` uninstalls that same list.",
9
+ "kind": "fixed",
10
+ "summary": "`absolute add <framework>` installs the same packages and versions as the create-absolutejs scaffold, including vue-router for Vue"
11
+ },
12
+ {
13
+ "detail": "A Vue island that imported a module by a relative path, such as `import { counterStore } from '../shared/counterStore'`, failed `absolute dev` and `absolute build` with \"Cannot find module '../shared/counterStore'\". The island's server render is compiled into `.absolutejs/islands/vue/`, and only relative `.vue` imports were rewritten for that location, so every other relative import resolved against the generated file instead of the island's source. Every relative import in a Vue island's server module now resolves from the island's source file, the way it does in the browser bundle. Svelte islands already rewrote these imports, but replaced the specifier anywhere it appeared as text, so an island that imported both `../shared` and `../shared/counterStore` had the second import corrupted; they now replace only the exact quoted specifier.",
14
+ "kind": "fixed",
15
+ "summary": "Vue and Svelte islands can import shared modules by a relative path outside the islands directory"
16
+ },
17
+ {
18
+ "detail": "A Vue page whose only script block is a plain `<script>` without `export default` (such as the README's router page: `export const routes = defineRoutes([...])` with `<template><RouterView /></template>`) answered every request with 500 \"ReferenceError: script is not defined\" in production, and failed the same way in dev. The compilers relied on rewriting `export default` to name the component, so a page with no default export never declared it. Such pages now compile to an empty component with their template, in both the production build and the dev server. `RouterView` and `RouterLink` work in these templates without an import, because the page installs vue-router on the app. Pages with `<script setup>`, with both blocks, with `export default defineComponent(...)`, or with no script at all keep working.",
19
+ "kind": "fixed",
20
+ "summary": "Vue pages with only a plain `<script>` (like the README's defineRoutes sample) no longer fail with \"script is not defined\""
21
+ }
22
+ ],
23
+ "date": "2026-11-14",
24
+ "version": "0.20.0-beta.179"
25
+ },
5
26
  {
6
27
  "changes": [
7
28
  {
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- // .angular-partial-tmp-1GarPM/src/core/streamingSlotRegistrar.ts
2
+ // .angular-partial-tmp-jHcM0h/src/core/streamingSlotRegistrar.ts
3
3
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
4
4
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
5
5
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- // .angular-partial-tmp-1GarPM/src/core/streamingSlotRegistrar.ts
2
+ // .angular-partial-tmp-jHcM0h/src/core/streamingSlotRegistrar.ts
3
3
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
4
4
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
5
5
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -46,7 +46,7 @@ var warnMissingStreamingSlotCollector = (primitiveName) => {
46
46
  getWarningController()?.maybeWarn(primitiveName);
47
47
  };
48
48
 
49
- // .angular-partial-tmp-1GarPM/src/core/streamingSlotRegistry.ts
49
+ // .angular-partial-tmp-jHcM0h/src/core/streamingSlotRegistry.ts
50
50
  var STREAMING_SLOT_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotAsyncLocalStorage");
51
51
  var isObjectRecord2 = (value) => Boolean(value) && typeof value === "object";
52
52
  var isAsyncLocalStorage = (value) => isObjectRecord2(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
@@ -3214,7 +3214,7 @@ import { basename as basename3, dirname as dirname3, extname as extname2, join a
3214
3214
  var serverCacheRoot2, compiledModuleCache2, originalSourcePathCache, syncIslandGeneration, transpiler, ensureRelativeImportPath = (from, target) => {
3215
3215
  const importPath = relative3(dirname3(from), target).replace(/\\/g, "/");
3216
3216
  return importPath.startsWith(".") ? importPath : `./${importPath}`;
3217
- }, processDirectoryEntries = (entries, dir, targetFileName, stack) => {
3217
+ }, escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), replaceQuotedSpecifier = (code, spec, target) => code.replace(new RegExp(`(['"])${escapeRegExp(spec)}\\1`, "g"), (_match, quote) => `${quote}${target}${quote}`), processDirectoryEntries = (entries, dir, targetFileName, stack) => {
3218
3218
  for (const entry of entries) {
3219
3219
  const entryPath = join6(dir, entry.name);
3220
3220
  if (entry.isDirectory())
@@ -3259,18 +3259,21 @@ var serverCacheRoot2, compiledModuleCache2, originalSourcePathCache, syncIslandG
3259
3259
  return null;
3260
3260
  }
3261
3261
  const basePath = resolve4(dirname3(from), spec);
3262
+ const extensions = [
3263
+ ".ts",
3264
+ ".tsx",
3265
+ ".mts",
3266
+ ".cts",
3267
+ ".js",
3268
+ ".jsx",
3269
+ ".mjs",
3270
+ ".cjs",
3271
+ ".json"
3272
+ ];
3262
3273
  const candidates = [
3263
3274
  basePath,
3264
- `${basePath}.ts`,
3265
- `${basePath}.js`,
3266
- `${basePath}.mjs`,
3267
- `${basePath}.cjs`,
3268
- `${basePath}.json`,
3269
- join6(basePath, "index.ts"),
3270
- join6(basePath, "index.js"),
3271
- join6(basePath, "index.mjs"),
3272
- join6(basePath, "index.cjs"),
3273
- join6(basePath, "index.json")
3275
+ ...extensions.map((extension) => `${basePath}${extension}`),
3276
+ ...extensions.map((extension) => join6(basePath, `index${extension}`))
3274
3277
  ];
3275
3278
  const existResults = await Promise.all(candidates.map((candidate) => Bun.file(candidate).exists()));
3276
3279
  const foundIndex = existResults.indexOf(true);
@@ -3355,7 +3358,7 @@ var serverCacheRoot2, compiledModuleCache2, originalSourcePathCache, syncIslandG
3355
3358
  rewrittenModulePaths.set(spec, ensureRelativeImportPath(getCachedModulePath2(sourcePath), resolvedModuleImport));
3356
3359
  }
3357
3360
  for (const [spec, resolvedModuleImport] of rewrittenModulePaths) {
3358
- transpiled = transpiled.replaceAll(spec, resolvedModuleImport);
3361
+ transpiled = replaceQuotedSpecifier(transpiled, spec, resolvedModuleImport);
3359
3362
  }
3360
3363
  let compiledCode = compile(transpiled, {
3361
3364
  css: "injected",
@@ -3367,10 +3370,10 @@ var serverCacheRoot2, compiledModuleCache2, originalSourcePathCache, syncIslandG
3367
3370
  hmr: isDevelopmentRuntime()
3368
3371
  }).js.code;
3369
3372
  for (const [spec, compiledChildPath] of childModulePaths) {
3370
- compiledCode = compiledCode.replaceAll(spec, ensureRelativeImportPath(getCachedModulePath2(sourcePath), compiledChildPath));
3373
+ compiledCode = replaceQuotedSpecifier(compiledCode, spec, ensureRelativeImportPath(getCachedModulePath2(sourcePath), compiledChildPath));
3371
3374
  }
3372
3375
  for (const [spec, resolvedModuleImport] of rewrittenModulePaths) {
3373
- compiledCode = compiledCode.replaceAll(spec, resolvedModuleImport);
3376
+ compiledCode = replaceQuotedSpecifier(compiledCode, spec, resolvedModuleImport);
3374
3377
  }
3375
3378
  const sourceId = JSON.stringify(relative3(process.cwd(), resolutionSourcePath).replace(/\\/g, "/"));
3376
3379
  const componentName = /export default function ([\w$]+)\s*\(/.exec(compiledCode)?.[1];
@@ -3466,7 +3469,13 @@ var serverCacheRoot3, compiledModuleCache3, syncIslandGeneration2, transpiler2,
3466
3469
  ].join(`
3467
3470
  `) : nonVueLines.join(`
3468
3471
  `);
3469
- }, extractRelativeVueImports = (sourceCode) => Array.from(sourceCode.matchAll(/import\s+[\s\S]+?['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((importPath) => typeof importPath === "string" && importPath.startsWith(".") && importPath.endsWith(".vue")), compileVueServerModule = async (sourcePath) => {
3472
+ }, RELATIVE_SPECIFIER_PATTERN, extractRelativeImports = (code) => Array.from(new Set(Array.from(code.matchAll(RELATIVE_SPECIFIER_PATTERN), (match) => match.groups?.spec).filter((spec) => spec !== undefined))), resolveFromSource = (spec, sourcePath) => {
3473
+ try {
3474
+ return Bun.resolveSync(spec, dirname4(sourcePath));
3475
+ } catch {
3476
+ return null;
3477
+ }
3478
+ }, compileVueServerModule = async (sourcePath) => {
3470
3479
  syncIslandGeneration2();
3471
3480
  const cachedModulePath = compiledModuleCache3.get(sourcePath);
3472
3481
  if (cachedModulePath)
@@ -3499,10 +3508,10 @@ var serverCacheRoot3, compiledModuleCache3, syncIslandGeneration2, transpiler2,
3499
3508
  ssr: true,
3500
3509
  ssrCssVars: descriptor.cssVars
3501
3510
  }).code : "const ssrRender = () => {};";
3502
- const childImportPaths = extractRelativeVueImports(compiledScript.content);
3503
- const compiledChildren = await Promise.all(childImportPaths.map(async (relativeImport) => ({
3504
- compiledPath: await compileVueServerModule(resolve5(dirname4(sourcePath), relativeImport)),
3505
- spec: relativeImport
3511
+ const relativeImports = extractRelativeImports(compiledScript.content);
3512
+ const compiledChildren = await Promise.all(relativeImports.filter((spec) => spec.endsWith(".vue")).map(async (spec) => ({
3513
+ compiledPath: await compileVueServerModule(resolve5(dirname4(sourcePath), spec)),
3514
+ spec
3506
3515
  })));
3507
3516
  const strippedScript = stripExports(compiledScript.content);
3508
3517
  const transpiledScript = transpiler2.transformSync(strippedScript);
@@ -3514,10 +3523,22 @@ var serverCacheRoot3, compiledModuleCache3, syncIslandGeneration2, transpiler2,
3514
3523
  ].join(`
3515
3524
  `));
3516
3525
  const compiledModulePath = getCachedModulePath3(sourcePath);
3517
- let rewritten = assembled;
3526
+ const rewrittenSpecifiers = new Map;
3518
3527
  for (const child of compiledChildren) {
3519
- rewritten = rewritten.replaceAll(child.spec, ensureRelativeImportPath2(compiledModulePath, child.compiledPath));
3528
+ rewrittenSpecifiers.set(child.spec, ensureRelativeImportPath2(compiledModulePath, child.compiledPath));
3520
3529
  }
3530
+ for (const spec of extractRelativeImports(assembled)) {
3531
+ if (rewrittenSpecifiers.has(spec))
3532
+ continue;
3533
+ const resolvedImport = resolveFromSource(spec, sourcePath);
3534
+ if (!resolvedImport)
3535
+ continue;
3536
+ rewrittenSpecifiers.set(spec, ensureRelativeImportPath2(compiledModulePath, resolvedImport));
3537
+ }
3538
+ const rewritten = assembled.replace(RELATIVE_SPECIFIER_PATTERN, (match, prefix, quote, spec) => {
3539
+ const target = rewrittenSpecifiers.get(spec);
3540
+ return target ? `${prefix}${quote}${target}${quote}` : match;
3541
+ });
3521
3542
  await mkdir3(dirname4(compiledModulePath), { recursive: true });
3522
3543
  await writeIfChanged2(compiledModulePath, rewritten);
3523
3544
  compiledModuleCache3.set(sourcePath, compiledModulePath);
@@ -3531,6 +3552,7 @@ var init_vueServerModule = __esm(() => {
3531
3552
  compiledModuleCache3.clear();
3532
3553
  });
3533
3554
  transpiler2 = new Transpiler({ loader: "ts", target: "browser" });
3555
+ RELATIVE_SPECIFIER_PATTERN = /(\bfrom\s*|\bimport\s*\(\s*|\bimport\s+)(['"])(?<spec>\.{1,2}\/[^'"]*)\2/g;
3534
3556
  });
3535
3557
 
3536
3558
  // src/core/islands.ts
@@ -17371,5 +17393,5 @@ export {
17371
17393
  withPendingTask
17372
17394
  };
17373
17395
 
17374
- //# debugId=165DD646F249EF6564756E2164756E21
17396
+ //# debugId=EE8416B3EE78941D64756E2164756E21
17375
17397
  //# sourceMappingURL=index.js.map