@dirwell/theme-authoring 0.0.0-stage → 0.0.1-alpha.1
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/LICENSE +21 -0
- package/README.md +66 -2
- package/dist/compiler-C0rEfJCH.mjs +76 -0
- package/dist/compiler-C0rEfJCH.mjs.map +1 -0
- package/dist/compiler-DwxVCNyK.d.mts +6 -0
- package/dist/dev.d.mts +19 -0
- package/dist/dev.mjs +105 -0
- package/dist/dev.mjs.map +1 -0
- package/dist/index.d.mts +18 -0
- package/dist/index.mjs +181 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +47 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dirwell contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,67 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @dirwell/theme-authoring
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Compile trusted Svelte/Vue wrapper components
|
|
4
|
+
into matching SSR and browser implementations. Plain and core do not depend on
|
|
5
|
+
this package or its compilers.
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
import { buildFrameworkTheme } from "@dirwell/theme-authoring";
|
|
9
|
+
const result = await buildFrameworkTheme({
|
|
10
|
+
framework: "svelte", // 'vue' for Crosswave
|
|
11
|
+
component: "./Ledger.svelte",
|
|
12
|
+
output: "./generated-theme",
|
|
13
|
+
});
|
|
14
|
+
const { createTheme } = await import(result.themeUrl);
|
|
15
|
+
// Pass createTheme({title: 'Downloads'}) to generateExplorer or createExplorerHandler.
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Import Ledger from `@dirwell/theme-ledger/source`, or Crosswave from
|
|
19
|
+
`@dirwell/theme-crosswave/source`. Your wrapper accepts the `model` prop; public
|
|
20
|
+
model and row context types are available from each theme's `/model` entry.
|
|
21
|
+
Ledger accepts `header`, `row` and `footer` snippets. Crosswave exposes named slots
|
|
22
|
+
with those names. Header/footer receive `{model}`; row receives
|
|
23
|
+
`{model, entry, selected}`. These contexts track the current directory after
|
|
24
|
+
navigation or live updates. Row content lives inside the official link: do not
|
|
25
|
+
nest links, buttons, or other interactive controls inside it. Official list
|
|
26
|
+
identity, keyboard selection, link actions, virtualization, pagination, dialogs,
|
|
27
|
+
appearance controls and gamepad lifecycle remain owned by the theme.
|
|
28
|
+
|
|
29
|
+
See `examples/authoring` in the repository for complete wrappers. These are source
|
|
30
|
+
customizations, not serializable CLI options. The output's `theme.mjs#createTheme`
|
|
31
|
+
can be selected with the CLI's existing explicit module-factory argument.
|
|
32
|
+
|
|
33
|
+
Both targets use pinned framework runtimes and official Vite plugins. Nested
|
|
34
|
+
components, TypeScript script blocks, component CSS and static imported assets
|
|
35
|
+
are compiled together. Dedicated output directories have ownership markers and
|
|
36
|
+
are replaced only after both targets succeed. Failed builds retain the previous
|
|
37
|
+
output. Do not run the compiler while serving files from its output; rebuild,
|
|
38
|
+
create a fresh theme instance, then restart/swap the consumer. Node module caches
|
|
39
|
+
require a fresh import URL after replacing an already-imported `theme.mjs`.
|
|
40
|
+
|
|
41
|
+
## Local development
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
import { startAuthoringServer } from "@dirwell/theme-authoring/dev";
|
|
45
|
+
const server = await startAuthoringServer({
|
|
46
|
+
framework: "vue",
|
|
47
|
+
component: "./Crosswave.vue",
|
|
48
|
+
explorer: { root: "./files", live: { intervalMs: 500 } },
|
|
49
|
+
});
|
|
50
|
+
console.log(server.url);
|
|
51
|
+
// Await server.close() when finished; it owns Vite, sockets and filesystem watchers.
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The server binds to loopback only. Use Portless to provide a named development
|
|
55
|
+
URL. This is a trusted local source-development server, not a production
|
|
56
|
+
transport or authorization boundary: Vite serves project source modules. Do not
|
|
57
|
+
proxy it publicly. The production server remains `@dirwell/server`.
|
|
58
|
+
|
|
59
|
+
Source edits use official framework HMR; file changes use the explorer's separate
|
|
60
|
+
SSE revision protocol. CSS-only edits preserve the current component state. Wrapper template/snippet
|
|
61
|
+
edits and script changes can remount child components and reset search/selection;
|
|
62
|
+
HMR retains the current directory model, but does not guarantee filter/selection
|
|
63
|
+
persistence for those edits. Source writes are coalesced until stable for 100 ms
|
|
64
|
+
before compilation, so partial editor writes can recover cleanly. Compiler errors
|
|
65
|
+
produce Vite's overlay and recover after a valid edit. Development CSS loads
|
|
66
|
+
through Vite's client, so production output is the no-JavaScript/CSS acceptance
|
|
67
|
+
path. No Farm watcher is involved.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
|
4
|
+
import vue from "@vitejs/plugin-vue";
|
|
5
|
+
//#region src/compiler.ts
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const vueRequire = createRequire(require.resolve("vue/package.json"));
|
|
8
|
+
const domRequire = createRequire(vueRequire.resolve("@vue/runtime-dom/package.json"));
|
|
9
|
+
const coreRequire = createRequire(domRequire.resolve("@vue/runtime-core/package.json"));
|
|
10
|
+
const vueAliases = [
|
|
11
|
+
["vue", require.resolve("vue/dist/vue.runtime.esm-bundler.js")],
|
|
12
|
+
["vue/server-renderer", vueRequire.resolve("@vue/server-renderer/dist/server-renderer.esm-bundler.js")],
|
|
13
|
+
["@vue/server-renderer", vueRequire.resolve("@vue/server-renderer/dist/server-renderer.esm-bundler.js")],
|
|
14
|
+
["@vue/runtime-dom", vueRequire.resolve("@vue/runtime-dom/dist/runtime-dom.esm-bundler.js")],
|
|
15
|
+
["@vue/runtime-core", domRequire.resolve("@vue/runtime-core/dist/runtime-core.esm-bundler.js")],
|
|
16
|
+
["@vue/reactivity", coreRequire.resolve("@vue/reactivity/dist/reactivity.esm-bundler.js")],
|
|
17
|
+
["@vue/shared", vueRequire.resolve("@vue/shared/dist/shared.esm-bundler.js")]
|
|
18
|
+
].map(([name, replacement]) => ({
|
|
19
|
+
find: new RegExp(`^${name}$`),
|
|
20
|
+
replacement
|
|
21
|
+
}));
|
|
22
|
+
/** Both targets resolve the exact runtime shipped with this compiler. */
|
|
23
|
+
function frameworkConfig(framework, root) {
|
|
24
|
+
return {
|
|
25
|
+
configFile: false,
|
|
26
|
+
root,
|
|
27
|
+
publicDir: false,
|
|
28
|
+
logLevel: "warn",
|
|
29
|
+
plugins: [
|
|
30
|
+
{
|
|
31
|
+
name: "dirwell-pinned-runtime",
|
|
32
|
+
enforce: "pre",
|
|
33
|
+
resolveId(source, _importer, options) {
|
|
34
|
+
if (source === "svelte") return options.ssr ? require.resolve("svelte") : path.join(path.dirname(require.resolve("svelte/package.json")), "src/index-client.js");
|
|
35
|
+
if (source.startsWith("svelte/") || source === "@dirwell/theme-ledger/source" || source === "@dirwell/theme-crosswave/source" || source === "vue/server-renderer") return require.resolve(source);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
...framework === "svelte" ? [svelte({
|
|
39
|
+
configFile: false,
|
|
40
|
+
prebundleSvelteLibraries: false,
|
|
41
|
+
disableDependencyReinclusion: true
|
|
42
|
+
})] : [vue()],
|
|
43
|
+
{
|
|
44
|
+
name: "dirwell-runtime-optimization",
|
|
45
|
+
enforce: "post",
|
|
46
|
+
configResolved(config) {
|
|
47
|
+
if (config.optimizeDeps.include) config.optimizeDeps.include = config.optimizeDeps.include.filter((name) => !name.startsWith("svelte"));
|
|
48
|
+
for (const environment of Object.values(config.environments)) if (environment.optimizeDeps.include) environment.optimizeDeps.include = environment.optimizeDeps.include.filter((name) => !name.startsWith("svelte"));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
resolve: {
|
|
53
|
+
dedupe: [
|
|
54
|
+
"svelte",
|
|
55
|
+
"vue",
|
|
56
|
+
"@vue/runtime-core",
|
|
57
|
+
"@vue/runtime-dom",
|
|
58
|
+
"@vue/reactivity"
|
|
59
|
+
],
|
|
60
|
+
alias: vueAliases
|
|
61
|
+
},
|
|
62
|
+
ssr: { noExternal: true }
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function entrySource(framework, component, target) {
|
|
66
|
+
const app = `import App from ${JSON.stringify(component)};`;
|
|
67
|
+
if (target === "server") return app + (framework === "svelte" ? "import {render} from 'svelte/server';export const renderBody=model=>render(App,{props:{model}}).body;" : "import {createSSRApp} from 'vue';import {renderToString} from 'vue/server-renderer';export const renderBody=model=>renderToString(createSSRApp(App,{model}));");
|
|
68
|
+
return app + "const model=JSON.parse(document.querySelector('#dirwell-page-data').textContent);const target=document.querySelector('[data-dirwell-theme]');" + (framework === "svelte" ? "import {hydrate,unmount} from 'svelte';const app=hydrate(App,{target,props:{model}});globalThis.__dirwellUnmount=()=>unmount(app);" : "import {createSSRApp} from 'vue';const app=createSSRApp(App,{model});app.mount(target);globalThis.__dirwellUnmount=()=>app.unmount();");
|
|
69
|
+
}
|
|
70
|
+
function validateFramework(framework) {
|
|
71
|
+
if (framework !== "svelte" && framework !== "vue") throw new TypeError("Unsupported theme framework");
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { frameworkConfig as n, validateFramework as r, entrySource as t };
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=compiler-C0rEfJCH.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiler-C0rEfJCH.mjs","names":[],"sources":["../src/compiler.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport path from \"node:path\";\nimport { svelte } from \"@sveltejs/vite-plugin-svelte\";\nimport vue from \"@vitejs/plugin-vue\";\nimport type { InlineConfig } from \"vite\";\nexport type Framework = \"svelte\" | \"vue\";\nconst require = createRequire(import.meta.url);\nconst vueRequire = createRequire(require.resolve(\"vue/package.json\"));\nconst domRequire = createRequire(vueRequire.resolve(\"@vue/runtime-dom/package.json\"));\nconst coreRequire = createRequire(domRequire.resolve(\"@vue/runtime-core/package.json\"));\nconst vueAliases = [\n [\"vue\", require.resolve(\"vue/dist/vue.runtime.esm-bundler.js\")],\n [\n \"vue/server-renderer\",\n vueRequire.resolve(\"@vue/server-renderer/dist/server-renderer.esm-bundler.js\"),\n ],\n [\n \"@vue/server-renderer\",\n vueRequire.resolve(\"@vue/server-renderer/dist/server-renderer.esm-bundler.js\"),\n ],\n [\"@vue/runtime-dom\", vueRequire.resolve(\"@vue/runtime-dom/dist/runtime-dom.esm-bundler.js\")],\n [\"@vue/runtime-core\", domRequire.resolve(\"@vue/runtime-core/dist/runtime-core.esm-bundler.js\")],\n [\"@vue/reactivity\", coreRequire.resolve(\"@vue/reactivity/dist/reactivity.esm-bundler.js\")],\n [\"@vue/shared\", vueRequire.resolve(\"@vue/shared/dist/shared.esm-bundler.js\")],\n].map(([name, replacement]) => ({ find: new RegExp(`^${name}$`), replacement: replacement! }));\n/** Both targets resolve the exact runtime shipped with this compiler. */\nexport function frameworkConfig(framework: Framework, root: string): InlineConfig {\n return {\n configFile: false,\n root,\n publicDir: false,\n logLevel: \"warn\",\n plugins: [\n {\n name: \"dirwell-pinned-runtime\",\n enforce: \"pre\",\n resolveId(source, _importer, options) {\n if (source === \"svelte\")\n return options.ssr\n ? require.resolve(\"svelte\")\n : path.join(\n path.dirname(require.resolve(\"svelte/package.json\")),\n \"src/index-client.js\",\n );\n if (\n source.startsWith(\"svelte/\") ||\n source === \"@dirwell/theme-ledger/source\" ||\n source === \"@dirwell/theme-crosswave/source\" ||\n source === \"vue/server-renderer\"\n )\n return require.resolve(source);\n return undefined;\n },\n },\n ...(framework === \"svelte\"\n ? [\n svelte({\n configFile: false,\n prebundleSvelteLibraries: false,\n disableDependencyReinclusion: true,\n }),\n ]\n : [vue()]),\n {\n name: \"dirwell-runtime-optimization\",\n enforce: \"post\",\n configResolved(config) {\n // Runtime imports resolve to compiler-owned absolute paths, not project dependencies.\n if (config.optimizeDeps.include)\n config.optimizeDeps.include = config.optimizeDeps.include.filter(\n (name) => !name.startsWith(\"svelte\"),\n );\n for (const environment of Object.values(config.environments)) {\n if (environment.optimizeDeps.include)\n environment.optimizeDeps.include = environment.optimizeDeps.include.filter(\n (name) => !name.startsWith(\"svelte\"),\n );\n }\n },\n },\n ],\n resolve: {\n dedupe: [\"svelte\", \"vue\", \"@vue/runtime-core\", \"@vue/runtime-dom\", \"@vue/reactivity\"],\n alias: vueAliases,\n },\n ssr: { noExternal: true },\n };\n}\nexport function entrySource(framework: Framework, component: string, target: \"server\" | \"client\") {\n const app = `import App from ${JSON.stringify(component)};`;\n if (target === \"server\")\n return (\n app +\n (framework === \"svelte\"\n ? \"import {render} from 'svelte/server';export const renderBody=model=>render(App,{props:{model}}).body;\"\n : \"import {createSSRApp} from 'vue';import {renderToString} from 'vue/server-renderer';export const renderBody=model=>renderToString(createSSRApp(App,{model}));\")\n );\n const data =\n \"const model=JSON.parse(document.querySelector('#dirwell-page-data').textContent);const target=document.querySelector('[data-dirwell-theme]');\";\n return (\n app +\n data +\n (framework === \"svelte\"\n ? \"import {hydrate,unmount} from 'svelte';const app=hydrate(App,{target,props:{model}});globalThis.__dirwellUnmount=()=>unmount(app);\"\n : \"import {createSSRApp} from 'vue';const app=createSSRApp(App,{model});app.mount(target);globalThis.__dirwellUnmount=()=>app.unmount();\")\n );\n}\nexport function validateFramework(framework: Framework) {\n if (framework !== \"svelte\" && framework !== \"vue\")\n throw new TypeError(\"Unsupported theme framework\");\n}\n"],"mappings":";;;;;AAMA,MAAM,UAAU,cAAc,YAAY,GAAG;AAC7C,MAAM,aAAa,cAAc,QAAQ,QAAQ,kBAAkB,CAAC;AACpE,MAAM,aAAa,cAAc,WAAW,QAAQ,+BAA+B,CAAC;AACpF,MAAM,cAAc,cAAc,WAAW,QAAQ,gCAAgC,CAAC;AACtF,MAAM,aAAa;CACjB,CAAC,OAAO,QAAQ,QAAQ,qCAAqC,CAAC;CAC9D,CACE,uBACA,WAAW,QAAQ,0DAA0D,CAC/E;CACA,CACE,wBACA,WAAW,QAAQ,0DAA0D,CAC/E;CACA,CAAC,oBAAoB,WAAW,QAAQ,kDAAkD,CAAC;CAC3F,CAAC,qBAAqB,WAAW,QAAQ,oDAAoD,CAAC;CAC9F,CAAC,mBAAmB,YAAY,QAAQ,gDAAgD,CAAC;CACzF,CAAC,eAAe,WAAW,QAAQ,wCAAwC,CAAC;AAC9E,CAAC,CAAC,KAAK,CAAC,MAAM,kBAAkB;CAAE,MAAM,IAAI,OAAO,IAAI,KAAK,EAAE;CAAgB;AAAa,EAAE;;AAE7F,SAAgB,gBAAgB,WAAsB,MAA4B;CAChF,OAAO;EACL,YAAY;EACZ;EACA,WAAW;EACX,UAAU;EACV,SAAS;GACP;IACE,MAAM;IACN,SAAS;IACT,UAAU,QAAQ,WAAW,SAAS;KACpC,IAAI,WAAW,UACb,OAAO,QAAQ,MACX,QAAQ,QAAQ,QAAQ,IACxB,KAAK,KACH,KAAK,QAAQ,QAAQ,QAAQ,qBAAqB,CAAC,GACnD,qBACF;KACN,IACE,OAAO,WAAW,SAAS,KAC3B,WAAW,kCACX,WAAW,qCACX,WAAW,uBAEX,OAAO,QAAQ,QAAQ,MAAM;IAEjC;GACF;GACA,GAAI,cAAc,WACd,CACE,OAAO;IACL,YAAY;IACZ,0BAA0B;IAC1B,8BAA8B;GAChC,CAAC,CACH,IACA,CAAC,IAAI,CAAC;GACV;IACE,MAAM;IACN,SAAS;IACT,eAAe,QAAQ;KAErB,IAAI,OAAO,aAAa,SACtB,OAAO,aAAa,UAAU,OAAO,aAAa,QAAQ,QACvD,SAAS,CAAC,KAAK,WAAW,QAAQ,CACrC;KACF,KAAK,MAAM,eAAe,OAAO,OAAO,OAAO,YAAY,GACzD,IAAI,YAAY,aAAa,SAC3B,YAAY,aAAa,UAAU,YAAY,aAAa,QAAQ,QACjE,SAAS,CAAC,KAAK,WAAW,QAAQ,CACrC;IAEN;GACF;EACF;EACA,SAAS;GACP,QAAQ;IAAC;IAAU;IAAO;IAAqB;IAAoB;GAAiB;GACpF,OAAO;EACT;EACA,KAAK,EAAE,YAAY,KAAK;CAC1B;AACF;AACA,SAAgB,YAAY,WAAsB,WAAmB,QAA6B;CAChG,MAAM,MAAM,mBAAmB,KAAK,UAAU,SAAS,EAAE;CACzD,IAAI,WAAW,UACb,OACE,OACC,cAAc,WACX,0GACA;CAIR,OACE,MACA,mJACC,cAAc,WACX,uIACA;AAER;AACA,SAAgB,kBAAkB,WAAsB;CACtD,IAAI,cAAc,YAAY,cAAc,OAC1C,MAAM,IAAI,UAAU,6BAA6B;AACrD"}
|
package/dist/dev.d.mts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { t as Framework } from "./compiler-DwxVCNyK.mjs";
|
|
2
|
+
import { LedgerThemeOptions } from "@dirwell/theme-ledger";
|
|
3
|
+
import { CrosswaveThemeOptions } from "@dirwell/theme-crosswave";
|
|
4
|
+
import { ExplorerHandlerOptions } from "@dirwell/server";
|
|
5
|
+
//#region src/dev.d.ts
|
|
6
|
+
export interface AuthoringServerOptions {
|
|
7
|
+
readonly framework: Framework;
|
|
8
|
+
readonly component: string;
|
|
9
|
+
readonly explorer: Omit<ExplorerHandlerOptions, "theme" | "mountPath">;
|
|
10
|
+
readonly themeOptions?: LedgerThemeOptions & CrosswaveThemeOptions;
|
|
11
|
+
readonly port?: number;
|
|
12
|
+
}
|
|
13
|
+
/** Trusted local development only: Vite serves executable source modules as well as explorer data. */
|
|
14
|
+
export declare function startAuthoringServer(options: AuthoringServerOptions): Promise<{
|
|
15
|
+
url: string;
|
|
16
|
+
close: () => Promise<void>;
|
|
17
|
+
}>;
|
|
18
|
+
//#endregion
|
|
19
|
+
//# sourceMappingURL=dev.d.mts.map
|
package/dist/dev.mjs
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { n as frameworkConfig, r as validateFramework, t as entrySource } from "./compiler-C0rEfJCH.mjs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { createServer, searchForWorkspaceRoot } from "vite";
|
|
4
|
+
import { realpath } from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { createNodeRequestListener } from "@dirwell/server/node";
|
|
7
|
+
import { createLedgerTheme } from "@dirwell/theme-ledger";
|
|
8
|
+
import { createCrosswaveTheme } from "@dirwell/theme-crosswave";
|
|
9
|
+
//#region src/dev.ts
|
|
10
|
+
/** Trusted local development only: Vite serves executable source modules as well as explorer data. */
|
|
11
|
+
async function startAuthoringServer(options) {
|
|
12
|
+
validateFramework(options.framework);
|
|
13
|
+
const component = await realpath(path.resolve(options.component));
|
|
14
|
+
if (path.extname(component) !== (options.framework === "svelte" ? ".svelte" : ".vue")) throw new TypeError("Component extension does not match framework");
|
|
15
|
+
const config = frameworkConfig(options.framework, path.dirname(component));
|
|
16
|
+
const require = createRequire(import.meta.url);
|
|
17
|
+
const id = "/@dirwell/authoring-";
|
|
18
|
+
const vite = await createServer({
|
|
19
|
+
...config,
|
|
20
|
+
appType: "custom",
|
|
21
|
+
mode: "development",
|
|
22
|
+
define: {
|
|
23
|
+
"process.env.NODE_ENV": JSON.stringify("development"),
|
|
24
|
+
__VUE_OPTIONS_API__: "true",
|
|
25
|
+
__VUE_PROD_DEVTOOLS__: "false",
|
|
26
|
+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: "false"
|
|
27
|
+
},
|
|
28
|
+
optimizeDeps: {
|
|
29
|
+
noDiscovery: true,
|
|
30
|
+
include: []
|
|
31
|
+
},
|
|
32
|
+
ssr: {
|
|
33
|
+
noExternal: true,
|
|
34
|
+
optimizeDeps: {
|
|
35
|
+
noDiscovery: true,
|
|
36
|
+
include: []
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
server: {
|
|
40
|
+
host: "127.0.0.1",
|
|
41
|
+
port: options.port ?? 0,
|
|
42
|
+
strictPort: true,
|
|
43
|
+
watch: { awaitWriteFinish: {
|
|
44
|
+
stabilityThreshold: 100,
|
|
45
|
+
pollInterval: 20
|
|
46
|
+
} },
|
|
47
|
+
fs: { allow: [searchForWorkspaceRoot(path.dirname(component)), searchForWorkspaceRoot(path.dirname(require.resolve("@dirwell/theme-ledger/source")))] }
|
|
48
|
+
},
|
|
49
|
+
plugins: [...config.plugins ?? [], {
|
|
50
|
+
name: "dirwell-authoring-entry",
|
|
51
|
+
resolveId: (source) => source.startsWith(id) ? `\0${source}` : void 0,
|
|
52
|
+
load(source) {
|
|
53
|
+
if (source === `\0${id}client`) return entrySource(options.framework, component, "client");
|
|
54
|
+
if (source === `\0${id}server`) return entrySource(options.framework, component, "server");
|
|
55
|
+
}
|
|
56
|
+
}]
|
|
57
|
+
});
|
|
58
|
+
try {
|
|
59
|
+
const renderBody = async (model) => {
|
|
60
|
+
const module = await vite.ssrLoadModule(`${id}server`).catch((error) => {
|
|
61
|
+
if (error instanceof Error) {
|
|
62
|
+
vite.ssrFixStacktrace(error);
|
|
63
|
+
vite.config.logger.error(error.stack ?? error.message);
|
|
64
|
+
}
|
|
65
|
+
throw error;
|
|
66
|
+
});
|
|
67
|
+
if (module === null || typeof module !== "object" || !("renderBody" in module) || typeof module.renderBody !== "function") throw new Error("Invalid compiled renderer");
|
|
68
|
+
const body = await module.renderBody(model);
|
|
69
|
+
if (typeof body !== "string") throw new Error("Invalid compiled body");
|
|
70
|
+
return body;
|
|
71
|
+
};
|
|
72
|
+
const renderer = {
|
|
73
|
+
renderBody,
|
|
74
|
+
clientScript: `import '/@vite/client';import '${id}client';`,
|
|
75
|
+
clientType: "module"
|
|
76
|
+
};
|
|
77
|
+
const theme = options.framework === "svelte" ? createLedgerTheme(options.themeOptions, renderer) : createCrosswaveTheme(options.themeOptions, renderer);
|
|
78
|
+
const listener = await createNodeRequestListener({
|
|
79
|
+
files: "media",
|
|
80
|
+
...options.explorer,
|
|
81
|
+
theme
|
|
82
|
+
});
|
|
83
|
+
vite.middlewares.use((request, response, next) => {
|
|
84
|
+
if (request.url?.startsWith("/@") || request.url?.startsWith("/node_modules/")) {
|
|
85
|
+
next();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
listener(request, response);
|
|
89
|
+
});
|
|
90
|
+
await vite.listen();
|
|
91
|
+
const address = vite.httpServer?.address();
|
|
92
|
+
if (!address || typeof address === "string") throw new Error("Authoring server address unavailable");
|
|
93
|
+
return {
|
|
94
|
+
url: `http://127.0.0.1:${address.port}`,
|
|
95
|
+
close: () => vite.close()
|
|
96
|
+
};
|
|
97
|
+
} catch (error) {
|
|
98
|
+
await vite.close();
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { startAuthoringServer };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=dev.mjs.map
|
package/dist/dev.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.mjs","names":[],"sources":["../src/dev.ts"],"sourcesContent":["import { createServer, searchForWorkspaceRoot } from \"vite\";\nimport { realpath } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { createNodeRequestListener } from \"@dirwell/server/node\";\nimport type { ExplorerHandlerOptions } from \"@dirwell/server\";\nimport { createLedgerTheme, type LedgerThemeOptions, type ThemePage } from \"@dirwell/theme-ledger\";\nimport { createCrosswaveTheme, type CrosswaveThemeOptions } from \"@dirwell/theme-crosswave\";\nimport { frameworkConfig, entrySource, validateFramework, type Framework } from \"./compiler.ts\";\nexport interface AuthoringServerOptions {\n readonly framework: Framework;\n readonly component: string;\n readonly explorer: Omit<ExplorerHandlerOptions, \"theme\" | \"mountPath\">;\n readonly themeOptions?: LedgerThemeOptions & CrosswaveThemeOptions;\n readonly port?: number;\n}\n/** Trusted local development only: Vite serves executable source modules as well as explorer data. */\nexport async function startAuthoringServer(options: AuthoringServerOptions) {\n validateFramework(options.framework);\n const component = await realpath(path.resolve(options.component));\n if (path.extname(component) !== (options.framework === \"svelte\" ? \".svelte\" : \".vue\"))\n throw new TypeError(\"Component extension does not match framework\");\n const config = frameworkConfig(options.framework, path.dirname(component));\n const require = createRequire(import.meta.url);\n const id = \"/@dirwell/authoring-\";\n const vite = await createServer({\n ...config,\n appType: \"custom\",\n mode: \"development\",\n define: {\n \"process.env.NODE_ENV\": JSON.stringify(\"development\"),\n __VUE_OPTIONS_API__: \"true\",\n __VUE_PROD_DEVTOOLS__: \"false\",\n __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: \"false\",\n },\n optimizeDeps: { noDiscovery: true, include: [] },\n ssr: { noExternal: true, optimizeDeps: { noDiscovery: true, include: [] } },\n server: {\n host: \"127.0.0.1\",\n port: options.port ?? 0,\n strictPort: true,\n watch: { awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 20 } },\n fs: {\n allow: [\n searchForWorkspaceRoot(path.dirname(component)),\n searchForWorkspaceRoot(path.dirname(require.resolve(\"@dirwell/theme-ledger/source\"))),\n ],\n },\n },\n plugins: [\n ...(config.plugins ?? []),\n {\n name: \"dirwell-authoring-entry\",\n resolveId: (source) => (source.startsWith(id) ? `\\0${source}` : undefined),\n load(source) {\n if (source === `\\0${id}client`)\n return entrySource(options.framework, component, \"client\");\n if (source === `\\0${id}server`)\n return entrySource(options.framework, component, \"server\");\n return undefined;\n },\n },\n ],\n });\n try {\n const renderBody = async (model: ThemePage) => {\n const module: unknown = await vite.ssrLoadModule(`${id}server`).catch((error: unknown) => {\n if (error instanceof Error) {\n vite.ssrFixStacktrace(error);\n vite.config.logger.error(error.stack ?? error.message);\n }\n throw error;\n });\n if (\n module === null ||\n typeof module !== \"object\" ||\n !(\"renderBody\" in module) ||\n typeof module.renderBody !== \"function\"\n )\n throw new Error(\"Invalid compiled renderer\");\n const body: unknown = await module.renderBody(model);\n if (typeof body !== \"string\") throw new Error(\"Invalid compiled body\");\n return body;\n };\n const renderer = {\n renderBody,\n clientScript: `import '/@vite/client';import '${id}client';`,\n clientType: \"module\" as const,\n };\n const theme =\n options.framework === \"svelte\"\n ? createLedgerTheme(options.themeOptions, renderer)\n : createCrosswaveTheme(options.themeOptions, renderer);\n const listener = await createNodeRequestListener({\n files: \"media\",\n ...options.explorer,\n theme,\n });\n vite.middlewares.use((request, response, next) => {\n if (request.url?.startsWith(\"/@\") || request.url?.startsWith(\"/node_modules/\")) {\n next();\n return;\n }\n void listener(request, response);\n });\n await vite.listen();\n const address = vite.httpServer?.address();\n if (!address || typeof address === \"string\")\n throw new Error(\"Authoring server address unavailable\");\n return { url: `http://127.0.0.1:${address.port}`, close: () => vite.close() };\n } catch (error) {\n await vite.close();\n throw error;\n }\n}\n"],"mappings":"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"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { t as Framework } from "./compiler-DwxVCNyK.mjs";
|
|
2
|
+
//#region src/index.d.ts
|
|
3
|
+
export interface BuildFrameworkThemeOptions {
|
|
4
|
+
readonly framework: Framework;
|
|
5
|
+
/** A wrapper component accepting the public model prop. Source code is trusted executable input. */
|
|
6
|
+
readonly component: string;
|
|
7
|
+
/** A dedicated compiler-owned directory. Existing unowned directories are rejected. */
|
|
8
|
+
readonly output: string;
|
|
9
|
+
}
|
|
10
|
+
export interface BuiltFrameworkTheme {
|
|
11
|
+
readonly themeUrl: string;
|
|
12
|
+
readonly output: string;
|
|
13
|
+
}
|
|
14
|
+
/** Publishes a paired build only after both targets compile. Failed builds retain the previous output. */
|
|
15
|
+
export declare function buildFrameworkTheme(options: BuildFrameworkThemeOptions): Promise<BuiltFrameworkTheme>;
|
|
16
|
+
//#endregion
|
|
17
|
+
export type { Framework };
|
|
18
|
+
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { n as frameworkConfig, r as validateFramework, t as entrySource } from "./compiler-C0rEfJCH.mjs";
|
|
2
|
+
import { build } from "vite";
|
|
3
|
+
import { lstat, mkdir, mkdtemp, readFile, readdir, realpath, rename, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
7
|
+
//#region src/notices.ts
|
|
8
|
+
/** Preserve notices for dependencies bundled into either runtime. */
|
|
9
|
+
function noticeCollector(notices) {
|
|
10
|
+
return {
|
|
11
|
+
name: "dirwell-bundle-notices",
|
|
12
|
+
async generateBundle() {
|
|
13
|
+
for (const id of this.getModuleIds()) {
|
|
14
|
+
if (!id.includes("node_modules") || id.startsWith("\0")) continue;
|
|
15
|
+
let directory = path.dirname(id.split("?")[0]);
|
|
16
|
+
while (directory !== path.dirname(directory)) try {
|
|
17
|
+
const manifest = JSON.parse(await readFile(path.join(directory, "package.json"), "utf8"));
|
|
18
|
+
if (manifest === null || typeof manifest !== "object") throw new Error("Invalid bundled package manifest");
|
|
19
|
+
if (!("name" in manifest) || typeof manifest.name !== "string") {
|
|
20
|
+
directory = path.dirname(directory);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const version = "version" in manifest ? String(manifest.version) : "unknown";
|
|
24
|
+
if (!notices.has(manifest.name)) {
|
|
25
|
+
const filename = (await readdir(directory)).find((name) => /^licen[sc]e(?:\.|$)/i.test(name));
|
|
26
|
+
if (!filename) throw new Error(`Bundled package ${manifest.name} has no license file`);
|
|
27
|
+
notices.set(manifest.name, `${manifest.name}@${version}\n${await readFile(path.join(directory, filename), "utf8")}`);
|
|
28
|
+
}
|
|
29
|
+
break;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) throw error;
|
|
32
|
+
directory = path.dirname(directory);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/index.ts
|
|
40
|
+
const marker = ".dirwell-theme-authoring.json";
|
|
41
|
+
function contains(parent, child) {
|
|
42
|
+
const relative = path.relative(parent, child);
|
|
43
|
+
return relative === "" || !relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative);
|
|
44
|
+
}
|
|
45
|
+
/** Publishes a paired build only after both targets compile. Failed builds retain the previous output. */
|
|
46
|
+
async function buildFrameworkTheme(options) {
|
|
47
|
+
validateFramework(options.framework);
|
|
48
|
+
const component = await realpath(path.resolve(options.component));
|
|
49
|
+
if (path.extname(component) !== (options.framework === "svelte" ? ".svelte" : ".vue")) throw new TypeError("Component extension does not match framework");
|
|
50
|
+
const requested = path.resolve(options.output);
|
|
51
|
+
await mkdir(path.dirname(requested), { recursive: true });
|
|
52
|
+
const output = path.join(await realpath(path.dirname(requested)), path.basename(requested));
|
|
53
|
+
if (contains(output, component) || output === path.parse(output).root) throw new Error("Output cannot contain the component source");
|
|
54
|
+
const lock = `${output}.dirwell-lock`;
|
|
55
|
+
await mkdir(lock);
|
|
56
|
+
const priorNodeEnv = process.env.NODE_ENV;
|
|
57
|
+
let stage;
|
|
58
|
+
let backup;
|
|
59
|
+
try {
|
|
60
|
+
let exists = false;
|
|
61
|
+
try {
|
|
62
|
+
const stat = await lstat(output);
|
|
63
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) throw new Error("Output must be a compiler-owned directory");
|
|
64
|
+
const ownership = JSON.parse(await readFile(path.join(output, marker), "utf8"));
|
|
65
|
+
if (ownership.version !== 1 || ownership.component !== component) throw new Error("Output belongs to a different component");
|
|
66
|
+
exists = true;
|
|
67
|
+
} catch (error) {
|
|
68
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) throw error;
|
|
69
|
+
try {
|
|
70
|
+
await lstat(output);
|
|
71
|
+
throw new Error("Refusing to replace unowned output");
|
|
72
|
+
} catch (missing) {
|
|
73
|
+
if (!(missing instanceof Error && "code" in missing && missing.code === "ENOENT")) throw missing;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
stage = await mkdtemp(`${output}.dirwell-stage-`);
|
|
77
|
+
const config = frameworkConfig(options.framework, path.dirname(component));
|
|
78
|
+
const notices = /* @__PURE__ */ new Map();
|
|
79
|
+
for (const target of ["server", "client"]) {
|
|
80
|
+
const id = path.join(path.dirname(component), `.dirwell-virtual-${target}.mjs`);
|
|
81
|
+
await build({
|
|
82
|
+
...config,
|
|
83
|
+
define: {
|
|
84
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
85
|
+
__VUE_OPTIONS_API__: "true",
|
|
86
|
+
__VUE_PROD_DEVTOOLS__: "false",
|
|
87
|
+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: "false"
|
|
88
|
+
},
|
|
89
|
+
plugins: [
|
|
90
|
+
...config.plugins ?? [],
|
|
91
|
+
noticeCollector(notices),
|
|
92
|
+
{
|
|
93
|
+
name: "dirwell-paired-entry",
|
|
94
|
+
resolveId: (source) => source === id ? `\0${id}` : void 0,
|
|
95
|
+
load: (source) => source === `\0${id}` ? entrySource(options.framework, component, target) : void 0
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
build: {
|
|
99
|
+
outDir: stage,
|
|
100
|
+
emptyOutDir: false,
|
|
101
|
+
ssr: target === "server",
|
|
102
|
+
minify: target === "client",
|
|
103
|
+
target: target === "client" ? "es2020" : "node22",
|
|
104
|
+
lib: {
|
|
105
|
+
entry: id,
|
|
106
|
+
formats: ["es"],
|
|
107
|
+
cssFileName: "component",
|
|
108
|
+
fileName: () => `${target}.mjs`
|
|
109
|
+
},
|
|
110
|
+
cssCodeSplit: false,
|
|
111
|
+
rollupOptions: { output: {
|
|
112
|
+
inlineDynamicImports: true,
|
|
113
|
+
entryFileNames: `${target}.mjs`
|
|
114
|
+
} }
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const notice = [...notices].sort(([a], [b]) => a.localeCompare(b)).map(([, text]) => text).join("\n\n");
|
|
119
|
+
await writeFile(path.join(stage, "THIRD_PARTY_NOTICES.txt"), notice);
|
|
120
|
+
for (const filename of ["server.mjs", "client.mjs"]) {
|
|
121
|
+
const code = await readFile(path.join(stage, filename), "utf8");
|
|
122
|
+
await writeFile(path.join(stage, filename), `/*!\n${notice.replaceAll("*/", "* /")}\n*/\n${code}`);
|
|
123
|
+
}
|
|
124
|
+
const server = await readFile(path.join(stage, "server.mjs"), "utf8");
|
|
125
|
+
const hash = createHash("sha256").update(server).digest("hex").slice(0, 16);
|
|
126
|
+
await rename(path.join(stage, "server.mjs"), path.join(stage, `server-${hash}.mjs`));
|
|
127
|
+
const styles = (await Promise.all((await readdir(stage)).filter((name) => name.endsWith(".css")).map((name) => readFile(path.join(stage, name), "utf8")))).join("\n");
|
|
128
|
+
await writeFile(path.join(stage, "styles.css"), styles);
|
|
129
|
+
const theme = options.framework === "svelte" ? "ledger" : "crosswave";
|
|
130
|
+
const factory = options.framework === "svelte" ? "createLedgerTheme" : "createCrosswaveTheme";
|
|
131
|
+
await writeFile(path.join(stage, "theme.mjs"), `import {readFile} from 'node:fs/promises';
|
|
132
|
+
import {${factory}} from '@dirwell/theme-${theme}';
|
|
133
|
+
import {renderBody} from './server-${hash}.mjs';
|
|
134
|
+
const clientScript=await readFile(new URL('./client.mjs',import.meta.url),'utf8');
|
|
135
|
+
const styles=await readFile(new URL('./styles.css',import.meta.url),'utf8');
|
|
136
|
+
export const createTheme=(options={})=>${factory}(options,{renderBody,clientScript,styles,clientType:'module'});
|
|
137
|
+
`);
|
|
138
|
+
await writeFile(path.join(stage, "theme.d.mts"), `import type {ExplorerTheme} from '@dirwell/core';\nimport type {${options.framework === "svelte" ? "Ledger" : "Crosswave"}ThemeOptions} from '@dirwell/theme-${theme}';\nexport declare const createTheme: (options?: ${options.framework === "svelte" ? "Ledger" : "Crosswave"}ThemeOptions) => ExplorerTheme;\n`);
|
|
139
|
+
await writeFile(path.join(stage, marker), JSON.stringify({
|
|
140
|
+
version: 1,
|
|
141
|
+
component,
|
|
142
|
+
framework: options.framework
|
|
143
|
+
}));
|
|
144
|
+
if (exists) {
|
|
145
|
+
backup = `${stage}-previous`;
|
|
146
|
+
await rename(output, backup);
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
await rename(stage, output);
|
|
150
|
+
stage = void 0;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
if (backup) {
|
|
153
|
+
await rename(backup, output);
|
|
154
|
+
backup = void 0;
|
|
155
|
+
}
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
if (backup) {
|
|
159
|
+
await rm(backup, { recursive: true });
|
|
160
|
+
backup = void 0;
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
themeUrl: pathToFileURL(path.join(output, "theme.mjs")).href,
|
|
164
|
+
output
|
|
165
|
+
};
|
|
166
|
+
} finally {
|
|
167
|
+
if (priorNodeEnv === void 0 && process.env.NODE_ENV === "production") delete process.env.NODE_ENV;
|
|
168
|
+
if (stage) await rm(stage, {
|
|
169
|
+
recursive: true,
|
|
170
|
+
force: true
|
|
171
|
+
});
|
|
172
|
+
await rm(lock, {
|
|
173
|
+
recursive: true,
|
|
174
|
+
force: true
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//#endregion
|
|
179
|
+
export { buildFrameworkTheme };
|
|
180
|
+
|
|
181
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/notices.ts","../src/index.ts"],"sourcesContent":["import { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Plugin } from \"vite\";\n/** Preserve notices for dependencies bundled into either runtime. */\nexport function noticeCollector(notices: Map<string, string>): Plugin {\n return {\n name: \"dirwell-bundle-notices\",\n async generateBundle() {\n for (const id of this.getModuleIds()) {\n if (!id.includes(\"node_modules\") || id.startsWith(\"\\0\")) continue;\n let directory = path.dirname(id.split(\"?\")[0]!);\n while (directory !== path.dirname(directory)) {\n try {\n const manifest: unknown = JSON.parse(\n await readFile(path.join(directory, \"package.json\"), \"utf8\"),\n );\n if (manifest === null || typeof manifest !== \"object\")\n throw new Error(\"Invalid bundled package manifest\");\n if (!(\"name\" in manifest) || typeof manifest.name !== \"string\") {\n directory = path.dirname(directory);\n continue;\n }\n const version = \"version\" in manifest ? String(manifest.version) : \"unknown\";\n if (!notices.has(manifest.name)) {\n const filename = (await readdir(directory)).find((name) =>\n /^licen[sc]e(?:\\.|$)/i.test(name),\n );\n if (!filename)\n throw new Error(`Bundled package ${manifest.name} has no license file`);\n notices.set(\n manifest.name,\n `${manifest.name}@${version}\\n${await readFile(path.join(directory, filename), \"utf8\")}`,\n );\n }\n break;\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\"))\n throw error;\n directory = path.dirname(directory);\n }\n }\n }\n },\n };\n}\n","import { build } from \"vite\";\nimport {\n mkdir,\n mkdtemp,\n readFile,\n writeFile,\n readdir,\n realpath,\n rename,\n rm,\n lstat,\n} from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { createHash } from \"node:crypto\";\nimport { frameworkConfig, entrySource, validateFramework, type Framework } from \"./compiler.ts\";\nimport { noticeCollector } from \"./notices.ts\";\nexport type { Framework } from \"./compiler.ts\";\nexport interface BuildFrameworkThemeOptions {\n readonly framework: Framework;\n /** A wrapper component accepting the public model prop. Source code is trusted executable input. */\n readonly component: string;\n /** A dedicated compiler-owned directory. Existing unowned directories are rejected. */\n readonly output: string;\n}\nexport interface BuiltFrameworkTheme {\n readonly themeUrl: string;\n readonly output: string;\n}\nconst marker = \".dirwell-theme-authoring.json\";\nfunction contains(parent: string, child: string) {\n const relative = path.relative(parent, child);\n return (\n relative === \"\" ||\n (!relative.startsWith(`..${path.sep}`) && relative !== \"..\" && !path.isAbsolute(relative))\n );\n}\n/** Publishes a paired build only after both targets compile. Failed builds retain the previous output. */\nexport async function buildFrameworkTheme(\n options: BuildFrameworkThemeOptions,\n): Promise<BuiltFrameworkTheme> {\n validateFramework(options.framework);\n const component = await realpath(path.resolve(options.component));\n if (path.extname(component) !== (options.framework === \"svelte\" ? \".svelte\" : \".vue\"))\n throw new TypeError(\"Component extension does not match framework\");\n const requested = path.resolve(options.output);\n await mkdir(path.dirname(requested), { recursive: true });\n const output = path.join(await realpath(path.dirname(requested)), path.basename(requested));\n if (contains(output, component) || output === path.parse(output).root)\n throw new Error(\"Output cannot contain the component source\");\n const lock = `${output}.dirwell-lock`;\n await mkdir(lock);\n const priorNodeEnv = process.env.NODE_ENV;\n let stage: string | undefined;\n let backup: string | undefined;\n try {\n let exists = false;\n try {\n const stat = await lstat(output);\n if (stat.isSymbolicLink() || !stat.isDirectory())\n throw new Error(\"Output must be a compiler-owned directory\");\n const ownership = JSON.parse(await readFile(path.join(output, marker), \"utf8\"));\n if (ownership.version !== 1 || ownership.component !== component)\n throw new Error(\"Output belongs to a different component\");\n exists = true;\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\")) throw error;\n // A missing marker inside an existing directory is not ownership.\n try {\n await lstat(output);\n throw new Error(\"Refusing to replace unowned output\");\n } catch (missing) {\n if (!(missing instanceof Error && \"code\" in missing && missing.code === \"ENOENT\"))\n throw missing;\n }\n }\n stage = await mkdtemp(`${output}.dirwell-stage-`);\n const config = frameworkConfig(options.framework, path.dirname(component));\n const notices = new Map<string, string>();\n for (const target of [\"server\", \"client\"] as const) {\n const id = path.join(path.dirname(component), `.dirwell-virtual-${target}.mjs`);\n await build({\n ...config,\n define: {\n \"process.env.NODE_ENV\": JSON.stringify(\"production\"),\n __VUE_OPTIONS_API__: \"true\",\n __VUE_PROD_DEVTOOLS__: \"false\",\n __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: \"false\",\n },\n plugins: [\n ...(config.plugins ?? []),\n noticeCollector(notices),\n {\n name: \"dirwell-paired-entry\",\n resolveId: (source) => (source === id ? `\\0${id}` : undefined),\n load: (source) =>\n source === `\\0${id}` ? entrySource(options.framework, component, target) : undefined,\n },\n ],\n build: {\n outDir: stage,\n emptyOutDir: false,\n ssr: target === \"server\",\n minify: target === \"client\",\n target: target === \"client\" ? \"es2020\" : \"node22\",\n lib: {\n entry: id,\n formats: [\"es\"],\n cssFileName: \"component\",\n fileName: () => `${target}.mjs`,\n },\n cssCodeSplit: false,\n rollupOptions: {\n output: { inlineDynamicImports: true, entryFileNames: `${target}.mjs` },\n },\n },\n });\n }\n const notice = [...notices]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([, text]) => text)\n .join(\"\\n\\n\");\n await writeFile(path.join(stage, \"THIRD_PARTY_NOTICES.txt\"), notice);\n for (const filename of [\"server.mjs\", \"client.mjs\"]) {\n const code = await readFile(path.join(stage, filename), \"utf8\");\n await writeFile(\n path.join(stage, filename),\n `/*!\\n${notice.replaceAll(\"*/\", \"* /\")}\\n*/\\n${code}`,\n );\n }\n const server = await readFile(path.join(stage, \"server.mjs\"), \"utf8\");\n const hash = createHash(\"sha256\").update(server).digest(\"hex\").slice(0, 16);\n await rename(path.join(stage, \"server.mjs\"), path.join(stage, `server-${hash}.mjs`));\n const styles = (\n await Promise.all(\n (await readdir(stage))\n .filter((name) => name.endsWith(\".css\"))\n .map((name) => readFile(path.join(stage!, name), \"utf8\")),\n )\n ).join(\"\\n\");\n await writeFile(path.join(stage, \"styles.css\"), styles);\n const theme = options.framework === \"svelte\" ? \"ledger\" : \"crosswave\";\n const factory = options.framework === \"svelte\" ? \"createLedgerTheme\" : \"createCrosswaveTheme\";\n await writeFile(\n path.join(stage, \"theme.mjs\"),\n `import {readFile} from 'node:fs/promises';\nimport {${factory}} from '@dirwell/theme-${theme}';\nimport {renderBody} from './server-${hash}.mjs';\nconst clientScript=await readFile(new URL('./client.mjs',import.meta.url),'utf8');\nconst styles=await readFile(new URL('./styles.css',import.meta.url),'utf8');\nexport const createTheme=(options={})=>${factory}(options,{renderBody,clientScript,styles,clientType:'module'});\n`,\n );\n await writeFile(\n path.join(stage, \"theme.d.mts\"),\n `import type {ExplorerTheme} from '@dirwell/core';\\nimport type {${options.framework === \"svelte\" ? \"Ledger\" : \"Crosswave\"}ThemeOptions} from '@dirwell/theme-${theme}';\\nexport declare const createTheme: (options?: ${options.framework === \"svelte\" ? \"Ledger\" : \"Crosswave\"}ThemeOptions) => ExplorerTheme;\\n`,\n );\n await writeFile(\n path.join(stage, marker),\n JSON.stringify({ version: 1, component, framework: options.framework }),\n );\n if (exists) {\n backup = `${stage}-previous`;\n await rename(output, backup);\n }\n try {\n await rename(stage, output);\n stage = undefined;\n } catch (error) {\n if (backup) {\n await rename(backup, output);\n backup = undefined;\n }\n throw error;\n }\n if (backup) {\n await rm(backup, { recursive: true });\n backup = undefined;\n }\n return { themeUrl: pathToFileURL(path.join(output, \"theme.mjs\")).href, output };\n } finally {\n if (priorNodeEnv === undefined && process.env.NODE_ENV === \"production\")\n delete process.env.NODE_ENV;\n if (stage) await rm(stage, { recursive: true, force: true });\n await rm(lock, { recursive: true, force: true });\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dirwell/theme-authoring",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.1-alpha.1",
|
|
4
|
+
"description": "Paired Svelte/Vue theme compilation and native development HMR.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/vp-tw/dirwell.git",
|
|
9
|
+
"directory": "packages/theme-authoring"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.mts",
|
|
20
|
+
"import": "./dist/index.mjs"
|
|
21
|
+
},
|
|
22
|
+
"./dev": {
|
|
23
|
+
"types": "./dist/dev.d.mts",
|
|
24
|
+
"import": "./dist/dev.mjs"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public",
|
|
29
|
+
"provenance": true,
|
|
30
|
+
"tag": "alpha"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@dirwell/core": "0.0.1-alpha.1",
|
|
34
|
+
"@dirwell/server": "0.0.1-alpha.1",
|
|
35
|
+
"@dirwell/theme-crosswave": "0.0.1-alpha.1",
|
|
36
|
+
"@dirwell/theme-ledger": "0.0.1-alpha.1",
|
|
37
|
+
"@sveltejs/vite-plugin-svelte": "7.3.1",
|
|
38
|
+
"@vitejs/plugin-vue": "6.0.10",
|
|
39
|
+
"@vue/compiler-sfc": "3.5.43",
|
|
40
|
+
"svelte": "5.57.2",
|
|
41
|
+
"vite": "8.3.0",
|
|
42
|
+
"vue": "3.5.43"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=22.12.0"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "vp pack"
|
|
49
|
+
}
|
|
6
50
|
}
|