@c9up/aurora 0.1.18 → 0.1.20

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.
@@ -38,6 +38,19 @@ export interface AuroraManagerConfig {
38
38
  * for an underscore-free scheme. An explicit `pages.urlPrefix` still wins.
39
39
  */
40
40
  assetsPrefix?: string;
41
+ /**
42
+ * App-level importmap overrides, configured ONCE here (the AdonisJS model:
43
+ * config lives in `config/aurora.ts`, controllers stay thin and never hand-write
44
+ * importmaps). Merged over aurora's auto defaults (`@c9up/aurora`,
45
+ * `@c9up/aurora/rpc`, `@c9up/comet`) on every `render()`. Use to point a bare
46
+ * specifier at a curated browser entry, e.g.
47
+ * `{ '@c9up/aurora': '/_assets/pages/browser/aurora.js' }`. A per-call
48
+ * `render(..., { importmap })` still wins over this.
49
+ *
50
+ * (Importmaps are aurora's no-bundler particularity — AdonisJS bundles via Vite
51
+ * and has no importmap; we keep the config-driven shape to stay Adonis-idiomatic.)
52
+ */
53
+ importmap?: Record<string, string>;
41
54
  }
42
55
  export declare class AuroraManager {
43
56
  readonly pages: Pages;
@@ -52,12 +65,15 @@ export declare class AuroraManager {
52
65
  readonly cometAssetPath: string;
53
66
  /** Resolved `@c9up/comet` dist dir, or `null` when comet isn't installed. */
54
67
  readonly cometDistRoot: string | null;
68
+ /** App-level importmap overrides from `config/aurora.ts`, merged on render. */
69
+ readonly importmap: Record<string, string>;
55
70
  constructor(config: AuroraManagerConfig);
56
71
  /**
57
- * SSR + hydrate + ship the document. The importmap default points
58
- * `@c9up/aurora` at this manager's `assetsPrefix`; a caller's
59
- * `options.importmap` still overrides (e.g. to remap to an app-curated
60
- * browser entry).
72
+ * SSR + hydrate + ship the document. The importmap layers, last wins:
73
+ * aurora's auto defaults (`@c9up/aurora`, `@c9up/aurora/rpc`, `@c9up/comet`)
74
+ * < the config-level `importmap` (from `config/aurora.ts`) < a per-call
75
+ * `options.importmap`. So a thin controller calls `render(ctx, name, props)`
76
+ * with no importmap, and any curation lives once in config.
61
77
  */
62
78
  render(ctx: RenderHttpContext, name: string, props: unknown, options?: RenderPageOptions): Promise<void>;
63
79
  /**
@@ -48,12 +48,15 @@ export class AuroraManager {
48
48
  cometAssetPath;
49
49
  /** Resolved `@c9up/comet` dist dir, or `null` when comet isn't installed. */
50
50
  cometDistRoot;
51
+ /** App-level importmap overrides from `config/aurora.ts`, merged on render. */
52
+ importmap;
51
53
  constructor(config) {
52
54
  this.assetsPrefix = normalizePrefix(config.assetsPrefix ?? "/_assets");
53
55
  this.auroraAssetPath = `${this.assetsPrefix}/aurora`;
54
56
  this.pageAssetPath = `${this.assetsPrefix}/pages`;
55
57
  this.cometAssetPath = `${this.assetsPrefix}/comet`;
56
58
  this.cometDistRoot = config.cometDistRoot ?? resolveCometDist();
59
+ this.importmap = config.importmap ?? {};
57
60
  // Pages serve their compiled JS from the same prefix unless the app
58
61
  // pins an explicit urlPrefix.
59
62
  this.pages = new Pages({
@@ -63,22 +66,31 @@ export class AuroraManager {
63
66
  this.auroraDistRoot = config.auroraDistRoot ?? DEFAULT_AURORA_DIST;
64
67
  }
65
68
  /**
66
- * SSR + hydrate + ship the document. The importmap default points
67
- * `@c9up/aurora` at this manager's `assetsPrefix`; a caller's
68
- * `options.importmap` still overrides (e.g. to remap to an app-curated
69
- * browser entry).
69
+ * SSR + hydrate + ship the document. The importmap layers, last wins:
70
+ * aurora's auto defaults (`@c9up/aurora`, `@c9up/aurora/rpc`, `@c9up/comet`)
71
+ * < the config-level `importmap` (from `config/aurora.ts`) < a per-call
72
+ * `options.importmap`. So a thin controller calls `render(ctx, name, props)`
73
+ * with no importmap, and any curation lives once in config.
70
74
  */
71
75
  render(ctx, name, props, options) {
72
76
  return renderPage(ctx, this.pages, name, props, {
73
77
  ...options,
74
78
  importmap: {
75
79
  "@c9up/aurora": `${this.auroraAssetPath}/index.js`,
76
- // Auto-map @c9up/comet when installed so `@c9up/aurora/rpc`'s bare
80
+ // The browser-facing subpath (RPC client) needs an explicit entry —
81
+ // importmaps don't read package `exports`, and an extensionless bare
82
+ // specifier won't hit a trailing-slash prefix map. Served from the
83
+ // same aurora dist; harmless when a page never imports it.
84
+ "@c9up/aurora/rpc": `${this.auroraAssetPath}/rpc.js`,
85
+ // Auto-map @c9up/comet when installed so the rpc client's bare
77
86
  // `import '@c9up/comet'` resolves in the no-bundler browser — no
78
87
  // app-side importmap wiring. Omitted when comet isn't present.
79
88
  ...(this.cometDistRoot
80
89
  ? { "@c9up/comet": `${this.cometAssetPath}/index.js` }
81
90
  : {}),
91
+ // Config-level overrides (config/aurora.ts) — Adonis-style config-driven,
92
+ // so controllers never hand-write an importmap. A per-call override wins.
93
+ ...this.importmap,
82
94
  ...options?.importmap,
83
95
  },
84
96
  });
package/dist/live.d.ts CHANGED
@@ -53,3 +53,8 @@ export interface LiveSession {
53
53
  * every session then reads the same signal and patches on its change.
54
54
  */
55
55
  export declare function mountLiveSession(factory: () => LiveComponentDefinition): LiveSession;
56
+ export { connectPatches, type LiveStore, liveStore, type RelayBroadcaster, } from "./liveBroadcast.js";
57
+ export { buildLiveTransport, type LiveClientOptions, type LiveClientTransport, type LiveHttpPoster, liveClient, type RelaySubscribeClient, } from "./liveClient.js";
58
+ export { createLiveRegistry, type LiveRegistry, type LiveSessionHandle, } from "./liveRegistry.js";
59
+ export { createLiveRouter, type LiveMount, type LiveRouter, } from "./liveRouter.js";
60
+ export { DEFAULT_LIVE_EVENT_PATH, type LiveHttpContext, type LiveHttpRouter, type WireLiveEventsOptions, wireLiveEvents, } from "./liveServer.js";
package/dist/live.js CHANGED
@@ -94,3 +94,15 @@ export function mountLiveSession(factory) {
94
94
  },
95
95
  };
96
96
  }
97
+ // ─── `@c9up/aurora/live` barrel ──────────────────────────────────────
98
+ //
99
+ // The Live stack (broadcast / client / registry / router / server) is
100
+ // re-exported here so the whole niche surface lives behind ONE subpath,
101
+ // `@c9up/aurora/live` — keeping the main `.` barrel lean (it no longer
102
+ // eager-pulls these into every browser graph), consistent with how `./ssr`,
103
+ // `./relay`, `./rpc` and `./hydrate` are already subpath-gated.
104
+ export { connectPatches, liveStore, } from "./liveBroadcast.js";
105
+ export { buildLiveTransport, liveClient, } from "./liveClient.js";
106
+ export { createLiveRegistry, } from "./liveRegistry.js";
107
+ export { createLiveRouter, } from "./liveRouter.js";
108
+ export { DEFAULT_LIVE_EVENT_PATH, wireLiveEvents, } from "./liveServer.js";
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `auroraContext` — binds `ctx.aurora.render(name, props)` onto the request
3
+ * context, the AdonisJS ctx-service idiom (the `ctx.view` / `ctx.inertia`
4
+ * analog). Register it globally in your kernel; a thin controller then does:
5
+ *
6
+ * async show({ aurora }: HttpContext) {
7
+ * return aurora.render('Dashboard', { user, stats })
8
+ * }
9
+ *
10
+ * Agnostic: it resolves the AuroraManager from the request container
11
+ * (`ctx.containerResolver.make('aurora')`) — never imports `@c9up/ream` — and is
12
+ * a no-op when no manager is registered. The module-level `aurora.render(ctx, …)`
13
+ * service still works; this is the ctx-bound sugar.
14
+ */
15
+ import type { RenderHttpContext, RenderPageOptions } from "./server/renderPage.js";
16
+ /** The `ctx.aurora` surface — ctx-bound render (no explicit ctx argument). */
17
+ export interface AuroraRequestRenderer {
18
+ render(name: string, props?: unknown, options?: RenderPageOptions): Promise<void>;
19
+ }
20
+ /** Request context the middleware needs: render target + optional resolver/slot. */
21
+ interface AuroraMiddlewareContext extends RenderHttpContext {
22
+ containerResolver?: {
23
+ make(token: unknown): unknown;
24
+ };
25
+ aurora?: AuroraRequestRenderer;
26
+ }
27
+ /**
28
+ * Middleware: attach `ctx.aurora` for the request. No-op (passes through) when
29
+ * the AuroraManager isn't registered, so it's safe to mount unconditionally.
30
+ */
31
+ export declare function auroraContext(ctx: AuroraMiddlewareContext, next: () => Promise<void>): Promise<void>;
32
+ export {};
@@ -0,0 +1,43 @@
1
+ /**
2
+ * `auroraContext` — binds `ctx.aurora.render(name, props)` onto the request
3
+ * context, the AdonisJS ctx-service idiom (the `ctx.view` / `ctx.inertia`
4
+ * analog). Register it globally in your kernel; a thin controller then does:
5
+ *
6
+ * async show({ aurora }: HttpContext) {
7
+ * return aurora.render('Dashboard', { user, stats })
8
+ * }
9
+ *
10
+ * Agnostic: it resolves the AuroraManager from the request container
11
+ * (`ctx.containerResolver.make('aurora')`) — never imports `@c9up/ream` — and is
12
+ * a no-op when no manager is registered. The module-level `aurora.render(ctx, …)`
13
+ * service still works; this is the ctx-bound sugar.
14
+ */
15
+ /** Structural check that a resolved value is render-capable (an AuroraManager). */
16
+ function isManager(value) {
17
+ return (typeof value === "object" &&
18
+ value !== null &&
19
+ "render" in value &&
20
+ typeof value.render === "function");
21
+ }
22
+ function resolveManager(resolver) {
23
+ try {
24
+ const resolved = resolver?.make("aurora");
25
+ return isManager(resolved) ? resolved : undefined;
26
+ }
27
+ catch {
28
+ return undefined;
29
+ }
30
+ }
31
+ /**
32
+ * Middleware: attach `ctx.aurora` for the request. No-op (passes through) when
33
+ * the AuroraManager isn't registered, so it's safe to mount unconditionally.
34
+ */
35
+ export function auroraContext(ctx, next) {
36
+ const manager = resolveManager(ctx.containerResolver);
37
+ if (manager) {
38
+ ctx.aurora = {
39
+ render: (name, props, options) => manager.render(ctx, name, props, options),
40
+ };
41
+ }
42
+ return next();
43
+ }
package/dist/server.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { AuroraManager, type AuroraManagerConfig } from "./AuroraManager.js";
2
+ export { type AuroraRequestRenderer, auroraContext, } from "./middleware.js";
2
3
  export { type PageFactory, Pages, type PagesConfig } from "./Pages.js";
3
4
  export { type RenderHttpContext, type RenderPageOptions, type RenderResponse, renderPage, } from "./server/renderPage.js";
4
5
  export { type AssetsHttpContext, type AssetsRequest, type AssetsResponse, packageAssetDir, type ServeAssetsOptions, serveAssets, } from "./server/serveAssets.js";
package/dist/server.js CHANGED
@@ -5,6 +5,7 @@
5
5
  // Node built-ins through the import graph. Server code imports from
6
6
  // `@c9up/aurora/server`; the client `.` entry stays node-free.
7
7
  export { AuroraManager } from "./AuroraManager.js";
8
+ export { auroraContext, } from "./middleware.js";
8
9
  export { Pages } from "./Pages.js";
9
10
  export { renderPage, } from "./server/renderPage.js";
10
11
  export { packageAssetDir, serveAssets, } from "./server/serveAssets.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c9up/aurora",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "Aurora — reactive UI runtime for the Ream framework. Tagged-template DOM, signal-based state, isomorphic SSR + hydration, zero build step.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -50,6 +50,19 @@ export interface AuroraManagerConfig {
50
50
  * for an underscore-free scheme. An explicit `pages.urlPrefix` still wins.
51
51
  */
52
52
  assetsPrefix?: string;
53
+ /**
54
+ * App-level importmap overrides, configured ONCE here (the AdonisJS model:
55
+ * config lives in `config/aurora.ts`, controllers stay thin and never hand-write
56
+ * importmaps). Merged over aurora's auto defaults (`@c9up/aurora`,
57
+ * `@c9up/aurora/rpc`, `@c9up/comet`) on every `render()`. Use to point a bare
58
+ * specifier at a curated browser entry, e.g.
59
+ * `{ '@c9up/aurora': '/_assets/pages/browser/aurora.js' }`. A per-call
60
+ * `render(..., { importmap })` still wins over this.
61
+ *
62
+ * (Importmaps are aurora's no-bundler particularity — AdonisJS bundles via Vite
63
+ * and has no importmap; we keep the config-driven shape to stay Adonis-idiomatic.)
64
+ */
65
+ importmap?: Record<string, string>;
53
66
  }
54
67
 
55
68
  const DEFAULT_AURORA_DIST = resolvePath(
@@ -89,6 +102,8 @@ export class AuroraManager {
89
102
  readonly cometAssetPath: string;
90
103
  /** Resolved `@c9up/comet` dist dir, or `null` when comet isn't installed. */
91
104
  readonly cometDistRoot: string | null;
105
+ /** App-level importmap overrides from `config/aurora.ts`, merged on render. */
106
+ readonly importmap: Record<string, string>;
92
107
 
93
108
  constructor(config: AuroraManagerConfig) {
94
109
  this.assetsPrefix = normalizePrefix(config.assetsPrefix ?? "/_assets");
@@ -96,6 +111,7 @@ export class AuroraManager {
96
111
  this.pageAssetPath = `${this.assetsPrefix}/pages`;
97
112
  this.cometAssetPath = `${this.assetsPrefix}/comet`;
98
113
  this.cometDistRoot = config.cometDistRoot ?? resolveCometDist();
114
+ this.importmap = config.importmap ?? {};
99
115
  // Pages serve their compiled JS from the same prefix unless the app
100
116
  // pins an explicit urlPrefix.
101
117
  this.pages = new Pages({
@@ -106,10 +122,11 @@ export class AuroraManager {
106
122
  }
107
123
 
108
124
  /**
109
- * SSR + hydrate + ship the document. The importmap default points
110
- * `@c9up/aurora` at this manager's `assetsPrefix`; a caller's
111
- * `options.importmap` still overrides (e.g. to remap to an app-curated
112
- * browser entry).
125
+ * SSR + hydrate + ship the document. The importmap layers, last wins:
126
+ * aurora's auto defaults (`@c9up/aurora`, `@c9up/aurora/rpc`, `@c9up/comet`)
127
+ * < the config-level `importmap` (from `config/aurora.ts`) < a per-call
128
+ * `options.importmap`. So a thin controller calls `render(ctx, name, props)`
129
+ * with no importmap, and any curation lives once in config.
113
130
  */
114
131
  render(
115
132
  ctx: RenderHttpContext,
@@ -121,12 +138,20 @@ export class AuroraManager {
121
138
  ...options,
122
139
  importmap: {
123
140
  "@c9up/aurora": `${this.auroraAssetPath}/index.js`,
124
- // Auto-map @c9up/comet when installed so `@c9up/aurora/rpc`'s bare
141
+ // The browser-facing subpath (RPC client) needs an explicit entry —
142
+ // importmaps don't read package `exports`, and an extensionless bare
143
+ // specifier won't hit a trailing-slash prefix map. Served from the
144
+ // same aurora dist; harmless when a page never imports it.
145
+ "@c9up/aurora/rpc": `${this.auroraAssetPath}/rpc.js`,
146
+ // Auto-map @c9up/comet when installed so the rpc client's bare
125
147
  // `import '@c9up/comet'` resolves in the no-bundler browser — no
126
148
  // app-side importmap wiring. Omitted when comet isn't present.
127
149
  ...(this.cometDistRoot
128
150
  ? { "@c9up/comet": `${this.cometAssetPath}/index.js` }
129
151
  : {}),
152
+ // Config-level overrides (config/aurora.ts) — Adonis-style config-driven,
153
+ // so controllers never hand-write an importmap. A per-call override wins.
154
+ ...this.importmap,
130
155
  ...options?.importmap,
131
156
  },
132
157
  });
package/src/live.ts CHANGED
@@ -130,3 +130,42 @@ export function mountLiveSession(
130
130
  },
131
131
  };
132
132
  }
133
+
134
+ // ─── `@c9up/aurora/live` barrel ──────────────────────────────────────
135
+ //
136
+ // The Live stack (broadcast / client / registry / router / server) is
137
+ // re-exported here so the whole niche surface lives behind ONE subpath,
138
+ // `@c9up/aurora/live` — keeping the main `.` barrel lean (it no longer
139
+ // eager-pulls these into every browser graph), consistent with how `./ssr`,
140
+ // `./relay`, `./rpc` and `./hydrate` are already subpath-gated.
141
+ export {
142
+ connectPatches,
143
+ type LiveStore,
144
+ liveStore,
145
+ type RelayBroadcaster,
146
+ } from "./liveBroadcast.js";
147
+ export {
148
+ buildLiveTransport,
149
+ type LiveClientOptions,
150
+ type LiveClientTransport,
151
+ type LiveHttpPoster,
152
+ liveClient,
153
+ type RelaySubscribeClient,
154
+ } from "./liveClient.js";
155
+ export {
156
+ createLiveRegistry,
157
+ type LiveRegistry,
158
+ type LiveSessionHandle,
159
+ } from "./liveRegistry.js";
160
+ export {
161
+ createLiveRouter,
162
+ type LiveMount,
163
+ type LiveRouter,
164
+ } from "./liveRouter.js";
165
+ export {
166
+ DEFAULT_LIVE_EVENT_PATH,
167
+ type LiveHttpContext,
168
+ type LiveHttpRouter,
169
+ type WireLiveEventsOptions,
170
+ wireLiveEvents,
171
+ } from "./liveServer.js";
@@ -0,0 +1,74 @@
1
+ /**
2
+ * `auroraContext` — binds `ctx.aurora.render(name, props)` onto the request
3
+ * context, the AdonisJS ctx-service idiom (the `ctx.view` / `ctx.inertia`
4
+ * analog). Register it globally in your kernel; a thin controller then does:
5
+ *
6
+ * async show({ aurora }: HttpContext) {
7
+ * return aurora.render('Dashboard', { user, stats })
8
+ * }
9
+ *
10
+ * Agnostic: it resolves the AuroraManager from the request container
11
+ * (`ctx.containerResolver.make('aurora')`) — never imports `@c9up/ream` — and is
12
+ * a no-op when no manager is registered. The module-level `aurora.render(ctx, …)`
13
+ * service still works; this is the ctx-bound sugar.
14
+ */
15
+
16
+ import type { AuroraManager } from "./AuroraManager.js";
17
+ import type {
18
+ RenderHttpContext,
19
+ RenderPageOptions,
20
+ } from "./server/renderPage.js";
21
+
22
+ /** The `ctx.aurora` surface — ctx-bound render (no explicit ctx argument). */
23
+ export interface AuroraRequestRenderer {
24
+ render(
25
+ name: string,
26
+ props?: unknown,
27
+ options?: RenderPageOptions,
28
+ ): Promise<void>;
29
+ }
30
+
31
+ /** Request context the middleware needs: render target + optional resolver/slot. */
32
+ interface AuroraMiddlewareContext extends RenderHttpContext {
33
+ containerResolver?: { make(token: unknown): unknown };
34
+ aurora?: AuroraRequestRenderer;
35
+ }
36
+
37
+ /** Structural check that a resolved value is render-capable (an AuroraManager). */
38
+ function isManager(value: unknown): value is AuroraManager {
39
+ return (
40
+ typeof value === "object" &&
41
+ value !== null &&
42
+ "render" in value &&
43
+ typeof value.render === "function"
44
+ );
45
+ }
46
+
47
+ function resolveManager(
48
+ resolver: { make(token: unknown): unknown } | undefined,
49
+ ): AuroraManager | undefined {
50
+ try {
51
+ const resolved = resolver?.make("aurora");
52
+ return isManager(resolved) ? resolved : undefined;
53
+ } catch {
54
+ return undefined;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Middleware: attach `ctx.aurora` for the request. No-op (passes through) when
60
+ * the AuroraManager isn't registered, so it's safe to mount unconditionally.
61
+ */
62
+ export function auroraContext(
63
+ ctx: AuroraMiddlewareContext,
64
+ next: () => Promise<void>,
65
+ ): Promise<void> {
66
+ const manager = resolveManager(ctx.containerResolver);
67
+ if (manager) {
68
+ ctx.aurora = {
69
+ render: (name, props, options) =>
70
+ manager.render(ctx, name, props, options),
71
+ };
72
+ }
73
+ return next();
74
+ }
package/src/server.ts CHANGED
@@ -6,6 +6,10 @@
6
6
  // `@c9up/aurora/server`; the client `.` entry stays node-free.
7
7
 
8
8
  export { AuroraManager, type AuroraManagerConfig } from "./AuroraManager.js";
9
+ export {
10
+ type AuroraRequestRenderer,
11
+ auroraContext,
12
+ } from "./middleware.js";
9
13
  export { type PageFactory, Pages, type PagesConfig } from "./Pages.js";
10
14
  export {
11
15
  type RenderHttpContext,