@absolutejs/absolute 0.19.0-beta.961 → 0.19.0-beta.963
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/dist/angular/browser.js +170 -44
- package/dist/angular/browser.js.map +9 -6
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/angular/components/stream-slot.component.js +3 -6
- package/dist/angular/index.js +123 -16
- package/dist/angular/index.js.map +10 -7
- package/dist/angular/server.js.map +3 -3
- package/dist/build.js +36 -17
- package/dist/build.js.map +16 -16
- package/dist/cli/index.js +1 -7
- package/dist/client/index.js.map +1 -1
- package/dist/index.js +36 -17
- package/dist/index.js.map +18 -18
- package/dist/islands/index.js.map +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/src/angular/browser.d.ts +2 -0
- package/dist/src/angular/components/stream-slot.component.d.ts +0 -1
- package/dist/src/angular/composables/index.d.ts +5 -0
- package/dist/src/angular/composables/useResource.d.ts +42 -0
- package/dist/src/angular/composables/useSubscription.d.ts +20 -0
- package/dist/src/angular/composables/useTimers.d.ts +18 -0
- package/dist/src/angular/index.d.ts +2 -0
- package/dist/src/vue/components/Image.d.ts +1 -1
- package/dist/svelte/index.js.map +1 -1
- package/dist/vue/index.js.map +1 -1
- package/package.json +4 -3
package/dist/cli/index.js
CHANGED
|
@@ -1518,13 +1518,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
|
|
|
1518
1518
|
return;
|
|
1519
1519
|
const angularScopeDir = resolve11(process.cwd(), "node_modules", "@angular");
|
|
1520
1520
|
const angularPackages = existsSync11(angularScopeDir) ? readdirSync2(angularScopeDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => entry.name !== "compiler-cli").map((entry) => `@angular/${entry.name}`) : [];
|
|
1521
|
-
const roots = new Set([
|
|
1522
|
-
...angularPackages,
|
|
1523
|
-
"rxjs",
|
|
1524
|
-
"tslib",
|
|
1525
|
-
"typescript",
|
|
1526
|
-
"zone.js"
|
|
1527
|
-
]);
|
|
1521
|
+
const roots = new Set([...angularPackages, "rxjs", "tslib", "typescript"]);
|
|
1528
1522
|
const seen = new Set;
|
|
1529
1523
|
for (const specifier of roots) {
|
|
1530
1524
|
copyPackageToBuild(specifier, outdir, seen);
|
package/dist/client/index.js.map
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"import { existsSync, readFileSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\n\n/**\n * Resolve Angular package paths from the compiled runtime node_modules first,\n * then the app's process.cwd()/node_modules, falling back to the bare specifier.\n * This prevents Bun's baked import.meta.dir from resolving Angular packages\n * from the absolutejs source tree instead of the consumer's project when\n * running from a published npm package.\n */\nexport const resolveAngularPackageDir = (specifier: string) => {\n\tconst fromCompiledRuntime = process.env.ABSOLUTE_BUILD_DIR\n\t\t? resolve(process.env.ABSOLUTE_BUILD_DIR, 'node_modules', specifier)\n\t\t: null;\n\tif (fromCompiledRuntime && existsSync(fromCompiledRuntime)) {\n\t\treturn fromCompiledRuntime;\n\t}\n\n\tconst fromProject = resolve(process.cwd(), 'node_modules', specifier);\n\n\tif (existsSync(fromProject)) {\n\t\treturn fromProject;\n\t}\n\n\treturn null;\n};\n\nconst resolvePackageEntry = (packageDir: string) => {\n\ttry {\n\t\tconst pkg = JSON.parse(\n\t\t\treadFileSync(join(packageDir, 'package.json'), 'utf-8')\n\t\t);\n\t\tconst rootExport = pkg.exports?.['.'];\n\t\tconst entry =\n\t\t\t(typeof rootExport === 'string'\n\t\t\t\t? rootExport\n\t\t\t\t: rootExport?.default) ??\n\t\t\tpkg.module ??\n\t\t\tpkg.main ??\n\t\t\t'index.js';\n\n\t\treturn join(packageDir, entry);\n\t} catch {\n\t\treturn packageDir;\n\t}\n};\n\nexport const resolveAngularPackage = (specifier: string) => {\n\tconst packageDir = resolveAngularPackageDir(specifier);\n\tif (packageDir) return resolvePackageEntry(packageDir);\n\n\treturn specifier;\n};\n\nconst toSafeVendorName = (specifier: string) =>\n\tspecifier.replace(/^@/, '').replace(/\\//g, '_');\n\n/** Prefer the linked Bun-target vendor file built by\n * `buildAngularServerVendor`. The file is at\n * `<ABSOLUTE_BUILD_DIR>/angular/vendor/server/<safe>.js`, which is what every\n * server bundle's `@angular/*` imports get rewritten to point at. Sharing\n * this path keeps SSR's class identity unified — the dual-package hazard\n * that produces NG0201 only appears when the runtime imports a *different*\n * copy from the bundles. Falls back to `resolveAngularPackage` (node_modules)\n * when no vendor file is available — e.g. running tests outside an\n * absolutejs build, or before the vendor pass completes. */\nexport const resolveAngularRuntimePath = (specifier: string) => {\n\tconst buildDirs = [\n\t\tprocess.env.ABSOLUTE_BUILD_DIR,\n\t\tresolve(process.cwd(), 'build')\n\t].filter((value): value is string => Boolean(value));\n\n\tfor (const buildDir of buildDirs) {\n\t\tconst vendorPath = join(\n\t\t\tbuildDir,\n\t\t\t'angular',\n\t\t\t'vendor',\n\t\t\t'server',\n\t\t\t`${toSafeVendorName(specifier)}.js`\n\t\t);\n\t\tif (existsSync(vendorPath)) return vendorPath;\n\t}\n\n\treturn resolveAngularPackage(specifier);\n};\n",
|
|
13
13
|
"/* Bundler-safe NODE_ENV reader.\n *\n * Bun (like esbuild and most modern bundlers) statically replaces\n * `process.env.NODE_ENV` with the build-time string. When absolutejs\n * itself is bundled (`bun run scripts/build.ts`), NODE_ENV is unset,\n * so every `process.env.NODE_ENV === 'production'` site collapses to\n * `false` and the production branch is dead-code-eliminated from\n * `dist/`. That breaks `bun start`, `bun compile`, and the standalone\n * compiled binary — they all run with NODE_ENV=production but see the\n * dev branches baked in.\n *\n * Computed-property access (`process.env[KEY]`) is NOT constant-folded\n * by Bun, so we read NODE_ENV through a string variable. Both branches\n * stay live in `dist/`, and the consumer's actual runtime NODE_ENV\n * decides which one fires.\n *\n * Verified empirically: Bun's bundler matches the literal AST shape\n * `MemberExpression { object: process.env, property: NODE_ENV }` for\n * its replacement. Computed-key access uses\n * `MemberExpression { computed: true, property: Identifier(KEY) }`,\n * which doesn't match the pattern. */\n\nconst ENV_VAR = 'NODE_ENV';\n\nexport const getNodeEnv = () => process.env[ENV_VAR];\n\nexport const isProductionRuntime = () => process.env[ENV_VAR] === 'production';\n\nexport const isDevelopmentRuntime = () =>\n\tprocess.env[ENV_VAR] === 'development';\n",
|
|
14
14
|
"import { resolveAngularRuntimePath } from './resolveAngularPackage';\nimport { isProductionRuntime } from '../utils/runtimeMode';\n\n// Patches Angular SSR's DominoAdapter to guard against null doc.head\n\nconst ensureHead = (doc: Document) => {\n\tif (!doc || doc.head || !doc.documentElement) {\n\t\treturn;\n\t}\n\n\tconst head = doc.createElement('head');\n\tdoc.documentElement.insertBefore(head, doc.documentElement.firstChild);\n};\n\n// Domino's Element does not implement layout APIs that browser components\n// (e.g. ngx-datatable, swiper, drag-drop) call eagerly during change detection.\n// Returning a zeroed DOMRect lets those components render in SSR without\n// crashing — the real values get computed once the page hydrates client-side.\nconst SSR_LAYOUT_RECT = Object.freeze({\n\tbottom: 0,\n\theight: 0,\n\tleft: 0,\n\tright: 0,\n\ttop: 0,\n\twidth: 0,\n\tx: 0,\n\ty: 0,\n\ttoJSON() {\n\t\treturn this;\n\t}\n});\nlet layoutPatchApplied = false;\nconst collectPrototypeChain = (instance: object | null) => {\n\tconst protos: object[] = [];\n\tlet current: object | null = instance\n\t\t? Object.getPrototypeOf(instance)\n\t\t: null;\n\twhile (current && current !== Object.prototype) {\n\t\tprotos.push(current);\n\t\tcurrent = Object.getPrototypeOf(current);\n\t}\n\n\treturn protos;\n};\n\nconst patchElementLayout = (doc: Document) => {\n\tif (layoutPatchApplied || !doc) {\n\t\treturn;\n\t}\n\tlet element: Element;\n\ttry {\n\t\telement = doc.createElement('div');\n\t} catch {\n\t\treturn;\n\t}\n\t// Walk the entire prototype chain so HTMLElement → Element → Node all get\n\t// the layout shims. Domino's base Element.prototype is several hops above\n\t// HTMLDivElement.prototype, and 3rd-party libs call methods anywhere along\n\t// the chain.\n\tconst protos = collectPrototypeChain(element);\n\tif (protos.length === 0) return;\n\n\tconst copyLayoutRect = (rect: typeof SSR_LAYOUT_RECT) => ({ ...rect });\n\tconst createLayoutRect = () => copyLayoutRect(SSR_LAYOUT_RECT);\n\tconst getClientRects = () => [];\n\tconst noop = () => undefined;\n\tconst numericProps = [\n\t\t'clientWidth',\n\t\t'clientHeight',\n\t\t'clientLeft',\n\t\t'clientTop',\n\t\t'offsetWidth',\n\t\t'offsetHeight',\n\t\t'offsetLeft',\n\t\t'offsetTop',\n\t\t'scrollWidth',\n\t\t'scrollHeight',\n\t\t'scrollLeft',\n\t\t'scrollTop'\n\t];\n\n\tfor (const proto of protos) {\n\t\tconst define = (name: string, value: unknown) => {\n\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(proto, name);\n\t\t\tif (typeof descriptor?.value === 'function') return;\n\n\t\t\tObject.defineProperty(proto, name, {\n\t\t\t\tconfigurable: true,\n\t\t\t\tvalue,\n\t\t\t\twritable: true\n\t\t\t});\n\t\t};\n\n\t\tdefine('getBoundingClientRect', createLayoutRect);\n\t\tdefine('getClientRects', getClientRects);\n\t\tdefine('scrollTo', noop);\n\t\tdefine('scrollBy', noop);\n\t\tdefine('scrollIntoView', noop);\n\t\tdefine('focus', noop);\n\t\tdefine('blur', noop);\n\n\t\tfor (const prop of numericProps) {\n\t\t\tconst desc = Object.getOwnPropertyDescriptor(proto, prop);\n\t\t\tif (desc) continue;\n\t\t\tObject.defineProperty(proto, prop, {\n\t\t\t\tconfigurable: true,\n\t\t\t\tget: () => 0\n\t\t\t});\n\t\t}\n\t}\n\n\tlayoutPatchApplied = true;\n};\n\nexport const applyPatches = async () => {\n\t// §1.1 — bare specifier in dev shares Bun's module cache with bundled\n\t// server pages. Production stays on the resolved vendor path. Use\n\t// `isProductionRuntime()` instead of a direct `process.env.NODE_ENV`\n\t// read so Bun's bundler doesn't constant-fold this branch out of\n\t// dist/ at absolutejs build time.\n\tconst spec = isProductionRuntime()\n\t\t? resolveAngularRuntimePath('@angular/platform-server')\n\t\t: '@angular/platform-server';\n\tconst { ɵDominoAdapter } = await import(spec);\n\tif (!ɵDominoAdapter?.prototype) {\n\t\tconsole.warn(\n\t\t\t'[Angular Patch] ɵDominoAdapter not found, skipping patches'\n\t\t);\n\n\t\treturn false;\n\t}\n\n\t// Patch the layout shims onto Domino's Element prototypes immediately\n\t// (don't wait for the first createHtmlDocument call). Components that\n\t// hold an ElementRef from the very first change-detection pass call\n\t// these methods before the lazy patch path would have run.\n\ttry {\n\t\tconst adapter = new ɵDominoAdapter();\n\t\tconst seedDoc =\n\t\t\ttypeof adapter.createHtmlDocument === 'function'\n\t\t\t\t? adapter.createHtmlDocument()\n\t\t\t\t: typeof adapter.getDefaultDocument === 'function'\n\t\t\t\t\t? adapter.getDefaultDocument()\n\t\t\t\t\t: null;\n\t\tif (seedDoc) {\n\t\t\tpatchElementLayout(seedDoc);\n\t\t\tconst probe = seedDoc.createElement('div') as Element & {\n\t\t\t\tgetBoundingClientRect?: () => DOMRect;\n\t\t\t};\n\t\t\tif (typeof probe.getBoundingClientRect !== 'function') {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t'[Angular Patch] Layout shim did not stick on probe element prototype chain'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tconsole.warn(\n\t\t\t'[Angular Patch] Could not eagerly patch Element prototypes:',\n\t\t\terror\n\t\t);\n\t}\n\n\tconst proto = ɵDominoAdapter.prototype;\n\n\tconst origGetBaseHref = proto.getBaseHref;\n\tproto.getBaseHref = function (doc: Document) {\n\t\tif (!doc || !doc.head || typeof doc.head.children === 'undefined') {\n\t\t\treturn '';\n\t\t}\n\n\t\treturn origGetBaseHref.call(this, doc);\n\t};\n\n\tconst origCreateHtmlDocument = proto.createHtmlDocument;\n\tproto.createHtmlDocument = function () {\n\t\tconst doc = origCreateHtmlDocument.call(this);\n\t\tensureHead(doc);\n\t\tpatchElementLayout(doc);\n\n\t\treturn doc;\n\t};\n\n\tconst origGetDefaultDocument = proto.getDefaultDocument;\n\tproto.getDefaultDocument = function () {\n\t\tconst doc = origGetDefaultDocument.call(this);\n\t\tensureHead(doc);\n\t\tpatchElementLayout(doc);\n\n\t\treturn doc;\n\t};\n\n\treturn true;\n};\n",
|
|
15
|
-
"import type { AngularDeps } from '../../types/angular';\nimport { resolveAngularRuntimePath } from './resolveAngularPackage';\nimport {\n\tisDevelopmentRuntime,\n\tisProductionRuntime\n} from '../utils/runtimeMode';\n\nconst initDominoAdapter = (platformServer: {\n\tɵDominoAdapter?: { makeCurrent?: () => void };\n}) => {\n\ttry {\n\t\tplatformServer.ɵDominoAdapter?.makeCurrent?.();\n\t} catch (err) {\n\t\tconsole.error('Failed to initialize DominoAdapter:', err);\n\t}\n};\n\nconst loadAngularDeps = async () => {\n\t// JIT compiler is only needed in development, where user pages are\n\t// runtime-compiled by `compileAngularFileJIT` and emit partial\n\t// declarations that need the compiler facade to link. In production\n\t// the linker has already processed every partial declaration into\n\t// final ɵdir/ɵcmp/ɵfac at vendor build time, so the compiler isn't\n\t// imported and isn't part of the prod vendor bundle.\n\tif (!isProductionRuntime()) {\n\t\t// Bare specifier in dev — Bun's module cache dedupes on\n\t\t// normalized specifier, so this is the same instance as the\n\t\t// `import \"@angular/compiler\"` baked into bundled server pages.\n\t\tawait import('@angular/compiler');\n\t}\n\n\t// angularPatch imports @angular/platform-server internally, so it\n\t// must also run after the compiler is available.\n\tconst { applyPatches } = await import('./angularPatch');\n\tawait applyPatches();\n\n\t// In dev (no Angular server vendor on disk — see §1.1), use bare\n\t// specifiers so Bun resolves them through node_modules and shares\n\t// the same module records with the bundled server pages, which\n\t// also have bare `@angular/*` imports in dev. Production keeps the\n\t// resolved-path import because the vendor bundle is what every\n\t// server-side import points at, and the resolved path is stable.\n\tconst useBareSpecifiers = !isProductionRuntime();\n\tconst [platformBrowser, platformServer, common, core] = await Promise.all([\n\t\timport(\n\t\t\tuseBareSpecifiers\n\t\t\t\t? '@angular/platform-browser'\n\t\t\t\t: resolveAngularRuntimePath('@angular/platform-browser')\n\t\t),\n\t\timport(\n\t\t\tuseBareSpecifiers\n\t\t\t\t? '@angular/platform-server'\n\t\t\t\t: resolveAngularRuntimePath('@angular/platform-server')\n\t\t),\n\t\timport(\n\t\t\tuseBareSpecifiers\n\t\t\t\t? '@angular/common'\n\t\t\t\t: resolveAngularRuntimePath('@angular/common')\n\t\t),\n\t\timport(\n\t\t\tuseBareSpecifiers\n\t\t\t\t? '@angular/core'\n\t\t\t\t: resolveAngularRuntimePath('@angular/core')\n\t\t)\n\t]);\n\n\tif (!isDevelopmentRuntime()) {\n\t\tcore.enableProdMode();\n\t}\n\n\tinitDominoAdapter(platformServer);\n\n\treturn {\n\t\tAPP_BASE_HREF: common.APP_BASE_HREF,\n\t\tbootstrapApplication: platformBrowser.bootstrapApplication,\n\t\tDomSanitizer: platformBrowser.DomSanitizer,\n\t\tENVIRONMENT_INITIALIZER: core.ENVIRONMENT_INITIALIZER,\n\t\tinject: core.inject,\n\t\tprovideClientHydration: platformBrowser.provideClientHydration,\n\t\tprovideServerRendering: platformServer.provideServerRendering,\n\t\tprovideZonelessChangeDetection: core.provideZonelessChangeDetection,\n\t\treflectComponentType: core.reflectComponentType,\n\t\trenderApplication: platformServer.renderApplication,\n\t\tREQUEST: core.REQUEST,\n\t\tREQUEST_CONTEXT: core.REQUEST_CONTEXT,\n\t\tRESPONSE_INIT: core.RESPONSE_INIT,\n\t\tSanitizer: core.Sanitizer,\n\t\tSecurityContext: core.SecurityContext,\n\t\twithHttpTransferCacheOptions:\n\t\t\tplatformBrowser.withHttpTransferCacheOptions\n\t};\n};\n\nlet angularDeps: Promise<AngularDeps> | null = null;\n\nexport const getAngularDeps = () => {\n\tif (!angularDeps) {\n\t\tangularDeps = loadAngularDeps();\n\t}\n\n\treturn angularDeps;\n};\n\n// TODO(test): the unit-style coverage in\n// `tests/integration/angular/single-core.test.ts` checks that\n// `resolveAngularRuntimePath` is consistent across calls and that two\n// dynamic imports from the resolved path return the same module record\n// — necessary but not sufficient. A stronger test would spawn a dev\n// server, trigger an HMR cycle, and assert the SSR process never sees\n// two `@angular/core` evaluations (e.g. via a marker incremented at\n// module init in a vendor stub). The fixture in\n// `tests/fixtures/compile-angular` is wired for compile-time checks\n// only, so end-to-end verification of the SSR core uniqueness fix\n// happens manually in `~/onspark/absolutejs/dealroom` (see\n// ABSOLUTEJS_ANGULAR_HMR.md §3.9).\n",
|
|
15
|
+
"import type { AngularDeps } from '../../types/angular';\nimport { resolveAngularRuntimePath } from './resolveAngularPackage';\nimport {\n\tisDevelopmentRuntime,\n\tisProductionRuntime\n} from '../utils/runtimeMode';\n\nconst initDominoAdapter = (platformServer: {\n\tɵDominoAdapter?: { makeCurrent?: () => void };\n}) => {\n\ttry {\n\t\tplatformServer.ɵDominoAdapter?.makeCurrent?.();\n\t} catch (err) {\n\t\tconsole.error('Failed to initialize DominoAdapter:', err);\n\t}\n};\n\nconst loadAngularDeps = async () => {\n\t// JIT compiler is only needed in development, where user pages are\n\t// runtime-compiled by `compileAngularFileJIT` and emit partial\n\t// declarations that need the compiler facade to link. In production\n\t// the linker has already processed every partial declaration into\n\t// final ɵdir/ɵcmp/ɵfac at vendor build time, so the compiler isn't\n\t// imported and isn't part of the prod vendor bundle.\n\tif (!isProductionRuntime()) {\n\t\t// Bare specifier in dev — Bun's module cache dedupes on\n\t\t// normalized specifier, so this is the same instance as the\n\t\t// `import \"@angular/compiler\"` baked into bundled server pages.\n\t\tawait import('@angular/compiler');\n\t}\n\n\t// angularPatch imports @angular/platform-server internally, so it\n\t// must also run after the compiler is available.\n\tconst { applyPatches } = await import('./angularPatch');\n\tawait applyPatches();\n\n\t// In dev (no Angular server vendor on disk — see §1.1), use bare\n\t// specifiers so Bun resolves them through node_modules and shares\n\t// the same module records with the bundled server pages, which\n\t// also have bare `@angular/*` imports in dev. Production keeps the\n\t// resolved-path import because the vendor bundle is what every\n\t// server-side import points at, and the resolved path is stable.\n\tconst useBareSpecifiers = !isProductionRuntime();\n\tconst [platformBrowser, platformServer, common, core] = await Promise.all([\n\t\timport(\n\t\t\tuseBareSpecifiers\n\t\t\t\t? '@angular/platform-browser'\n\t\t\t\t: resolveAngularRuntimePath('@angular/platform-browser')\n\t\t),\n\t\timport(\n\t\t\tuseBareSpecifiers\n\t\t\t\t? '@angular/platform-server'\n\t\t\t\t: resolveAngularRuntimePath('@angular/platform-server')\n\t\t),\n\t\timport(\n\t\t\tuseBareSpecifiers\n\t\t\t\t? '@angular/common'\n\t\t\t\t: resolveAngularRuntimePath('@angular/common')\n\t\t),\n\t\timport(\n\t\t\tuseBareSpecifiers\n\t\t\t\t? '@angular/core'\n\t\t\t\t: resolveAngularRuntimePath('@angular/core')\n\t\t)\n\t]);\n\n\tif (!isDevelopmentRuntime()) {\n\t\tcore.enableProdMode();\n\t}\n\n\tinitDominoAdapter(platformServer);\n\n\treturn {\n\t\tAPP_BASE_HREF: common.APP_BASE_HREF,\n\t\tbootstrapApplication: platformBrowser.bootstrapApplication,\n\t\tDomSanitizer: platformBrowser.DomSanitizer,\n\t\tENVIRONMENT_INITIALIZER: core.ENVIRONMENT_INITIALIZER,\n\t\tinject: core.inject,\n\t\tprovideClientHydration: platformBrowser.provideClientHydration,\n\t\tprovideServerRendering: platformServer.provideServerRendering,\n\t\tprovideZonelessChangeDetection: core.provideZonelessChangeDetection,\n\t\treflectComponentType: core.reflectComponentType,\n\t\trenderApplication: platformServer.renderApplication,\n\t\tREQUEST: core.REQUEST,\n\t\tREQUEST_CONTEXT: core.REQUEST_CONTEXT,\n\t\tRESPONSE_INIT: core.RESPONSE_INIT,\n\t\tSanitizer: core.Sanitizer,\n\t\tSecurityContext: core.SecurityContext,\n\t\twithHttpTransferCacheOptions:\n\t\t\tplatformBrowser.withHttpTransferCacheOptions\n\t};\n};\n\nlet angularDeps: Promise<AngularDeps> | null = null;\n\nexport const getAngularDeps = () => {\n\tif (!angularDeps) {\n\t\tangularDeps = loadAngularDeps();\n\t}\n\n\treturn angularDeps;\n};\n\n// TODO(test): the unit-style coverage in\n// `tests/integration/angular/single-core.test.ts` checks that\n// `resolveAngularRuntimePath` is consistent across calls and that two\n// dynamic imports from the resolved path return the same module record\n// — necessary but not sufficient. A stronger test would spawn a dev\n// server, trigger an HMR cycle, and assert the SSR process never sees\n// two `@angular/core` evaluations (e.g. via a marker incremented at\n// module init in a vendor stub). The fixture in\n// `tests/fixtures/compile-angular` is wired for compile-time checks\n// only, so end-to-end verification of the SSR core uniqueness fix\n// happens manually in `~/onspark/absolutejs/dealroom` (see\n// docs/ABSOLUTEJS_ANGULAR_HMR.md §3.9).\n",
|
|
16
16
|
"const normalizeSlug = (str: string) =>\n\tstr\n\t\t.trim()\n\t\t.replace(/\\s+/g, '-')\n\t\t.replace(/[^A-Za-z0-9\\-_]+/g, '')\n\t\t.replace(/[-_]{2,}/g, '-');\n\nexport const toKebab = (str: string) =>\n\tnormalizeSlug(str)\n\t\t.replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n\t\t.toLowerCase();\nexport const toPascal = (str: string) => {\n\tif (!str.includes('-') && !str.includes('_')) {\n\t\treturn str.charAt(0).toUpperCase() + str.slice(1);\n\t}\n\n\treturn normalizeSlug(str)\n\t\t.split(/[-_]/)\n\t\t.filter(Boolean)\n\t\t.map(\n\t\t\t(segment) =>\n\t\t\t\tsegment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()\n\t\t)\n\t\t.join('');\n};\nexport const toScreamingSnake = (str: string) =>\n\tstr.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();\n",
|
|
17
17
|
"/**\n * Utility for registering client-side scripts that need to run after Angular SSR hydration.\n *\n * This is necessary because Angular's lifecycle hooks don't always run reliably on the client\n * after SSR hydration, especially for event listeners attached to DOM elements.\n *\n * Usage in Angular components:\n * ```typescript\n * import { registerClientScript } from '@absolutejs/absolute';\n *\n * // Register an event listener script\n * registerClientScript(() => {\n * const element = document.querySelector('.my-element');\n * if (element) {\n * element.addEventListener('click', () => {\n * console.log('Clicked!');\n * });\n * }\n * });\n * ```\n *\n * The script will be automatically injected into the HTML response and executed on the client.\n */\n\n// Request-scoped registry for client scripts\n// Each request gets its own set of scripts to inject\nconst scriptRegistry = new Map<string, Set<() => void>>();\n\n// Generate a unique request ID for tracking scripts per request\nlet requestCounter = 0;\nconst getRequestId = () => `req_${Date.now()}_${++requestCounter}`;\n\n// Allow SSR frameworks to inject a request context getter (e.g. AsyncLocalStorage)\nlet ssrContextGetter: (() => string | undefined) | null = null;\nexport const getSsrContextId = () =>\n\tssrContextGetter?.() ||\n\tObject.getOwnPropertyDescriptor(globalThis, '__absolutejs_requestId')\n\t\t?.value;\nexport const registerClientScript = (\n\tscript: () => void,\n\trequestId?: string\n) => {\n\t// Try to get requestId from explicit arg, then Async Context, then global fallback\n\tconst id = requestId || getSsrContextId() || getRequestId();\n\n\tif (!scriptRegistry.has(id)) {\n\t\tscriptRegistry.set(id, new Set());\n\t}\n\n\tscriptRegistry.get(id)?.add(script);\n\n\treturn id;\n};\nexport const setSsrContextGetter = (getter: () => string | undefined) => {\n\tssrContextGetter = getter;\n};\n\n// Make registerClientScript available globally during SSR for Angular components\n// Using type assertion for globalThis extension\nif (typeof globalThis !== 'undefined') {\n\tObject.assign(globalThis, { registerClientScript });\n}\n\n/**\n * Get all registered scripts for a request and clear them.\n * This is called by the page handler after rendering.\n *\n * @param requestId - The request ID to get scripts for\n * @returns Array of script functions, or empty array if none registered\n */\nexport const clearAllClientScripts = () => {\n\tscriptRegistry.clear();\n};\nexport const generateClientScriptCode = (scripts: (() => void)[]) => {\n\tif (scripts.length === 0) {\n\t\treturn '';\n\t}\n\n\t// Convert functions to strings and wrap in IIFE\n\tconst scriptCode = scripts\n\t\t.map((script, index) => {\n\t\t\t// Get the function body as a string\n\t\t\tconst funcString = script.toString();\n\n\t\t\t// Extract the body (everything between { and })\n\t\t\tconst bodyMatch = funcString.match(/\\{([\\s\\S]*)\\}/);\n\t\t\tif (!bodyMatch || !bodyMatch[1]) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tconst body = bodyMatch[1].trim();\n\n\t\t\t// Wrap in IIFE with MutationObserver for DOM readiness\n\t\t\treturn `\n\t(function() {\n\t\tvar executed = false;\n\t\tfunction executeScript_${index}() {\n\t\t\tif (executed) return;\n\t\t\texecuted = true;\n\t\t\t${body}\n\t\t}\n\n\t\tif (document.readyState === 'complete' || document.readyState === 'interactive') {\n\t\t\texecuteScript_${index}();\n\t\t} else {\n\t\t\tdocument.addEventListener('DOMContentLoaded', executeScript_${index});\n\t\t}\n\n\t\t// Watch for hydration-added elements\n\t\tvar observer = new MutationObserver(function() {\n\t\t\texecuteScript_${index}();\n\t\t\tif (executed) observer.disconnect();\n\t\t});\n\t\tif (!executed) {\n\t\t\tobserver.observe(document.body || document.documentElement, { childList: true, subtree: true });\n\t\t}\n\n\t\t// Single fallback timeout\n\t\tsetTimeout(function() {\n\t\t\texecuteScript_${index}();\n\t\t\tobserver.disconnect();\n\t\t}, 1000);\n\t})();`;\n\t\t})\n\t\t.join('\\n');\n\n\treturn `<script>\n(function() {\n${scriptCode}\n})();\n</script>`;\n};\nexport const getAndClearClientScripts = (requestId?: string) => {\n\tconst id = requestId || ssrContextGetter?.();\n\tif (!id) return [];\n\n\tconst scripts = scriptRegistry.get(id);\n\tif (!scripts) {\n\t\treturn [];\n\t}\n\n\tconst scriptArray = Array.from(scripts);\n\tscriptRegistry.delete(id);\n\n\treturn scriptArray;\n};\n",
|
|
18
18
|
"import type { HttpTransferCacheOptions } from '@angular/common/http';\n\nexport const ABSOLUTE_HTTP_TRANSFER_CACHE_SKIP_HEADER = 'x-skip-transfer-cache';\n\nexport type AbsoluteHttpTransferCacheOptions = Omit<\n\tHttpTransferCacheOptions,\n\t'filter'\n> & {\n\tfilter?: NonNullable<HttpTransferCacheOptions['filter']>;\n\tskipHeader?: string;\n};\n\nexport const buildAbsoluteHttpTransferCacheOptions = (\n\toptions: AbsoluteHttpTransferCacheOptions = {}\n) => {\n\tconst {\n\t\tfilter: userFilter,\n\t\tskipHeader = ABSOLUTE_HTTP_TRANSFER_CACHE_SKIP_HEADER,\n\t\t...angularOptions\n\t} = options;\n\n\treturn {\n\t\tincludePostRequests: false,\n\t\tincludeRequestsWithAuthHeaders: false,\n\t\t...angularOptions,\n\t\tfilter: (request) =>\n\t\t\t!request.headers.has(skipHeader) && (userFilter?.(request) ?? true)\n\t} satisfies HttpTransferCacheOptions;\n};\n",
|
package/dist/index.js
CHANGED
|
@@ -10718,17 +10718,12 @@ var DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, DEFAULT_QUALITY, OPTIMIZATION_END
|
|
|
10718
10718
|
return actual.startsWith(prefix);
|
|
10719
10719
|
}
|
|
10720
10720
|
return actual === pattern;
|
|
10721
|
-
}, MIME_MAP, isSharpFactory = (value) => typeof value === "function",
|
|
10722
|
-
if (!isSharpFactory(sharpRef)) {
|
|
10723
|
-
throw new Error("Loaded sharp module is not callable.");
|
|
10724
|
-
}
|
|
10725
|
-
return sharpRef(input);
|
|
10726
|
-
}, toBuffer = (input) => {
|
|
10721
|
+
}, MIME_MAP, isSharpFactory = (value) => typeof value === "function", toBuffer = (input) => {
|
|
10727
10722
|
if (Buffer.isBuffer(input))
|
|
10728
10723
|
return input;
|
|
10729
10724
|
return Buffer.from(input);
|
|
10730
|
-
}, buildOptimizedUrl = (src, width, quality, basePath = OPTIMIZATION_ENDPOINT) => `${basePath}?url=${encodeURIComponent(src)}&w=${width}&q=${quality}`, formatToMime = (format) => MIME_MAP[format], generateBlurSvg = (base64Thumbnail) => {
|
|
10731
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 320"><filter id="b" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="${BLUR_DEVIATION}"/><feColorMatrix values="1 0 0 0 0 0 1 0 0 0 0 0
|
|
10725
|
+
}, isUnsupportedFormatError = (err) => typeof err === "object" && err !== null && ("code" in err) && err.code === "ERR_IMAGE_FORMAT_UNSUPPORTED", buildOptimizedUrl = (src, width, quality, basePath = OPTIMIZATION_ENDPOINT) => `${basePath}?url=${encodeURIComponent(src)}&w=${width}&q=${quality}`, formatToMime = (format) => MIME_MAP[format], generateBlurSvg = (base64Thumbnail) => {
|
|
10726
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 320"><filter id="b" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="${BLUR_DEVIATION}"/><feColorMatrix values="1 0 0 0 0 0 1 0 0 0 0 0 100 -1"/></filter><image filter="url(#b)" x="0" y="0" width="100%" height="100%" href="${base64Thumbnail}"/></svg>`;
|
|
10732
10727
|
const encoded = encodeURIComponent(svg);
|
|
10733
10728
|
return `url("data:image/svg+xml,${encoded}")`;
|
|
10734
10729
|
}, generateSrcSet = (src, width, sizes, config, loader) => {
|
|
@@ -10788,11 +10783,24 @@ var DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, DEFAULT_QUALITY, OPTIMIZATION_END
|
|
|
10788
10783
|
return "webp";
|
|
10789
10784
|
}
|
|
10790
10785
|
return "jpeg";
|
|
10791
|
-
}, AVIF_QUALITY_OFFSET = 20, AVIF_EFFORT = 3,
|
|
10792
|
-
const
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
10786
|
+
}, AVIF_QUALITY_OFFSET = 20, AVIF_EFFORT = 3, PNG_COMPRESSION_LEVEL = 9, optimizeWithBunImage = async (buffer, width, quality, format) => {
|
|
10787
|
+
const pipeline = new Bun.Image(buffer).resize(width, undefined, {
|
|
10788
|
+
withoutEnlargement: true
|
|
10789
|
+
});
|
|
10790
|
+
switch (format) {
|
|
10791
|
+
case "avif":
|
|
10792
|
+
return pipeline.avif({
|
|
10793
|
+
quality: Math.max(1, quality - AVIF_QUALITY_OFFSET)
|
|
10794
|
+
}).toBuffer();
|
|
10795
|
+
case "jpeg":
|
|
10796
|
+
return pipeline.jpeg({ quality }).toBuffer();
|
|
10797
|
+
case "png":
|
|
10798
|
+
return pipeline.png({ compressionLevel: PNG_COMPRESSION_LEVEL }).toBuffer();
|
|
10799
|
+
case "webp":
|
|
10800
|
+
return pipeline.webp({ quality }).toBuffer();
|
|
10801
|
+
}
|
|
10802
|
+
}, optimizeWithSharp = async (sharpRef, buffer, width, quality, format) => {
|
|
10803
|
+
const pipeline = sharpRef(buffer).rotate().resize(width, undefined, { withoutEnlargement: true });
|
|
10796
10804
|
switch (format) {
|
|
10797
10805
|
case "avif":
|
|
10798
10806
|
return pipeline.avif({
|
|
@@ -10805,8 +10813,19 @@ var DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, DEFAULT_QUALITY, OPTIMIZATION_END
|
|
|
10805
10813
|
return pipeline.png({ quality }).toBuffer();
|
|
10806
10814
|
case "webp":
|
|
10807
10815
|
return pipeline.webp({ quality }).toBuffer();
|
|
10808
|
-
|
|
10809
|
-
|
|
10816
|
+
}
|
|
10817
|
+
}, optimizeImage = async (buffer, width, quality, format) => {
|
|
10818
|
+
const input = toBuffer(buffer);
|
|
10819
|
+
try {
|
|
10820
|
+
return await optimizeWithBunImage(input, width, quality, format);
|
|
10821
|
+
} catch (err) {
|
|
10822
|
+
if (format === "avif" && isUnsupportedFormatError(err)) {
|
|
10823
|
+
const sharp = await tryLoadSharp();
|
|
10824
|
+
if (sharp && isSharpFactory(sharp)) {
|
|
10825
|
+
return optimizeWithSharp(sharp, input, width, quality, format);
|
|
10826
|
+
}
|
|
10827
|
+
}
|
|
10828
|
+
throw err;
|
|
10810
10829
|
}
|
|
10811
10830
|
}, readFromCache = (cacheDir, cacheKey) => {
|
|
10812
10831
|
const metaPath = join15(cacheDir, `${cacheKey}.meta`);
|
|
@@ -10833,7 +10852,7 @@ var DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, DEFAULT_QUALITY, OPTIMIZATION_END
|
|
|
10833
10852
|
if (sharpWarned)
|
|
10834
10853
|
return null;
|
|
10835
10854
|
sharpWarned = true;
|
|
10836
|
-
console.warn(
|
|
10855
|
+
console.warn('[image] AVIF requested but sharp not installed and Bun.Image cannot encode AVIF on this platform. Install sharp (`bun add sharp`) to enable AVIF, or remove "avif" from your image formats config. See docs/SHARP_REMOVAL.md for context.');
|
|
10837
10856
|
return null;
|
|
10838
10857
|
}
|
|
10839
10858
|
}, writeToCache = (cacheDir, cacheKey, buffer, meta) => {
|
|
@@ -34957,5 +34976,5 @@ export {
|
|
|
34957
34976
|
ANGULAR_INIT_TIMEOUT_MS
|
|
34958
34977
|
};
|
|
34959
34978
|
|
|
34960
|
-
//# debugId=
|
|
34979
|
+
//# debugId=C420045FC8B0290064756E2164756E21
|
|
34961
34980
|
//# sourceMappingURL=index.js.map
|