ignotum 0.0.13 → 0.0.15
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/README.md +6 -6
- package/dist/cli/bin.mjs +6111 -4448
- package/dist/cli/bin.mjs.map +1 -1
- package/dist/cli/emscripten-module-D5GzfUNv.mjs +533 -0
- package/dist/cli/emscripten-module-D5GzfUNv.mjs.map +1 -0
- package/dist/cli/ffi-7IElU4Co.mjs +148 -0
- package/dist/cli/ffi-7IElU4Co.mjs.map +1 -0
- package/dist/cli/managed-release-WHYLZwaS.mjs +10902 -0
- package/dist/cli/managed-release-WHYLZwaS.mjs.map +1 -0
- package/dist/cli/managed-release.d.mts +1 -0
- package/dist/cli/managed-release.mjs +14 -0
- package/dist/cli/managed-release.mjs.map +1 -0
- package/dist/cli/module-ES6BEMUI-D36I4NVn.mjs +1289 -0
- package/dist/cli/module-ES6BEMUI-D36I4NVn.mjs.map +1 -0
- package/dist/runtime/{api-Cv3hMbzo.d.ts → api-B4fwp5a2.d.ts} +4 -4
- package/dist/runtime/bootstrap-BISQSn_O.js +916 -0
- package/dist/runtime/bootstrap-BISQSn_O.js.map +1 -0
- package/dist/runtime/bootstrap-BTFScKAc.d.ts +545 -0
- package/dist/runtime/client.d.ts +50 -15
- package/dist/runtime/client.js +7 -1138
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/descriptor-CTY4mtwS-cS43EbwS.js +269 -0
- package/dist/runtime/descriptor-CTY4mtwS-cS43EbwS.js.map +1 -0
- package/dist/runtime/{id-Bt9XWRGL.js → id--1m0NuUL.js} +4 -4
- package/dist/runtime/id--1m0NuUL.js.map +1 -0
- package/dist/runtime/{id-BzFHf3Wo-DGPCjgrf.d.ts → id-7an3nxTu-DZJSM5xh.d.ts} +2 -2
- package/dist/runtime/id-CBOt2kDo.d.ts +1 -0
- package/dist/runtime/identity-QjtJRxBD.d.ts +2 -0
- package/dist/runtime/image-Djtjy4Z8.js +19 -0
- package/dist/runtime/image-Djtjy4Z8.js.map +1 -0
- package/dist/runtime/index-D4seNHlX.d.ts +184 -0
- package/dist/runtime/internal/api.d.ts +1 -1
- package/dist/runtime/internal/api.js +30 -1
- package/dist/runtime/internal/api.js.map +1 -0
- package/dist/runtime/internal/bootstrap.d.ts +2 -0
- package/dist/runtime/internal/bootstrap.js +2 -0
- package/dist/runtime/internal/client.d.ts +2 -0
- package/dist/runtime/internal/client.js +75 -0
- package/dist/runtime/internal/client.js.map +1 -0
- package/dist/runtime/internal/host.d.ts +25 -8
- package/dist/runtime/internal/host.js +27 -6
- package/dist/runtime/internal/host.js.map +1 -1
- package/dist/runtime/internal/routes.d.ts +2 -0
- package/dist/runtime/internal/routes.js +2 -0
- package/dist/runtime/internal/server.d.ts +1 -1
- package/dist/runtime/internal/server.js +1 -1
- package/dist/runtime/internal/types.d.ts +2 -1
- package/dist/runtime/internal/types.js +1 -1
- package/dist/runtime/pagination-CBOt2kDo.d.ts +1 -0
- package/dist/runtime/pagination-D3qd6s9N.js +33 -0
- package/dist/runtime/pagination-D3qd6s9N.js.map +1 -0
- package/dist/runtime/result-BkziOG1L.d.ts +1 -0
- package/dist/runtime/router-BSBI1oN1.js +2377 -0
- package/dist/runtime/router-BSBI1oN1.js.map +1 -0
- package/dist/runtime/routes-Ce8TVP-T.js +690 -0
- package/dist/runtime/routes-Ce8TVP-T.js.map +1 -0
- package/dist/runtime/{schema-1Zs03-iS.js → schema-D1wOqiNH.js} +40 -12
- package/dist/runtime/schema-D1wOqiNH.js.map +1 -0
- package/dist/runtime/server.d.ts +5 -5
- package/dist/runtime/server.js +2 -2
- package/dist/runtime/{sync-Bs8J3fIr.d.ts → sync-D-GK2sv9.d.ts} +3 -2
- package/dist/runtime/{api-CAgKDij7.js → sync-DzUwA8W9.js} +22 -41
- package/dist/runtime/sync-DzUwA8W9.js.map +1 -0
- package/dist/runtime/types-DeCCyqLU-BIm7rU-0.d.ts +341 -0
- package/package.json +29 -4
- package/src/cli/agent-files.ts +14 -8
- package/src/cli/build/managed-client.ts +411 -0
- package/src/cli/build/managed-server.ts +294 -0
- package/src/cli/build/managed.ts +67 -0
- package/src/cli/build/output.ts +47 -0
- package/src/cli/build/server.ts +51 -220
- package/src/cli/client-config.ts +1 -140
- package/src/cli/client-styles.ts +1 -0
- package/src/cli/codegen.ts +9 -4
- package/src/cli/command.ts +28 -5
- package/src/cli/control-client.ts +84 -101
- package/src/cli/deploy.ts +133 -177
- package/src/cli/dev.ts +506 -107
- package/src/cli/image-assets.ts +499 -0
- package/src/cli/managed-client-boundaries.ts +103 -0
- package/src/cli/managed-dev-platform.ts +118 -0
- package/src/cli/managed-exports.ts +219 -0
- package/src/cli/managed-release-bin.ts +13 -0
- package/src/cli/managed-release.ts +260 -0
- package/src/cli/module-boundaries.ts +11 -1
- package/src/cli/new-app.ts +111 -87
- package/src/cli/route-codegen.ts +311 -0
- package/src/cli/route-static.ts +710 -0
- package/src/client/bootstrap.ts +110 -0
- package/src/client/errors.ts +13 -7
- package/src/client/files.ts +64 -0
- package/src/client/id.ts +9 -5
- package/src/client/image.ts +28 -0
- package/src/client/index.ts +25 -2
- package/src/client/managed-client.ts +729 -0
- package/src/client/managed-upgrade.ts +283 -0
- package/src/client/recovery-journal.ts +195 -0
- package/src/client/route-boundaries.ts +184 -0
- package/src/client/router-history.ts +152 -0
- package/src/client/router-store.ts +644 -0
- package/src/client/router.ts +324 -0
- package/src/client/routes.ts +28 -0
- package/src/client/sync.ts +66 -592
- package/src/dev-runtime/database.ts +77 -2
- package/src/dev-runtime/functions.ts +3 -3
- package/src/dev-runtime/id.ts +19 -4
- package/src/dev-runtime/managed-functions.ts +255 -0
- package/src/dev-runtime/managed-sync.ts +263 -0
- package/src/dev-runtime/managed-websocket.ts +71 -0
- package/src/dev-runtime/migrations.ts +20 -0
- package/src/dev-runtime/sync.ts +236 -236
- package/src/image-assets.d.ts +36 -0
- package/src/internal/client.ts +186 -0
- package/src/internal/host.ts +1 -1
- package/src/internal/http-paths.ts +0 -3
- package/src/internal/routes.ts +45 -0
- package/dist/runtime/api-CAgKDij7.js.map +0 -1
- package/dist/runtime/descriptor-Cyo9FP9n-C0SRVXNW.js +0 -154
- package/dist/runtime/descriptor-Cyo9FP9n-C0SRVXNW.js.map +0 -1
- package/dist/runtime/id-Bt9XWRGL.js.map +0 -1
- package/dist/runtime/id-Dz0apuB3.d.ts +0 -1
- package/dist/runtime/index-D54flWtH.d.ts +0 -402
- package/dist/runtime/pagination-DnKg3dkI-r5ZUxBBx.d.ts +0 -112
- package/dist/runtime/pagination-Dz0apuB3.d.ts +0 -1
- package/dist/runtime/result-DKAA4gpS.d.ts +0 -1
- package/dist/runtime/schema-1Zs03-iS.js.map +0 -1
- package/src/cli/build/client.ts +0 -119
- package/src/cli/build/public.ts +0 -186
- package/src/cli/client-entry.ts +0 -152
- package/src/cli/client-plugin.ts +0 -136
- package/src/client/app.ts +0 -15
package/src/cli/dev.ts
CHANGED
|
@@ -1,26 +1,37 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
1
2
|
import prefresh from "@prefresh/vite";
|
|
2
3
|
import tailwindcss from "@tailwindcss/vite";
|
|
3
|
-
import { Effect, FileSystem, Path, Schema } from "effect";
|
|
4
|
-
import { createServer } from "vite";
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
import {
|
|
4
|
+
import { Crypto, Effect, FileSystem, Option, Path, Schema, Scope } from "effect";
|
|
5
|
+
import { createServer, normalizePath, type Plugin, type ViteDevServer } from "vite";
|
|
6
|
+
import { ChildProcessSpawner } from "effect/unstable/process";
|
|
7
|
+
import { ExecutionSelection, RuntimeRequirements } from "@ignotum/contracts/platform";
|
|
8
|
+
import { managedSelectionPath } from "@ignotum/contracts/managed-sync";
|
|
9
|
+
import { renderDocument } from "@ignotum/shared/document";
|
|
10
|
+
import { compilePatterns, matchLocation, resolveMetadata } from "@ignotum/shared/routing";
|
|
11
|
+
import { sha256 } from "@ignotum/versions";
|
|
12
|
+
import { InvalidClientFile } from "./client-config.js";
|
|
13
|
+
import { clientStylesSource } from "./client-styles.js";
|
|
14
|
+
import { generateClientRoutes, type ClientRouteDiscovery } from "./route-codegen.js";
|
|
15
|
+
import { createImageAssetsPlugin } from "./image-assets.js";
|
|
16
|
+
import { managedClientBoundariesPlugin } from "./managed-client-boundaries.js";
|
|
17
|
+
import { moduleBoundariesPlugin } from "./module-boundaries.js";
|
|
18
|
+
import { managedBrowserExports, managedPreactPeerPlugin } from "./managed-exports.js";
|
|
19
|
+
import { localManagedReleaseProvider } from "./managed-release.js";
|
|
8
20
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
21
|
+
buildLocalBrowserTools,
|
|
22
|
+
localExecutionSelection,
|
|
23
|
+
localPlatformRelease,
|
|
24
|
+
localPlatformUrl,
|
|
25
|
+
type LocalManagedRelease,
|
|
26
|
+
} from "./managed-dev-platform.js";
|
|
15
27
|
import { acquireDevDatabaseLock, devDatabasePath } from "../dev-runtime/dev-database.js";
|
|
16
|
-
import {
|
|
17
|
-
|
|
28
|
+
import { ignotumManagedSyncPlugin } from "../dev-runtime/sync.js";
|
|
29
|
+
import { createManagedFunctionLoader } from "../dev-runtime/managed-functions.js";
|
|
30
|
+
import { buildManagedServer } from "./build/server.js";
|
|
31
|
+
import { generate } from "./codegen.js";
|
|
18
32
|
export class ViteStartupFailed extends Schema.TaggedError<ViteStartupFailed>()(
|
|
19
33
|
"ViteStartupFailed",
|
|
20
|
-
{
|
|
21
|
-
cause: Schema.Defect(),
|
|
22
|
-
message: Schema.String,
|
|
23
|
-
},
|
|
34
|
+
{ cause: Schema.Defect(), message: Schema.String },
|
|
24
35
|
) {}
|
|
25
36
|
|
|
26
37
|
export interface DevOptions {
|
|
@@ -30,111 +41,499 @@ export interface DevOptions {
|
|
|
30
41
|
readonly appDirectory: string;
|
|
31
42
|
}
|
|
32
43
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
const registrationId = "virtual:ignotum/dev-registration";
|
|
45
|
+
const stylesId = "virtual:ignotum/dev-styles.css";
|
|
46
|
+
const moduleUrl = (id: string) => `/@id/__x00__${id}`;
|
|
47
|
+
const toolingPrefix = "/_ignotum/development/tools/";
|
|
48
|
+
|
|
49
|
+
export interface ManagedDevOptions extends DevOptions {
|
|
50
|
+
readonly applicationName?: string;
|
|
51
|
+
readonly sdkDirectory?: string;
|
|
52
|
+
readonly provider?: LocalManagedRelease;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const renderDevRegistration = (discovery: ClientRouteDiscovery, applicationName: string) => `
|
|
56
|
+
import { mountClient } from "ignotum/internal/bootstrap";
|
|
57
|
+
import ${JSON.stringify(`${toolingPrefix}debug.js`)};
|
|
58
|
+
import ${JSON.stringify(stylesId)};
|
|
59
|
+
const registration = {
|
|
60
|
+
applicationName: ${JSON.stringify(applicationName)},
|
|
61
|
+
routes: ${JSON.stringify(discovery.routes)},
|
|
62
|
+
layouts: ${JSON.stringify(discovery.layouts)},
|
|
63
|
+
modules: new Map([${discovery.modules.map((module) => `[${JSON.stringify(module.id)}, { load: () => import(${JSON.stringify(`/@fs/${normalizePath(module.path)}`)}) }]`).join(",\n")}]),
|
|
64
|
+
};
|
|
65
|
+
let mounted;
|
|
66
|
+
export default function mount(selection) {
|
|
67
|
+
import.meta.hot.data.selection = selection;
|
|
68
|
+
mounted?.dispose();
|
|
69
|
+
mounted = mountClient(registration, selection);
|
|
70
|
+
return mounted;
|
|
71
|
+
}
|
|
72
|
+
if (import.meta.hot) {
|
|
73
|
+
import.meta.hot.accept();
|
|
74
|
+
import.meta.hot.dispose(() => mounted?.dispose());
|
|
75
|
+
if (import.meta.hot.data.selection) mount(import.meta.hot.data.selection);
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
/** Internal assembly until all CLI producers switch together. The caller owns its Effect scope. */
|
|
80
|
+
export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(function* (
|
|
81
|
+
options: ManagedDevOptions,
|
|
36
82
|
) {
|
|
37
|
-
const
|
|
83
|
+
const fs = yield* FileSystem.FileSystem;
|
|
38
84
|
const path = yield* Path.Path;
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const clientDirectory =
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
const appDirectory = yield* fs.realPath(options.appDirectory);
|
|
86
|
+
const appName = options.applicationName ?? path.basename(appDirectory);
|
|
87
|
+
const clientDirectory = path.join(appDirectory, "client");
|
|
88
|
+
const sdkDirectory = options.sdkDirectory ?? fileURLToPath(new URL("../../", import.meta.url));
|
|
89
|
+
const validateFiles = Effect.fn("ManagedDev.validateFiles")(function* () {
|
|
90
|
+
for (const publicPath of [
|
|
91
|
+
path.join(appDirectory, "public"),
|
|
92
|
+
path.join(clientDirectory, "public"),
|
|
93
|
+
]) {
|
|
94
|
+
if (
|
|
95
|
+
(yield* fs.exists(publicPath)) ||
|
|
96
|
+
Option.isSome(yield* Effect.option(fs.readLink(publicPath)))
|
|
97
|
+
)
|
|
98
|
+
return yield* InvalidClientFile.make({
|
|
99
|
+
path: publicPath,
|
|
100
|
+
message:
|
|
101
|
+
"App public directories are not supported. Import supported images from client/_assets instead.",
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
const iconPath = path.join(clientDirectory, "icon.svg");
|
|
105
|
+
if (!(yield* fs.exists(iconPath))) return undefined;
|
|
106
|
+
if ((yield* fs.stat(iconPath)).type !== "File")
|
|
107
|
+
return yield* InvalidClientFile.make({
|
|
108
|
+
path: iconPath,
|
|
109
|
+
message: "The client icon must be a regular file.",
|
|
110
|
+
});
|
|
111
|
+
const bytes = yield* fs.readFile(iconPath);
|
|
112
|
+
return { bytes, url: `/_ignotum/assets/${yield* sha256(bytes)}/icon.svg` };
|
|
113
|
+
});
|
|
114
|
+
let icon = yield* validateFiles();
|
|
115
|
+
let discovery = yield* generateClientRoutes(appDirectory);
|
|
116
|
+
let patterns = yield* compilePatterns(discovery.routes, discovery.layouts);
|
|
117
|
+
let provider = options.provider ?? (yield* localManagedReleaseProvider(sdkDirectory));
|
|
118
|
+
let selection = localExecutionSelection(appDirectory, provider);
|
|
119
|
+
let tools = yield* buildLocalBrowserTools(provider, selection);
|
|
120
|
+
const runPromise = Effect.runPromiseWith(
|
|
121
|
+
yield* Effect.context<
|
|
122
|
+
| FileSystem.FileSystem
|
|
123
|
+
| Path.Path
|
|
124
|
+
| Crypto.Crypto
|
|
125
|
+
| Scope.Scope
|
|
126
|
+
| ChildProcessSpawner.ChildProcessSpawner
|
|
127
|
+
>(),
|
|
128
|
+
);
|
|
129
|
+
let diagnostic: unknown;
|
|
130
|
+
let serverDiagnostic: unknown;
|
|
131
|
+
let serverWork = Promise.resolve();
|
|
132
|
+
let viteServer: ViteDevServer | undefined;
|
|
133
|
+
let work = Promise.resolve();
|
|
134
|
+
const images = yield* createImageAssetsPlugin(appDirectory);
|
|
135
|
+
const boundaries = yield* moduleBoundariesPlugin("Client", appDirectory);
|
|
136
|
+
const platform = yield* managedClientBoundariesPlugin(appDirectory);
|
|
137
|
+
const peers = yield* managedPreactPeerPlugin({ resolvePeer: (specifier) => specifier });
|
|
138
|
+
// These checks run before the resolver turns supported externals into selected graph URLs.
|
|
139
|
+
const originalPlatformResolve = platform.resolveId;
|
|
140
|
+
platform.resolveId = function (specifier, importer) {
|
|
141
|
+
if (importer === `\0${registrationId}` && specifier === "ignotum/internal/bootstrap")
|
|
142
|
+
return {
|
|
143
|
+
id: localPlatformUrl(selection.platformReleaseId, provider.resolve("Browser", specifier)!),
|
|
144
|
+
external: true as const,
|
|
145
|
+
};
|
|
146
|
+
const resolved = originalPlatformResolve.call(this, specifier, importer);
|
|
147
|
+
if (resolved !== undefined && resolved.external) {
|
|
148
|
+
const module = provider.resolve("Browser", specifier);
|
|
149
|
+
if (module === undefined) this.error(`The local platform does not supply ${specifier}.`);
|
|
150
|
+
return { id: localPlatformUrl(selection.platformReleaseId, module), external: true as const };
|
|
151
|
+
}
|
|
152
|
+
return resolved;
|
|
153
|
+
};
|
|
154
|
+
const originalPeerResolve = peers.resolveId;
|
|
155
|
+
peers.resolveId = async function (specifier, importer) {
|
|
156
|
+
const resolved = await originalPeerResolve.call(this, specifier, importer);
|
|
157
|
+
return resolved === undefined
|
|
158
|
+
? undefined
|
|
159
|
+
: {
|
|
160
|
+
id: localPlatformUrl(
|
|
161
|
+
selection.platformReleaseId,
|
|
162
|
+
provider.resolve("Browser", specifier)!,
|
|
163
|
+
),
|
|
164
|
+
external: true as const,
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
const databasePath = yield* devDatabasePath(appDirectory);
|
|
168
|
+
yield* fs.makeDirectory(path.dirname(databasePath), { recursive: true });
|
|
169
|
+
yield* acquireDevDatabaseLock(appDirectory);
|
|
170
|
+
let loader = yield* createManagedFunctionLoader(appDirectory, {
|
|
171
|
+
guest: provider.guest,
|
|
172
|
+
release: localPlatformRelease(provider, selection),
|
|
173
|
+
requirements: Schema.decodeUnknownSync(RuntimeRequirements)({
|
|
174
|
+
clientApiVersion: 1,
|
|
175
|
+
serverApiVersion: 1,
|
|
176
|
+
capabilities: ["operations", "routing", "images"],
|
|
177
|
+
}),
|
|
178
|
+
});
|
|
179
|
+
const compileServer = Effect.fn("ManagedDev.compileServer")(function* () {
|
|
180
|
+
const generated = yield* generate(appDirectory);
|
|
181
|
+
const build = yield* buildManagedServer(
|
|
182
|
+
appDirectory,
|
|
183
|
+
path.join(appDirectory, ".ignotum/dev/server"),
|
|
184
|
+
generated.functionModules,
|
|
185
|
+
);
|
|
186
|
+
yield* loader.reload(build);
|
|
187
|
+
});
|
|
188
|
+
yield* compileServer();
|
|
189
|
+
const sync = ignotumManagedSyncPlugin(appDirectory, databasePath, {
|
|
190
|
+
selection: () => selection,
|
|
191
|
+
isServerDependency: (file) => {
|
|
192
|
+
const relative = normalizePath(path.relative(appDirectory, file));
|
|
193
|
+
return (
|
|
194
|
+
!relative.startsWith("../") &&
|
|
195
|
+
!path.isAbsolute(relative) &&
|
|
196
|
+
!relative.startsWith("client/") &&
|
|
197
|
+
!relative.startsWith("_generated/") &&
|
|
198
|
+
!relative.startsWith(".ignotum/") &&
|
|
199
|
+
!relative.includes("node_modules/") &&
|
|
200
|
+
/\.(ts|tsx|js|mjs)$/.test(relative)
|
|
201
|
+
);
|
|
202
|
+
},
|
|
203
|
+
loadModule: async (filename) => {
|
|
204
|
+
await serverWork;
|
|
205
|
+
return loader.ssrLoadModule(filename);
|
|
206
|
+
},
|
|
207
|
+
beforeReload: () => {
|
|
208
|
+
const compile = () => runPromise(compileServer());
|
|
209
|
+
serverWork = serverWork.then(compile, compile).then(
|
|
210
|
+
() => {
|
|
211
|
+
const recovered = serverDiagnostic !== undefined;
|
|
212
|
+
serverDiagnostic = undefined;
|
|
213
|
+
if (recovered) viteServer?.ws.send({ type: "full-reload" });
|
|
214
|
+
},
|
|
215
|
+
(cause) => {
|
|
216
|
+
loader.invalidate(cause);
|
|
217
|
+
serverDiagnostic = cause;
|
|
218
|
+
viteServer?.ws.send({ type: "error", err: { message: String(cause), stack: "" } });
|
|
219
|
+
throw cause;
|
|
220
|
+
},
|
|
221
|
+
);
|
|
222
|
+
return serverWork;
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
const plugin: Plugin = {
|
|
226
|
+
name: "ignotum:managed-development",
|
|
227
|
+
enforce: "pre",
|
|
228
|
+
resolveId(id) {
|
|
229
|
+
if (id === registrationId || id === stylesId) return `\0${id}`;
|
|
230
|
+
if (id === "@prefresh/core" || id === "@prefresh/utils")
|
|
231
|
+
return {
|
|
232
|
+
id: `${toolingPrefix}${id.slice("@prefresh/".length)}.js`,
|
|
233
|
+
external: true as const,
|
|
234
|
+
};
|
|
235
|
+
if (id.startsWith(toolingPrefix) || id.startsWith("/_ignotum/platform/"))
|
|
236
|
+
return { id, external: true as const };
|
|
237
|
+
},
|
|
238
|
+
load(id) {
|
|
239
|
+
if (id === `\0${registrationId}`) {
|
|
240
|
+
if (diagnostic !== undefined) throw diagnostic;
|
|
241
|
+
if (serverDiagnostic !== undefined) throw serverDiagnostic;
|
|
242
|
+
return renderDevRegistration(discovery, appName);
|
|
243
|
+
}
|
|
244
|
+
if (id === `\0${stylesId}`) return clientStylesSource;
|
|
245
|
+
},
|
|
246
|
+
configResolved(config) {
|
|
247
|
+
// Prefresh adds optimizer entries. Its tools are already compiled against the managed renderer.
|
|
248
|
+
config.optimizeDeps.include = [];
|
|
249
|
+
config.optimizeDeps.noDiscovery = true;
|
|
250
|
+
config.optimizeDeps.exclude = [
|
|
251
|
+
...managedBrowserExports.map((entry) => entry.specifier),
|
|
252
|
+
"@prefresh/core",
|
|
253
|
+
"@prefresh/utils",
|
|
254
|
+
];
|
|
255
|
+
},
|
|
256
|
+
configureServer(server) {
|
|
257
|
+
viteServer = server;
|
|
258
|
+
server.watcher.add([clientDirectory, path.join(appDirectory, "_shared")]);
|
|
259
|
+
const regenerate = async () => {
|
|
260
|
+
try {
|
|
261
|
+
const nextIcon = await runPromise(validateFiles());
|
|
262
|
+
const next = await runPromise(generateClientRoutes(appDirectory));
|
|
263
|
+
const nextPatterns = await runPromise(compilePatterns(next.routes, next.layouts));
|
|
264
|
+
const changed =
|
|
265
|
+
JSON.stringify({
|
|
266
|
+
routes: next.routes,
|
|
267
|
+
layouts: next.layouts,
|
|
268
|
+
modules: next.modules,
|
|
269
|
+
icon: nextIcon?.url,
|
|
270
|
+
}) !==
|
|
271
|
+
JSON.stringify({
|
|
272
|
+
routes: discovery.routes,
|
|
273
|
+
layouts: discovery.layouts,
|
|
274
|
+
modules: discovery.modules,
|
|
275
|
+
icon: icon?.url,
|
|
276
|
+
});
|
|
277
|
+
discovery = next;
|
|
278
|
+
patterns = nextPatterns;
|
|
279
|
+
icon = nextIcon;
|
|
280
|
+
const recovered = diagnostic !== undefined;
|
|
281
|
+
diagnostic = undefined;
|
|
282
|
+
server.watcher.add(discovery.dependencies);
|
|
283
|
+
if (changed || recovered) {
|
|
284
|
+
const module = server.moduleGraph.getModuleById(`\0${registrationId}`);
|
|
285
|
+
if (module !== undefined) await server.reloadModule(module);
|
|
286
|
+
}
|
|
287
|
+
} catch (error) {
|
|
288
|
+
diagnostic = error;
|
|
289
|
+
server.ws.send({
|
|
290
|
+
type: "error",
|
|
291
|
+
err: {
|
|
292
|
+
message: String(error),
|
|
293
|
+
stack: error instanceof Error ? (error.stack ?? "") : "",
|
|
90
294
|
},
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
const onChange = (file: string) => {
|
|
299
|
+
const relative = normalizePath(path.relative(appDirectory, file));
|
|
300
|
+
if (
|
|
301
|
+
relative.startsWith("_generated/") ||
|
|
302
|
+
relative.startsWith(".ignotum/") ||
|
|
303
|
+
relative.includes("node_modules/")
|
|
304
|
+
)
|
|
305
|
+
return;
|
|
306
|
+
work = work.then(regenerate);
|
|
307
|
+
};
|
|
308
|
+
server.watcher.on("addDir", onChange);
|
|
309
|
+
server.watcher.on("unlinkDir", onChange);
|
|
310
|
+
server.watcher.on("add", onChange);
|
|
311
|
+
server.watcher.on("unlink", onChange);
|
|
312
|
+
server.watcher.on("change", onChange);
|
|
313
|
+
server.httpServer?.once("close", () => {
|
|
314
|
+
server.watcher.off("addDir", onChange);
|
|
315
|
+
server.watcher.off("unlinkDir", onChange);
|
|
316
|
+
server.watcher.off("add", onChange);
|
|
317
|
+
server.watcher.off("unlink", onChange);
|
|
318
|
+
server.watcher.off("change", onChange);
|
|
319
|
+
});
|
|
320
|
+
server.middlewares.use((request, response, next) => {
|
|
321
|
+
const url = new URL(
|
|
322
|
+
request.url ?? "/",
|
|
323
|
+
`http://${request.headers.host ?? "ignotum.local"}`,
|
|
324
|
+
);
|
|
325
|
+
const send = (body: string | Uint8Array, contentType: string, immutable = false) => {
|
|
326
|
+
response.setHeader("content-type", contentType);
|
|
327
|
+
response.setHeader(
|
|
328
|
+
"cache-control",
|
|
329
|
+
immutable ? "public, max-age=31536000, immutable" : "no-store",
|
|
330
|
+
);
|
|
331
|
+
response.setHeader("x-content-type-options", "nosniff");
|
|
332
|
+
response.end(request.method === "HEAD" ? undefined : body);
|
|
333
|
+
};
|
|
334
|
+
if (url.pathname === managedSelectionPath) {
|
|
335
|
+
send(JSON.stringify({ protocolVersion: 1, selection }), "application/json");
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
const platformPrefix = `/_ignotum/platform/${selection.platformReleaseId}/`;
|
|
339
|
+
if (url.pathname.startsWith(platformPrefix)) {
|
|
340
|
+
const modulePath = url.pathname.slice(platformPrefix.length);
|
|
341
|
+
const allowed = provider.browser.manifest.modules.some(
|
|
342
|
+
(module) => module.path === modulePath,
|
|
343
|
+
);
|
|
344
|
+
const bytes = allowed ? provider.read("Browser", modulePath) : undefined;
|
|
345
|
+
if (bytes === undefined) {
|
|
346
|
+
response.statusCode = 404;
|
|
347
|
+
response.end();
|
|
348
|
+
} else send(bytes, "text/javascript", true);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (url.pathname.startsWith(toolingPrefix)) {
|
|
352
|
+
const code = tools.get(url.pathname.slice(toolingPrefix.length));
|
|
353
|
+
if (code === undefined) {
|
|
354
|
+
response.statusCode = 404;
|
|
355
|
+
response.end();
|
|
356
|
+
} else send(code, "text/javascript");
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (icon !== undefined && url.pathname === icon.url) {
|
|
360
|
+
send(icon.bytes, "image/svg+xml", true);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
if (
|
|
364
|
+
url.pathname === "/icon.svg" ||
|
|
365
|
+
url.pathname.startsWith("/server/") ||
|
|
366
|
+
url.pathname.startsWith("/.")
|
|
367
|
+
) {
|
|
368
|
+
response.statusCode = 404;
|
|
369
|
+
response.end();
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const isDocument =
|
|
373
|
+
(request.method === "GET" || request.method === "HEAD") &&
|
|
374
|
+
!url.pathname.startsWith("/_ignotum/") &&
|
|
375
|
+
!url.pathname.startsWith("/@") &&
|
|
376
|
+
!url.searchParams.has("import") &&
|
|
377
|
+
(request.headers.accept?.includes("text/html") ?? false);
|
|
378
|
+
if (!isDocument) {
|
|
379
|
+
next();
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
void work
|
|
383
|
+
.then(async () => {
|
|
384
|
+
if (diagnostic !== undefined) throw diagnostic;
|
|
385
|
+
if (serverDiagnostic !== undefined) throw serverDiagnostic;
|
|
386
|
+
const outcome = await runPromise(matchLocation(patterns, request.url ?? "/"));
|
|
387
|
+
const metadata = await runPromise(
|
|
388
|
+
resolveMetadata({
|
|
389
|
+
applicationName: appName,
|
|
390
|
+
layouts: outcome.layouts.map((layout) => layout.metadata),
|
|
391
|
+
page: outcome._tag === "NotFound" ? undefined : outcome.route?.metadata,
|
|
392
|
+
outcome: outcome._tag,
|
|
393
|
+
}),
|
|
394
|
+
);
|
|
395
|
+
const imports = Object.fromEntries(
|
|
396
|
+
Object.entries(provider.browser.manifest.entries).map(([specifier, module]) => [
|
|
397
|
+
specifier,
|
|
398
|
+
localPlatformUrl(selection.platformReleaseId, module),
|
|
399
|
+
]),
|
|
400
|
+
);
|
|
401
|
+
const html = renderDocument({
|
|
402
|
+
metadata,
|
|
403
|
+
selection,
|
|
404
|
+
importMap: { imports },
|
|
405
|
+
browserEntry: imports["ignotum/internal/bootstrap"]!,
|
|
406
|
+
registration: { module: moduleUrl(registrationId), exportName: "default" },
|
|
407
|
+
styles: [],
|
|
408
|
+
icon: icon?.url,
|
|
409
|
+
});
|
|
410
|
+
response.statusCode =
|
|
411
|
+
outcome._tag === "NotFound" ? 404 : outcome._tag === "Invalid" ? 400 : 200;
|
|
412
|
+
send(
|
|
413
|
+
html.replace("</head>", '<script type="module" src="/@vite/client"></script></head>'),
|
|
414
|
+
"text/html; charset=utf-8",
|
|
415
|
+
);
|
|
416
|
+
})
|
|
417
|
+
.catch(next);
|
|
418
|
+
});
|
|
419
|
+
},
|
|
420
|
+
};
|
|
421
|
+
const server = yield* Effect.acquireRelease(
|
|
422
|
+
Effect.tryPromise({
|
|
423
|
+
try: async () =>
|
|
424
|
+
createServer({
|
|
425
|
+
appType: "custom",
|
|
426
|
+
configFile: false,
|
|
427
|
+
envDir: false,
|
|
428
|
+
mode: "development",
|
|
429
|
+
root: appDirectory,
|
|
430
|
+
publicDir: false,
|
|
431
|
+
plugins: [
|
|
432
|
+
plugin,
|
|
433
|
+
images.plugin,
|
|
434
|
+
boundaries,
|
|
435
|
+
platform,
|
|
436
|
+
peers,
|
|
437
|
+
sync,
|
|
438
|
+
await prefresh(),
|
|
439
|
+
tailwindcss(),
|
|
440
|
+
],
|
|
441
|
+
oxc: { jsx: { importSource: "ignotum/client", runtime: "automatic" } },
|
|
442
|
+
optimizeDeps: { noDiscovery: true, include: [] },
|
|
443
|
+
resolve: {
|
|
444
|
+
alias: [
|
|
445
|
+
{
|
|
446
|
+
find: /^tailwindcss$/,
|
|
447
|
+
replacement: fileURLToPath(import.meta.resolve("tailwindcss/index.css")),
|
|
95
448
|
},
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
449
|
+
],
|
|
450
|
+
tsconfigPaths: true,
|
|
451
|
+
},
|
|
452
|
+
server: {
|
|
453
|
+
preTransformRequests: false,
|
|
454
|
+
host: options.host,
|
|
455
|
+
port: options.port,
|
|
456
|
+
open: options.open,
|
|
457
|
+
strictPort: true,
|
|
458
|
+
forwardConsole: { logLevels: ["warn", "error"], unhandledErrors: true },
|
|
459
|
+
},
|
|
460
|
+
}),
|
|
103
461
|
catch: (cause) =>
|
|
104
462
|
ViteStartupFailed.make({
|
|
105
463
|
cause,
|
|
106
|
-
message: "Ignotum could not create the
|
|
464
|
+
message: "Ignotum could not create the managed development server.",
|
|
107
465
|
}),
|
|
108
466
|
}),
|
|
109
|
-
(server) =>
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
try: () => server.listen(),
|
|
116
|
-
catch: (cause) =>
|
|
117
|
-
ViteStartupFailed.make({
|
|
118
|
-
cause,
|
|
119
|
-
message: "Ignotum could not start the Vite development server.",
|
|
467
|
+
(server) =>
|
|
468
|
+
Effect.promise(async () => {
|
|
469
|
+
const closing = server.close();
|
|
470
|
+
await sync.api.dispose();
|
|
471
|
+
await closing;
|
|
472
|
+
await Promise.allSettled([work, serverWork]);
|
|
120
473
|
}),
|
|
121
|
-
|
|
474
|
+
);
|
|
475
|
+
return {
|
|
476
|
+
server,
|
|
477
|
+
selection: () => selection,
|
|
478
|
+
settled: () => work,
|
|
479
|
+
replacePlatform: (next: LocalManagedRelease) => {
|
|
480
|
+
const replace = async () => {
|
|
481
|
+
const nextSelection = Schema.decodeUnknownSync(ExecutionSelection)({
|
|
482
|
+
...localExecutionSelection(appDirectory, next),
|
|
483
|
+
platformGeneration: selection.platformGeneration + 1,
|
|
484
|
+
});
|
|
485
|
+
const nextTools = await runPromise(buildLocalBrowserTools(next, nextSelection));
|
|
486
|
+
const nextLoader = await runPromise(
|
|
487
|
+
createManagedFunctionLoader(appDirectory, {
|
|
488
|
+
guest: next.guest,
|
|
489
|
+
release: localPlatformRelease(next, nextSelection),
|
|
490
|
+
requirements: Schema.decodeUnknownSync(RuntimeRequirements)({
|
|
491
|
+
clientApiVersion: 1,
|
|
492
|
+
serverApiVersion: 1,
|
|
493
|
+
capabilities: ["operations", "routing", "images"],
|
|
494
|
+
}),
|
|
495
|
+
}),
|
|
496
|
+
);
|
|
497
|
+
const generated = await runPromise(generate(appDirectory));
|
|
498
|
+
const nextBuild = await runPromise(
|
|
499
|
+
buildManagedServer(
|
|
500
|
+
appDirectory,
|
|
501
|
+
path.join(appDirectory, ".ignotum/dev/server"),
|
|
502
|
+
generated.functionModules,
|
|
503
|
+
),
|
|
504
|
+
);
|
|
505
|
+
await runPromise(nextLoader.reload(nextBuild));
|
|
506
|
+
loader = nextLoader;
|
|
507
|
+
provider = next;
|
|
508
|
+
tools = nextTools;
|
|
509
|
+
selection = Schema.decodeUnknownSync(ExecutionSelection)(nextSelection);
|
|
510
|
+
serverDiagnostic = undefined;
|
|
511
|
+
server.environments.client.moduleGraph.invalidateAll();
|
|
512
|
+
// Managed sync checks the new selection even for sockets with no active queries.
|
|
513
|
+
await sync.api.invalidate();
|
|
514
|
+
};
|
|
515
|
+
const replacement = serverWork.then(replace, replace);
|
|
516
|
+
// A rejected candidate leaves the current platform available to subsequent loads.
|
|
517
|
+
serverWork = replacement.catch(() => {});
|
|
518
|
+
return replacement;
|
|
519
|
+
},
|
|
520
|
+
};
|
|
122
521
|
});
|
|
123
522
|
|
|
124
|
-
export const dev = Effect.fn("
|
|
125
|
-
const clientFiles = yield* validateClientFiles(options.appDirectory);
|
|
126
|
-
yield* generate(options.appDirectory);
|
|
127
|
-
|
|
523
|
+
export const dev = Effect.fn("ManagedDev.run")(function* (options: ManagedDevOptions) {
|
|
128
524
|
return yield* Effect.scoped(
|
|
129
525
|
Effect.gen(function* () {
|
|
130
|
-
yield*
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
526
|
+
const { server } = yield* acquireManagedDevServer(options);
|
|
527
|
+
yield* Effect.tryPromise({
|
|
528
|
+
try: () => server.listen(),
|
|
529
|
+
catch: (cause) =>
|
|
530
|
+
ViteStartupFailed.make({
|
|
531
|
+
cause,
|
|
532
|
+
message: "Ignotum could not start the development server.",
|
|
533
|
+
}),
|
|
137
534
|
});
|
|
535
|
+
server.printUrls();
|
|
536
|
+
server.bindCLIShortcuts({ print: true });
|
|
138
537
|
return yield* Effect.never;
|
|
139
538
|
}),
|
|
140
539
|
);
|