@gracile/engine 0.8.2 → 0.9.0-next.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/dev/development.d.ts.map +1 -1
  2. package/dist/dev/development.js +1 -1
  3. package/dist/dev/ssr-ce-tracker.d.ts +27 -0
  4. package/dist/dev/ssr-ce-tracker.d.ts.map +1 -0
  5. package/dist/dev/ssr-ce-tracker.js +113 -0
  6. package/dist/errors/create-vite-better-error.js +1 -1
  7. package/dist/plugin.d.ts.map +1 -1
  8. package/dist/plugin.js +56 -256
  9. package/dist/render/light-dom.d.ts +2 -0
  10. package/dist/render/light-dom.d.ts.map +1 -0
  11. package/dist/render/light-dom.js +31 -0
  12. package/dist/render/{utils.d.ts → lit-ssr.d.ts} +1 -1
  13. package/dist/render/lit-ssr.d.ts.map +1 -0
  14. package/dist/render/route-template-pipeline.d.ts +64 -0
  15. package/dist/render/route-template-pipeline.d.ts.map +1 -0
  16. package/dist/render/route-template-pipeline.js +144 -0
  17. package/dist/render/route-template.d.ts +4 -3
  18. package/dist/render/route-template.d.ts.map +1 -1
  19. package/dist/render/route-template.js +41 -87
  20. package/dist/routes/collect.d.ts +5 -1
  21. package/dist/routes/collect.d.ts.map +1 -1
  22. package/dist/routes/collect.js +11 -6
  23. package/dist/routes/load-module.d.ts.map +1 -1
  24. package/dist/routes/load-module.js +5 -2
  25. package/dist/routes/match.d.ts +31 -1
  26. package/dist/routes/match.d.ts.map +1 -1
  27. package/dist/routes/match.js +22 -4
  28. package/dist/routes/render.d.ts.map +1 -1
  29. package/dist/routes/render.js +12 -3
  30. package/dist/server/adapters/hono.d.ts +1 -1
  31. package/dist/server/adapters/hono.d.ts.map +1 -1
  32. package/dist/server/adapters/hono.js +1 -1
  33. package/dist/server/adapters/node.d.ts +1 -1
  34. package/dist/server/adapters/node.d.ts.map +1 -1
  35. package/dist/server/adapters/node.js +2 -2
  36. package/dist/server/request-pipeline.d.ts +109 -0
  37. package/dist/server/request-pipeline.d.ts.map +1 -0
  38. package/dist/server/request-pipeline.js +198 -0
  39. package/dist/server/request.d.ts +3 -16
  40. package/dist/server/request.d.ts.map +1 -1
  41. package/dist/server/request.js +78 -173
  42. package/dist/server/{utils.d.ts → utilities.d.ts} +1 -1
  43. package/dist/server/utilities.d.ts.map +1 -0
  44. package/dist/test/init.d.ts +2 -0
  45. package/dist/test/init.d.ts.map +1 -0
  46. package/dist/test/init.js +7 -0
  47. package/dist/user-config.d.ts +48 -0
  48. package/dist/user-config.d.ts.map +1 -1
  49. package/dist/vite/build-routes.d.ts +1 -2
  50. package/dist/vite/build-routes.d.ts.map +1 -1
  51. package/dist/vite/build-routes.js +0 -98
  52. package/dist/vite/plugin-build-environment.d.ts +21 -0
  53. package/dist/vite/plugin-build-environment.d.ts.map +1 -0
  54. package/dist/vite/plugin-build-environment.js +83 -0
  55. package/dist/vite/plugin-ce-tracker.d.ts +19 -0
  56. package/dist/vite/plugin-ce-tracker.d.ts.map +1 -0
  57. package/dist/vite/plugin-ce-tracker.js +87 -0
  58. package/dist/vite/plugin-client-build.d.ts +20 -0
  59. package/dist/vite/plugin-client-build.d.ts.map +1 -0
  60. package/dist/vite/plugin-client-build.js +55 -0
  61. package/dist/vite/plugin-html-routes-build.d.ts +22 -0
  62. package/dist/vite/plugin-html-routes-build.d.ts.map +1 -0
  63. package/dist/vite/plugin-html-routes-build.js +140 -0
  64. package/dist/vite/plugin-serve.d.ts +18 -0
  65. package/dist/vite/plugin-serve.d.ts.map +1 -0
  66. package/dist/vite/plugin-serve.js +61 -0
  67. package/dist/vite/plugin-server-build.d.ts +43 -0
  68. package/dist/vite/plugin-server-build.d.ts.map +1 -0
  69. package/dist/vite/plugin-server-build.js +108 -0
  70. package/dist/vite/plugin-shared-state.d.ts +33 -0
  71. package/dist/vite/plugin-shared-state.d.ts.map +1 -0
  72. package/dist/vite/plugin-shared-state.js +23 -0
  73. package/dist/vite/virtual-routes.d.ts +8 -5
  74. package/dist/vite/virtual-routes.d.ts.map +1 -1
  75. package/dist/vite/virtual-routes.js +32 -31
  76. package/package.json +11 -11
  77. package/dist/render/utils.d.ts.map +0 -1
  78. package/dist/server/utils.d.ts.map +0 -1
  79. /package/dist/render/{utils.js → lit-ssr.js} +0 -0
  80. /package/dist/server/{utils.js → utilities.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"development.d.ts","sourceRoot":"","sources":["../../src/dev/development.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAEN,KAAK,cAAc,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,wBAAsB,wBAAwB,CAAC,EAC9C,MAAM,EACN,IAAI,EACJ,aAAa,GACb,EAAE;IACF,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,aAAa,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;CAC7B,GAAG,OAAO,CAAC;IACX,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,cAAc,CAAC;CACvB,CAAC,CAgDD"}
1
+ {"version":3,"file":"development.d.ts","sourceRoot":"","sources":["../../src/dev/development.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAEN,KAAK,cAAc,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,wBAAsB,wBAAwB,CAAC,EAC9C,MAAM,EACN,IAAI,EACJ,aAAa,GACb,EAAE;IACF,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,aAAa,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;CAC7B,GAAG,OAAO,CAAC;IACX,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,cAAc,CAAC;CACvB,CAAC,CAqDD"}
@@ -10,7 +10,7 @@ export async function createDevelopmentHandler({ routes, vite, gracileConfig, })
10
10
  logger.info('');
11
11
  logger.info(c.dim('Creating the request handler…'), { timestamp: true });
12
12
  const collectAndCodegen = async () => {
13
- await collectRoutes(routes, root, gracileConfig.routes?.exclude);
13
+ await collectRoutes(routes, root, gracileConfig.routes?.exclude, gracileConfig.trailingSlash);
14
14
  if (gracileConfig.experimental?.generateRoutesTypings)
15
15
  await generateRoutesTypings(root, routes).catch((error) => logger.error(String(error)));
16
16
  };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Server-side Custom Elements registry tracker for dev HMR.
3
+ *
4
+ * Wraps the Lit SSR DOM shim's `customElements` so orphaned CEs
5
+ * can be blocked when their import is removed during development.
6
+ *
7
+ * @internal — dev-only, never runs in production builds.
8
+ */
9
+ export declare function installCeTracker(): void;
10
+ /**
11
+ * Block all CEs registered by a given module.
12
+ * They will be unblocked if the module is re-evaluated and calls define() again.
13
+ */
14
+ export declare function blockCesForModule(moduleId: string): void;
15
+ /** Check whether a module has registered any CEs. */
16
+ export declare function hasCeRegistrations(moduleId: string): boolean;
17
+ /**
18
+ * Reset tracking state.
19
+ * @param full - Also reset installation state (for test suite teardown
20
+ * so a subsequent `installCeTracker` call takes effect).
21
+ */
22
+ export declare function resetCeTracker(full?: boolean): void;
23
+ /** Read-only view of currently blocked tags. For test assertions. */
24
+ export declare function getBlockedTags(): ReadonlySet<string>;
25
+ /** Read-only view of module → tag-names mappings. For test assertions. */
26
+ export declare function getModuleToTags(): ReadonlyMap<string, ReadonlySet<string>>;
27
+ //# sourceMappingURL=ssr-ce-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssr-ce-tracker.d.ts","sourceRoot":"","sources":["../../src/dev/ssr-ce-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAwDH,wBAAgB,gBAAgB,SA+B/B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,QAMjD;AAED,qDAAqD;AACrD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,UAAQ,QAK1C;AAED,qEAAqE;AACrE,wBAAgB,cAAc,IAAI,WAAW,CAAC,MAAM,CAAC,CAEpD;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,IAAI,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAE1E"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Server-side Custom Elements registry tracker for dev HMR.
3
+ *
4
+ * Wraps the Lit SSR DOM shim's `customElements` so orphaned CEs
5
+ * can be blocked when their import is removed during development.
6
+ *
7
+ * @internal — dev-only, never runs in production builds.
8
+ */
9
+ // ── Tracking state ──────────────────────────────────────────────────
10
+ /** module ID → tag names that module registered */
11
+ const moduleToTags = new Map();
12
+ /** Tags blocked from registry lookup (orphaned modules) */
13
+ const blocked = new Set();
14
+ /** Which module is currently being evaluated (set by transform-injected code) */
15
+ let currentModuleId = null;
16
+ let installed = false;
17
+ // ── Registry wrapper ────────────────────────────────────────────────
18
+ function wrapRegistry(registry) {
19
+ const origDefine = registry.define.bind(registry);
20
+ const origGet = registry.get.bind(registry);
21
+ registry.define = function (name, ctor, options) {
22
+ // If re-registered after being blocked, unblock.
23
+ blocked.delete(name);
24
+ if (currentModuleId) {
25
+ let tags = moduleToTags.get(currentModuleId);
26
+ if (!tags) {
27
+ tags = new Set();
28
+ moduleToTags.set(currentModuleId, tags);
29
+ }
30
+ tags.add(name);
31
+ }
32
+ try {
33
+ origDefine(name, ctor, options);
34
+ }
35
+ catch {
36
+ // Already defined — expected during HMR re-evaluation.
37
+ }
38
+ };
39
+ registry.get = function (name) {
40
+ if (blocked.has(name))
41
+ return;
42
+ return origGet(name);
43
+ };
44
+ }
45
+ // ── Public API ──────────────────────────────────────────────────────
46
+ export function installCeTracker() {
47
+ if (installed)
48
+ return;
49
+ installed = true;
50
+ if (globalThis.customElements) {
51
+ wrapRegistry(globalThis.customElements);
52
+ }
53
+ else {
54
+ // Shim not yet installed — intercept the assignment so we can
55
+ // wrap it the moment Lit SSR's DOM shim sets it up.
56
+ let _ce;
57
+ Object.defineProperty(globalThis, 'customElements', {
58
+ get: () => _ce,
59
+ set(value) {
60
+ _ce = value;
61
+ wrapRegistry(value);
62
+ },
63
+ configurable: true,
64
+ enumerable: true,
65
+ });
66
+ }
67
+ // Expose for transform-injected code.
68
+ // Runs in the same process via Vite's ssrLoadModule.
69
+ globalThis['__gracile_ce_tracker'] = {
70
+ setModule(id) {
71
+ currentModuleId = id;
72
+ },
73
+ clearModule() {
74
+ currentModuleId = null;
75
+ },
76
+ };
77
+ }
78
+ /**
79
+ * Block all CEs registered by a given module.
80
+ * They will be unblocked if the module is re-evaluated and calls define() again.
81
+ */
82
+ export function blockCesForModule(moduleId) {
83
+ const tags = moduleToTags.get(moduleId);
84
+ if (!tags)
85
+ return;
86
+ for (const tag of tags) {
87
+ blocked.add(tag);
88
+ }
89
+ }
90
+ /** Check whether a module has registered any CEs. */
91
+ export function hasCeRegistrations(moduleId) {
92
+ return moduleToTags.has(moduleId);
93
+ }
94
+ /**
95
+ * Reset tracking state.
96
+ * @param full - Also reset installation state (for test suite teardown
97
+ * so a subsequent `installCeTracker` call takes effect).
98
+ */
99
+ export function resetCeTracker(full = false) {
100
+ moduleToTags.clear();
101
+ blocked.clear();
102
+ currentModuleId = null;
103
+ if (full)
104
+ installed = false;
105
+ }
106
+ /** Read-only view of currently blocked tags. For test assertions. */
107
+ export function getBlockedTags() {
108
+ return blocked;
109
+ }
110
+ /** Read-only view of module → tag-names mappings. For test assertions. */
111
+ export function getModuleToTags() {
112
+ return moduleToTags;
113
+ }
@@ -3,7 +3,7 @@ import { getLogger } from '@gracile/internal-utils/logger/helpers';
3
3
  import { formatErrorMessage } from '@gracile-labs/better-errors/dev/logger';
4
4
  import { collectErrorMetadata } from '@gracile-labs/better-errors/dev/utils';
5
5
  import { getViteErrorPayload } from '@gracile-labs/better-errors/dev/vite';
6
- import { renderLitTemplate } from '../render/utils.js';
6
+ import { renderLitTemplate } from '../render/lit-ssr.js';
7
7
  import { GRACILE_JS_ERRORS_DOCS_BASE, GracileErrorData } from './errors.js';
8
8
  import { builtInErrorPage } from './pages.js';
9
9
  const logger = getLogger();
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAQtD;;;;;;;;;;;;;;;;GAgBG;AAIH,eAAO,MAAM,OAAO,YAAa,aAAa,KAAG,GAAG,EAqUnD,CAAC;AAEF,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAsBtD;;;;;;;;;;;;;;;;GAgBG;AAIH,eAAO,MAAM,OAAO,GAAI,SAAS,aAAa,KAAG,GAAG,EA2EnD,CAAC;AAEF,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/plugin.js CHANGED
@@ -1,17 +1,19 @@
1
- import { join } from 'node:path';
2
- import { rename, rm } from 'node:fs/promises';
3
1
  import { createLogger } from '@gracile/internal-utils/logger/helpers';
4
- import { getVersion } from '@gracile/internal-utils/version';
5
- // import { betterErrors } from '@gracile-labs/better-errors/plugin';
6
- import c from 'picocolors';
7
- import { build, createServer } from 'vite';
8
- import {} from './routes/render.js';
9
- import { createDevelopmentHandler } from './dev/development.js';
10
- import { nodeAdapter } from './server/adapters/node.js';
11
- import { buildRoutes } from './vite/build-routes.js';
2
+ import { getPluginContext, } from '@gracile/internal-utils/plugin-context';
12
3
  import { htmlRoutesLoader } from './vite/html-routes.js';
13
- import { virtualRoutes, virtualRoutesClient } from './vite/virtual-routes.js';
14
4
  import { hmrSsrReload } from './vite/hmr.js';
5
+ import { virtualRoutesClient, virtualRoutes } from './vite/virtual-routes.js';
6
+ import { createPluginSharedState } from './vite/plugin-shared-state.js';
7
+ import { gracileServePlugin } from './vite/plugin-serve.js';
8
+ import { gracileClientBuildPlugin } from './vite/plugin-client-build.js';
9
+ import { gracileBuildEnvironmentPlugin } from './vite/plugin-build-environment.js';
10
+ import { gracileCollectClientAssetsPlugin, gracileEntrypointPlugin, gracileMoveServerAssetsPlugin, } from './vite/plugin-server-build.js';
11
+ import { gracileCETrackerPlugin } from './vite/plugin-ce-tracker.js';
12
+ import { gracileHtmlRoutesBuildPlugins } from './vite/plugin-html-routes-build.js';
13
+ // When plugin-client-build creates a temporary dev server via createServer(),
14
+ // the user's vite.config is re-evaluated, calling gracile() again.
15
+ // This guard prevents that re-entrant call from initializing the full plugin set.
16
+ // Reset in configureServer so dev-mode config hot-reloads still work.
15
17
  let isClientBuilt = false;
16
18
  /**
17
19
  * The main Vite plugin for loading the Gracile framework.
@@ -35,262 +37,60 @@ let isClientBuilt = false;
35
37
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
38
  export const gracile = (config) => {
37
39
  const logger = createLogger();
38
- const outputMode = config?.output || 'static';
39
- const clientAssets = {};
40
- const routes = new Map();
41
- let renderedRoutes = null;
42
- let root = null;
43
- const gracileConfig = config || {};
44
- // HACK: Prevent duplicate client build for the SSR build step in server mode.
45
- // TODO: Move to the new, clean, environments builders API.
40
+ const state = createPluginSharedState(config);
46
41
  if (isClientBuilt)
47
42
  return [];
48
43
  isClientBuilt = true;
49
44
  const virtualRoutesForClient = virtualRoutesClient({
50
- mode: outputMode,
51
- routes,
52
- // NOTE: This will be a dedicated setting when it will not be experimental
53
- // anymore.
54
- gracileConfig,
55
- // enabled: gracileConfig?.pages?.premises?.expose || false,
45
+ mode: state.outputMode,
46
+ routes: state.routes,
47
+ gracileConfig: state.gracileConfig,
56
48
  });
49
+ let sharedPluginContext;
57
50
  return [
58
- // betterErrors({
59
- // overlayImportPath: '@gracile/gracile/_internals/vite-custom-overlay',
60
- // }),
61
- // {
62
- // name: 'gracile-routes-codegen',
63
- // // watchChange(change) {
64
- // // console.log({ change });
65
- // // },
66
- // resolveId(id) {
67
- // const virtualModuleId = 'gracile:route';
68
- // const resolvedVirtualModuleId = `\0${virtualModuleId}`;
69
- // if (id === virtualModuleId) {
70
- // return resolvedVirtualModuleId;
71
- // }
72
- // return null;
73
- // },
74
- // load(id) {
75
- // const virtualModuleId = 'gracile:route';
76
- // const resolvedVirtualModuleId = `\0${virtualModuleId}`;
77
- // if (id === resolvedVirtualModuleId) {
78
- // return `
79
- // export function route(input){
80
- // return input;
81
- // }`;
82
- // }
83
- // return null;
84
- // },
85
- // },
86
- hmrSsrReload(),
51
+ // MARK: 1. Plugin context setup
87
52
  {
88
- name: 'vite-plugin-gracile-serve-middleware',
89
- apply: 'serve',
90
- config(_, environment) {
91
- if (environment.isPreview)
92
- return null;
93
- return {
94
- // NOTE: Supresses message: `Could not auto-determine entry point from rollupOptions or html files…`
95
- // FIXME: It's not working when reloading the Vite config.
96
- // Is user config, putting `optimizeDeps: { include: [] }` solve this.
97
- optimizeDeps: { include: [] },
98
- // NOTE: Useful? It breaks preview (expected)
99
- appType: 'custom',
100
- // resolve: {
101
- // conditions: ['development'],
102
- // },
103
- };
53
+ name: 'vite-plugin-gracile-context',
54
+ config(viteConfig) {
55
+ sharedPluginContext = getPluginContext(viteConfig);
56
+ state.gracileConfig.litSsr ??= { renderInfo: {} };
57
+ state.gracileConfig.litSsr.renderInfo =
58
+ sharedPluginContext.litSsrRenderInfo;
104
59
  },
105
- async configureServer(server) {
106
- // HACK: We know we are in dev here, this will prevent incorrect
107
- // vite.config hot reloading. Will be removed when adopting env. API.
60
+ },
61
+ // MARK: 2. CE registry tracker (dev HMR cleanup)
62
+ gracileCETrackerPlugin(),
63
+ // MARK: 3. HMR SSR reload
64
+ hmrSsrReload(),
65
+ // MARK: 4. Dev serve middleware
66
+ gracileServePlugin({
67
+ state,
68
+ config,
69
+ logger,
70
+ resetClientBuiltFlag: () => {
108
71
  isClientBuilt = false;
109
- // Infos
110
- // // NOTE: Beware import.meta.resolve is only compatible
111
- // // with v20.6.0 (without cli flag)and upward
112
- // // Not working with StackBlitz ATM?
113
- // const mainPjson = import.meta
114
- // .resolve('@gracile/gracile')
115
- // // NOTE: Weirdly, it will assume that it's `dist/**.js`,
116
- // // even after fiddling with pjson exports.
117
- // .replace('/dist/index.js', '/package.json');
118
- // const { version } = JSON.parse(
119
- // await readFile(new URL(mainPjson), 'utf-8'),
120
- // ) as {
121
- // version: number;
122
- // };
123
- const version = getVersion();
124
- logger.info(`${c.cyan(c.italic(c.underline('🧚 Gracile')))}` +
125
- ` ${c.dim(`~`)} ${c.green(`v${version ?? 'X'}`)}`);
126
- // ---
127
- const { handler } = await createDevelopmentHandler({
128
- routes,
129
- vite: server,
130
- gracileConfig,
131
- });
132
- logger.info(c.dim('Vite development server is starting…'), {
133
- timestamp: true,
134
- });
135
- server.watcher.on('ready', () => {
136
- setTimeout(() => {
137
- logger.info('');
138
- logger.info(c.green('Watching for file changes…'), {
139
- timestamp: true,
140
- });
141
- logger.info('');
142
- // NOTE: We want it to show after the Vite intro stuff
143
- }, 100);
144
- });
145
- return () => {
146
- server.middlewares.use((request, response, next) => {
147
- const locals = config?.dev?.locals?.({ nodeRequest: request });
148
- Promise.resolve(nodeAdapter(handler, { logger })(request, response, locals)).catch((error) => next(error));
149
- });
150
- };
151
72
  },
152
- },
73
+ }),
74
+ // MARK: 5. Client virtual routes
153
75
  virtualRoutesForClient,
76
+ // MARK: 6. HTML routes loader
154
77
  htmlRoutesLoader(),
155
- {
156
- name: 'vite-plugin-gracile-build',
157
- apply: 'build',
158
- async config(viteConfig) {
159
- const viteServerForClientHtmlBuild = await createServer({
160
- // configFile: false,
161
- root: viteConfig.root || process.cwd(),
162
- server: { middlewareMode: true },
163
- // NOTE: Stub. KEEP IT!
164
- optimizeDeps: { include: [] },
165
- plugins: [virtualRoutesForClient],
166
- });
167
- const htmlPages = await buildRoutes({
168
- viteServerForBuild: viteServerForClientHtmlBuild,
169
- root: viteConfig.root || process.cwd(),
170
- gracileConfig,
171
- serverMode: outputMode === 'server',
172
- routes,
173
- });
174
- renderedRoutes = htmlPages.renderedRoutes;
175
- await viteServerForClientHtmlBuild.close();
176
- return {
177
- build: {
178
- // ssrManifest: true,
179
- rollupOptions: {
180
- input: htmlPages.inputList,
181
- plugins: [htmlPages.plugin],
182
- },
183
- outDir: join(viteConfig.build?.outDir || 'dist', outputMode === 'server' ? 'client' : ''),
184
- },
185
- };
186
- },
187
- },
188
- {
189
- name: 'vite-plugin-gracile-collect-client-assets-for-server',
190
- writeBundle(_, bundle) {
191
- if (outputMode === 'static')
192
- return;
193
- for (const file of Object.values(bundle))
194
- if (file.type === 'asset' && file.name)
195
- clientAssets[file.name] = file.fileName;
196
- },
197
- },
198
- {
199
- name: 'vite-plugin-gracile-server-build',
200
- apply: 'build',
201
- config(viteConfig) {
202
- root = viteConfig.root || null;
203
- },
204
- async closeBundle() {
205
- if (outputMode === 'static' || !routes || !renderedRoutes)
206
- return;
207
- await build({
208
- root: root || process.cwd(),
209
- ssr: { external: ['@gracile/gracile'] },
210
- build: {
211
- target: 'esnext',
212
- ssr: true,
213
- // ssrManifest: true,
214
- copyPublicDir: false,
215
- outDir: 'dist/server',
216
- ssrEmitAssets: true,
217
- cssMinify: true,
218
- cssCodeSplit: true,
219
- rollupOptions: {
220
- input: 'entrypoint.js',
221
- // external: ['@gracile/gracile'],
222
- // FIXME: ~~MUST import css from client somewhere.~~
223
- // ~~Hack could be using dynamic imports on client, so asset is picked up~~
224
- output: {
225
- entryFileNames: '[name].js',
226
- // assetFileNames: 'assets/[name].[ext]',
227
- // NOTE: Useful for, e.g., link tag with `?url`
228
- assetFileNames: (chunkInfo) => {
229
- if (chunkInfo.name) {
230
- const fileName = clientAssets[chunkInfo.name];
231
- if (fileName)
232
- return fileName;
233
- // NOTE: When not imported at all from client
234
- return `assets/${chunkInfo.name.replace(/\.(.*)$/, '')}-[hash].[ext]`;
235
- }
236
- // throw new Error(`Not a client asset`);
237
- return 'assets/[name]-[hash].[ext]';
238
- },
239
- chunkFileNames: 'chunk/[name].js',
240
- },
241
- },
242
- },
243
- plugins: [
244
- virtualRoutesForClient,
245
- virtualRoutes({ routes, renderedRoutes }),
246
- {
247
- name: 'vite-plugin-gracile-entry',
248
- resolveId(id) {
249
- if (id === 'entrypoint.js') {
250
- return id;
251
- }
252
- return null;
253
- },
254
- load(id) {
255
- if (id === 'entrypoint.js' && routes && renderedRoutes) {
256
- return `
257
- import { routeAssets, routeImports, routes } from 'gracile:routes';
258
- import { createGracileHandler } from '@gracile/gracile/_internals/server-runtime';
259
- import { createLogger } from '@gracile/gracile/_internals/logger';
260
-
261
- createLogger();
262
-
263
- export const handler = createGracileHandler({
264
- root: process.cwd(),
265
- routes,
266
- routeImports,
267
- routeAssets,
268
- serverMode: true,
269
- gracileConfig: ${JSON.stringify(gracileConfig, null, 2)}
270
- });
271
- `;
272
- }
273
- return null;
274
- },
275
- },
276
- {
277
- name: 'gracile-move-server-assets',
278
- async writeBundle(_, bundle) {
279
- const cwd = root || process.cwd();
280
- await Promise.all(Object.entries(bundle).map(async ([file]) => {
281
- if (file.startsWith('assets/') === false)
282
- return;
283
- await rename(join(cwd, `/dist/server/${file}`), join(cwd, `/dist/client/${file}`));
284
- }));
285
- // NOTE: Disabled for now, because it conflict with test's folder comparer
286
- await rm(join(cwd, `/dist/server/assets`), {
287
- recursive: true,
288
- }).catch(() => null);
289
- },
290
- },
291
- ],
292
- });
293
- },
294
- },
78
+ // MARK: 7. Client build (route rendering → populates shared state)
79
+ gracileClientBuildPlugin({
80
+ state,
81
+ virtualRoutesForClient,
82
+ }),
83
+ // MARK: 8. HTML route resolution + asset collection (client build only)
84
+ ...gracileHtmlRoutesBuildPlugins({ state }),
85
+ // MARK: 9. Build environment configuration (consumes shared state)
86
+ gracileBuildEnvironmentPlugin({ state }),
87
+ // MARK: 9. Collect client assets for server
88
+ gracileCollectClientAssetsPlugin({ state }),
89
+ // MARK: 10. Server virtual routes (SSR environment only)
90
+ ...virtualRoutes({ state }),
91
+ // MARK: 11. Server entrypoint (SSR environment only)
92
+ gracileEntrypointPlugin({ state }),
93
+ // MARK: 12. Move server assets (SSR environment only)
94
+ gracileMoveServerAssetsPlugin({ state }),
295
95
  ];
296
96
  };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=light-dom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"light-dom.d.ts","sourceRoot":"","sources":["../../src/render/light-dom.ts"],"names":[],"mappings":"AAsCA,OAAO,EAAE,CAAC"}
@@ -0,0 +1,31 @@
1
+ // import { LitElementRenderer } from '@lit-labs/ssr/lib/lit-element-renderer.js';
2
+ // import type { ThunkedRenderResult } from '@lit-labs/ssr/lib/render-result.js';
3
+ // export class LightDomLitElementRenderer extends LitElementRenderer {
4
+ // static override matchesClass(ctor: typeof HTMLElement) {
5
+ // // return (ctor as any)._$lightDom === true;
6
+ // return true;
7
+ // }
8
+ // // eslint-disable-next-line class-methods-use-this
9
+ // override renderShadow(): ThunkedRenderResult {
10
+ // return;
11
+ // // return []; // ← no <template shadowrootmode> emitted
12
+ // // return [];
13
+ // }
14
+ // override renderLight(renderInfo) {
15
+ // // Emit the render() output as direct light-DOM children
16
+ // // yield* super.renderShadow(renderInfo);
17
+ // // return super.renderLight(renderInfo);
18
+ // const result = this.element.render();
19
+ // console.log({ result });
20
+ // // return renderInfo.render(result);
21
+ // return ['<div>Light DOM content</div>'];
22
+ // // yield* renderInfo.render(result);
23
+ // }
24
+ // // override *renderLight(renderInfo) {
25
+ // // const result = this.element.render();
26
+ // // yield* renderInfo.render(result);
27
+ // // }
28
+ // }
29
+ // // NOTE: On server, Lit SSR doesn't seems to care at all about CE ctors.
30
+ // // customElements.define('app-shell', new Object() as typeof HTMLElement);
31
+ export {};
@@ -23,4 +23,4 @@ import type { TemplateResult } from 'lit';
23
23
  * ```
24
24
  */
25
25
  export declare function renderLitTemplate(template: ServerRenderedTemplate | TemplateResult): Promise<string>;
26
- //# sourceMappingURL=utils.d.ts.map
26
+ //# sourceMappingURL=lit-ssr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lit-ssr.d.ts","sourceRoot":"","sources":["../../src/render/lit-ssr.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,iBAAiB,CACtC,QAAQ,EAAE,sBAAsB,GAAG,cAAc,GAC/C,OAAO,CAAC,MAAM,CAAC,CAEjB"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Pure, testable pipeline steps extracted from the route template renderer.
3
+ *
4
+ * Each function here is a focused stage of the document post-processing
5
+ * lifecycle. They are composed by `renderRouteTemplate` in
6
+ * `./route-template.ts`.
7
+ *
8
+ * @internal
9
+ */
10
+ import { Readable } from 'node:stream';
11
+ import type { RenderInfo } from '@lit-labs/ssr';
12
+ export declare const REGEX_TAG_SCRIPT: RegExp;
13
+ export declare const REGEX_TAG_LINK: RegExp;
14
+ /**
15
+ * Concatenate multiple `Readable` streams into a single async iterable.
16
+ */
17
+ export declare function concatStreams(...readables: Readable[]): AsyncGenerator<any, void, unknown>;
18
+ /**
19
+ * Merge user-provided `RenderInfo` with the default `LitElementRenderer`.
20
+ * Always appends `LitElementRenderer` to whatever the user supplied.
21
+ */
22
+ export declare function mergeRenderInfo(renderInfo: Partial<RenderInfo> | undefined): Partial<RenderInfo>;
23
+ /**
24
+ * Inject sibling page assets into the rendered document HTML.
25
+ *
26
+ * Inserts the `PAGE_ASSETS_MARKER` before `</head>`, then replaces it
27
+ * with concrete `<script>` / `<link>` tags for each asset path.
28
+ *
29
+ * @param documentHtml The rendered document string.
30
+ * @param pageAssets Array of asset file paths (e.g. `['src/pages/about.css']`).
31
+ * @returns The document with asset tags injected (or unchanged if no assets).
32
+ */
33
+ export declare function injectSiblingAssets(documentHtml: string, pageAssets: string[]): string;
34
+ /**
35
+ * Prepend `<!doctype html>` if the document doesn't already start with one.
36
+ *
37
+ * @param documentHtml The rendered document string.
38
+ * @returns The document guaranteed to start with a doctype declaration.
39
+ */
40
+ export declare function ensureDoctype(documentHtml: string): string;
41
+ /**
42
+ * The HMR error overlay script injected in dev mode.
43
+ * Returns the raw HTML string for the `<script>` tag.
44
+ */
45
+ export declare function developmentOverlaySnippet(): string;
46
+ /**
47
+ * Inject the dev overlay script right after `<head>`.
48
+ * Only applied when `mode === 'dev'`.
49
+ *
50
+ * @param documentHtml The rendered document string.
51
+ * @returns The document with the overlay injected.
52
+ */
53
+ export declare function injectDevelopmentOverlay(documentHtml: string): string;
54
+ /**
55
+ * For server-output builds: strip dev-time `<script type="module">` and
56
+ * `<link rel="stylesheet">` tags, then inject the production asset string
57
+ * before `</head>`.
58
+ *
59
+ * @param documentHtml The rendered document string.
60
+ * @param routeAssetsHtml The production asset tags to inject.
61
+ * @returns The document with dev assets stripped and production assets injected.
62
+ */
63
+ export declare function injectServerAssets(documentHtml: string, routeAssetsHtml: string): string;
64
+ //# sourceMappingURL=route-template-pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-template-pipeline.d.ts","sourceRoot":"","sources":["../../src/render/route-template-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAMhD,eAAO,MAAM,gBAAgB,QACkC,CAAC;AAEhE,eAAO,MAAM,cAAc,QAA2B,CAAC;AAIvD;;GAEG;AACH,wBAAuB,aAAa,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,sCAM5D;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAC9B,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,SAAS,GACzC,OAAO,CAAC,UAAU,CAAC,CAQrB;AASD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAClC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAAE,GAClB,MAAM,CA2BR;AAID;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAO1D;AAID;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAalD;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAKrE;AAID;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CACjC,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,GACrB,MAAM,CAWR"}