ignotum 0.0.16 → 0.0.18
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 +13263 -2689
- package/dist/cli/bin.mjs.map +1 -1
- package/dist/platform/_headers +3 -0
- package/dist/platform/_ignotum/v1.0/client.js +12 -0
- package/dist/runtime/{api-B4fwp5a2.d.ts → api-BnUKx9cj-D49Tf0rX.d.ts} +4 -3
- package/dist/runtime/api-C-tltz6s.js +31 -0
- package/dist/runtime/api-C-tltz6s.js.map +1 -0
- package/dist/runtime/artifact-BB5qzoa6.js +42 -0
- package/dist/runtime/artifact-BB5qzoa6.js.map +1 -0
- package/dist/runtime/{bootstrap-BTFScKAc.d.ts → bootstrap-DjTwGJao-DBx5zdFI.d.ts} +64 -64
- package/dist/runtime/{bootstrap-BISQSn_O.js → bootstrap-DlNIfH-r.js} +9 -9
- package/dist/runtime/bootstrap-DlNIfH-r.js.map +1 -0
- package/dist/runtime/client.d.ts +24 -20
- package/dist/runtime/client.js +9 -9
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/id-BI08JkmR.d.ts +1 -0
- package/dist/runtime/{id--1m0NuUL.js → id-BrEnxY-r.js} +118 -53
- package/dist/runtime/id-BrEnxY-r.js.map +1 -0
- package/dist/runtime/{image-Djtjy4Z8.js → image-gofzZeCm.js} +2 -2
- package/dist/runtime/image-gofzZeCm.js.map +1 -0
- package/dist/runtime/{index-D4seNHlX.d.ts → index-Biaw5vdF.d.ts} +2 -2
- package/dist/runtime/internal/api.d.ts +1 -1
- package/dist/runtime/internal/api.js +1 -30
- package/dist/runtime/internal/bootstrap.d.ts +1 -1
- package/dist/runtime/internal/bootstrap.js +1 -1
- package/dist/runtime/internal/client.d.ts +2 -2
- package/dist/runtime/internal/client.js +4 -4
- package/dist/runtime/internal/client.js.map +1 -1
- package/dist/runtime/internal/host.d.ts +4 -4
- package/dist/runtime/internal/host.js +4 -4
- package/dist/runtime/internal/routes.d.ts +1 -1
- package/dist/runtime/internal/routes.js +1 -1
- package/dist/runtime/internal/server.d.ts +3 -2
- package/dist/runtime/internal/server.js +2 -2
- package/dist/runtime/internal/server.js.map +1 -1
- package/dist/runtime/internal/types.d.ts +2 -2
- package/dist/runtime/internal/types.js +1 -1
- package/dist/runtime/{pagination-D3qd6s9N.js → pagination--f4kMKf6.js} +2 -2
- package/dist/runtime/{pagination-D3qd6s9N.js.map → pagination--f4kMKf6.js.map} +1 -1
- package/dist/runtime/pagination-BI08JkmR.d.ts +1 -0
- package/dist/runtime/{router-BSBI1oN1.js → router-C1eC9yy5.js} +462 -419
- package/dist/runtime/router-C1eC9yy5.js.map +1 -0
- package/dist/runtime/routes-DnU39R7c.js +152 -0
- package/dist/runtime/routes-DnU39R7c.js.map +1 -0
- package/dist/runtime/{schema-D1wOqiNH.js → schema-BSjepoNF.js} +271 -6
- package/dist/runtime/schema-BSjepoNF.js.map +1 -0
- package/dist/runtime/server.d.ts +5 -4
- package/dist/runtime/server.js +3 -3
- package/dist/runtime/server.js.map +1 -1
- package/dist/runtime/{sync-DzUwA8W9.js → sync-BwgS19Xy.js} +4 -16
- package/dist/runtime/sync-BwgS19Xy.js.map +1 -0
- package/dist/runtime/{sync-D-GK2sv9.d.ts → sync-By2hX5ev.d.ts} +1 -2
- package/dist/runtime/{types-DeCCyqLU-BIm7rU-0.d.ts → types-DeCCyqLU-CHx7KFtx.d.ts} +2 -2
- package/package.json +7 -1
- package/src/cli/agent-files.ts +2 -0
- package/src/cli/build/asset-names.ts +190 -0
- package/src/cli/build/managed-client.ts +151 -81
- package/src/cli/build/managed-server.ts +4 -4
- package/src/cli/build/managed.ts +5 -6
- package/src/cli/command.ts +7 -15
- package/src/cli/control-client.ts +7 -9
- package/src/cli/deploy.ts +45 -15
- package/src/cli/dev.ts +50 -99
- package/src/cli/image-assets.ts +5 -2
- package/src/cli/managed-client-boundaries.ts +6 -6
- package/src/cli/managed-dev-platform.ts +52 -66
- package/src/cli/managed-exports.ts +5 -66
- package/src/cli/new-app.ts +7 -2
- package/src/cli/path.ts +11 -0
- package/src/cli/route-codegen.ts +2 -1
- package/src/cli/route-static.ts +3 -2
- package/src/cli/upload-journal.ts +130 -0
- package/src/client/bootstrap.ts +1 -110
- package/src/client/errors.ts +1 -70
- package/src/client/files.ts +1 -233
- package/src/client/hooks.ts +1 -367
- package/src/client/id.ts +1 -263
- package/src/client/image.ts +1 -28
- package/src/client/index.ts +1 -126
- package/src/client/jsx-dev-runtime.ts +1 -2
- package/src/client/jsx-runtime.ts +1 -2
- package/src/client/managed-client.ts +1 -729
- package/src/client/managed-upgrade.ts +1 -283
- package/src/client/page-observers.ts +1 -77
- package/src/client/query.ts +1 -17
- package/src/client/recovery-journal.ts +1 -195
- package/src/client/route-boundaries.ts +1 -184
- package/src/client/router-history.ts +1 -152
- package/src/client/router-store.ts +1 -644
- package/src/client/router.ts +1 -324
- package/src/client/routes.ts +1 -28
- package/src/client/sync.ts +1 -286
- package/src/dev-runtime/id.ts +1 -1
- package/src/dev-runtime/managed-functions.ts +10 -18
- package/src/dev-runtime/managed-sync.ts +16 -16
- package/src/dev-runtime/sync.ts +6 -4
- package/src/internal/api.ts +1 -156
- package/src/internal/client.ts +1 -186
- package/src/internal/host.ts +1 -1
- package/src/internal/http-paths.ts +1 -4
- package/src/internal/routes.ts +1 -45
- package/src/internal/server.ts +1 -3
- package/src/internal/types.ts +1 -2
- package/src/server/index.ts +1 -27
- package/dist/cli/managed-release-WHYLZwaS.mjs +0 -10902
- package/dist/cli/managed-release-WHYLZwaS.mjs.map +0 -1
- package/dist/cli/managed-release.d.mts +0 -1
- package/dist/cli/managed-release.mjs +0 -14
- package/dist/cli/managed-release.mjs.map +0 -1
- package/dist/runtime/bootstrap-BISQSn_O.js.map +0 -1
- package/dist/runtime/descriptor-CTY4mtwS-cS43EbwS.js +0 -269
- package/dist/runtime/descriptor-CTY4mtwS-cS43EbwS.js.map +0 -1
- package/dist/runtime/id--1m0NuUL.js.map +0 -1
- package/dist/runtime/id-CBOt2kDo.d.ts +0 -1
- package/dist/runtime/identity-QjtJRxBD.d.ts +0 -2
- package/dist/runtime/image-Djtjy4Z8.js.map +0 -1
- package/dist/runtime/internal/api.js.map +0 -1
- package/dist/runtime/pagination-CBOt2kDo.d.ts +0 -1
- package/dist/runtime/router-BSBI1oN1.js.map +0 -1
- package/dist/runtime/routes-Ce8TVP-T.js +0 -690
- package/dist/runtime/routes-Ce8TVP-T.js.map +0 -1
- package/dist/runtime/schema-D1wOqiNH.js.map +0 -1
- package/dist/runtime/sync-DzUwA8W9.js.map +0 -1
- package/src/cli/managed-release-bin.ts +0 -13
- package/src/cli/managed-release.ts +0 -260
package/src/cli/command.ts
CHANGED
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
} from "./auth-client.js";
|
|
15
15
|
import { ControlClient } from "./control-client.js";
|
|
16
16
|
import { deploy as runDeploy, resumeVersion } from "./deploy.js";
|
|
17
|
-
import { VersionId } from "@ignotum/contracts/runtime/identity";
|
|
18
17
|
import { resetDevDatabase } from "../dev-runtime/dev-database.js";
|
|
19
18
|
import { dev as runDev } from "./dev.js";
|
|
20
19
|
import { createApp } from "./new-app.js";
|
|
@@ -145,10 +144,9 @@ const dev = Command.make(
|
|
|
145
144
|
const deploy = Command.make(
|
|
146
145
|
"deploy",
|
|
147
146
|
{
|
|
148
|
-
resume: Flag.
|
|
149
|
-
Flag.withDescription("
|
|
150
|
-
Flag.
|
|
151
|
-
Flag.optional,
|
|
147
|
+
resume: Flag.boolean("resume").pipe(
|
|
148
|
+
Flag.withDescription("Resume the saved upload or activation."),
|
|
149
|
+
Flag.withDefault(false),
|
|
152
150
|
),
|
|
153
151
|
app: Flag.string("app").pipe(
|
|
154
152
|
Flag.withDescription("Create or link this app slug on the first deploy."),
|
|
@@ -159,12 +157,8 @@ const deploy = Command.make(
|
|
|
159
157
|
Effect.fn("deploy")(function* ({ app, resume }) {
|
|
160
158
|
const path = yield* Path.Path;
|
|
161
159
|
const terminal = yield* Terminal.Terminal;
|
|
162
|
-
if (
|
|
163
|
-
const result = yield* resumeVersion(
|
|
164
|
-
path.resolve("."),
|
|
165
|
-
resume.value,
|
|
166
|
-
Option.getOrUndefined(app),
|
|
167
|
-
).pipe(
|
|
160
|
+
if (resume) {
|
|
161
|
+
const result = yield* resumeVersion(path.resolve("."), Option.getOrUndefined(app)).pipe(
|
|
168
162
|
// @effect-diagnostics-next-line strictEffectProvide:off This command owns the authenticated control client.
|
|
169
163
|
Effect.provide(ControlClient.layer),
|
|
170
164
|
Effect.mapError((error) =>
|
|
@@ -172,7 +166,7 @@ const deploy = Command.make(
|
|
|
172
166
|
),
|
|
173
167
|
);
|
|
174
168
|
yield* terminal.display(
|
|
175
|
-
`Version ${result.versionNumber} is live.\n\nApp: ${result.appUrl}\
|
|
169
|
+
`Version ${result.versionNumber} is live.\n\nApp: ${result.appUrl}\n`,
|
|
176
170
|
);
|
|
177
171
|
return;
|
|
178
172
|
}
|
|
@@ -184,9 +178,7 @@ const deploy = Command.make(
|
|
|
184
178
|
),
|
|
185
179
|
);
|
|
186
180
|
|
|
187
|
-
yield* terminal.display(
|
|
188
|
-
`Version ${result.versionNumber} is live.\n\nApp: ${result.appUrl}\nVersion ID: ${result.versionId}\n`,
|
|
189
|
-
);
|
|
181
|
+
yield* terminal.display(`Version ${result.versionNumber} is live.\n\nApp: ${result.appUrl}\n`);
|
|
190
182
|
}),
|
|
191
183
|
).pipe(Command.withDescription("Build and deploy the application to Ignotum Cloud."));
|
|
192
184
|
|
|
@@ -23,8 +23,8 @@ import {
|
|
|
23
23
|
controlVersionPath,
|
|
24
24
|
} from "@ignotum/contracts/control";
|
|
25
25
|
import { UploadDeclaration } from "@ignotum/contracts/app-definition";
|
|
26
|
-
import {
|
|
27
|
-
import type { AppId, VersionId } from "@ignotum/contracts/runtime/identity";
|
|
26
|
+
import { ServingSelection } from "@ignotum/contracts/platform";
|
|
27
|
+
import type { AppId, VersionId, VersionNumber } from "@ignotum/contracts/runtime/identity";
|
|
28
28
|
import {
|
|
29
29
|
Config,
|
|
30
30
|
Context,
|
|
@@ -111,8 +111,8 @@ export interface VersionUploadFile {
|
|
|
111
111
|
interface ControlClientService {
|
|
112
112
|
readonly activateVersion: (
|
|
113
113
|
appId: AppId,
|
|
114
|
-
|
|
115
|
-
) => Effect.Effect<
|
|
114
|
+
number: VersionNumber,
|
|
115
|
+
) => Effect.Effect<ServingSelection, ControlApiError | ControlClientUnavailable>;
|
|
116
116
|
readonly beginVersion: (
|
|
117
117
|
appId: AppId,
|
|
118
118
|
versionId: VersionId,
|
|
@@ -329,13 +329,11 @@ export const controlClientLayer = Layer.effect(
|
|
|
329
329
|
|
|
330
330
|
const activateVersion = Effect.fn("ControlClient.activateVersion")(function* (
|
|
331
331
|
appId: AppId,
|
|
332
|
-
|
|
332
|
+
number: VersionNumber,
|
|
333
333
|
) {
|
|
334
334
|
return yield* executeIdempotent(
|
|
335
|
-
HttpClientRequest.post(
|
|
336
|
-
|
|
337
|
-
),
|
|
338
|
-
ExecutionSelection,
|
|
335
|
+
HttpClientRequest.post(endpoint(config.apiUrl, controlVersionActivatePath(appId, number))),
|
|
336
|
+
ServingSelection,
|
|
339
337
|
);
|
|
340
338
|
});
|
|
341
339
|
|
package/src/cli/deploy.ts
CHANGED
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
type VersionUploadFile,
|
|
12
12
|
} from "./control-client.js";
|
|
13
13
|
|
|
14
|
+
import { saveUpload, loadUpload, restoreUploadBuild, clearUpload } from "./upload-journal.js";
|
|
15
|
+
|
|
14
16
|
export class VersionUploadInterrupted extends Schema.TaggedError<VersionUploadInterrupted>()(
|
|
15
17
|
"VersionUploadInterrupted",
|
|
16
18
|
{ cause: Schema.Defect(), versionId: VersionId, message: Schema.String },
|
|
@@ -35,7 +37,7 @@ const activationError = (
|
|
|
35
37
|
cause,
|
|
36
38
|
versionId: version.id,
|
|
37
39
|
versionNumber: version.number,
|
|
38
|
-
message: `Version ${version.number}
|
|
40
|
+
message: `Version ${version.number} is ready, but activation could not be confirmed. Run ignotum deploy --resume to finish activation.`,
|
|
39
41
|
})
|
|
40
42
|
: cause;
|
|
41
43
|
|
|
@@ -45,7 +47,8 @@ const readyVersion = (version: ControlVersion) =>
|
|
|
45
47
|
: Effect.fail(
|
|
46
48
|
ControlClientUnavailable.make({
|
|
47
49
|
cause: { versionId: version.id, status: version.status },
|
|
48
|
-
message:
|
|
50
|
+
message:
|
|
51
|
+
"The saved upload is not ready for activation. Run ignotum deploy to start a new upload.",
|
|
49
52
|
}),
|
|
50
53
|
);
|
|
51
54
|
|
|
@@ -59,10 +62,22 @@ export const buildVersionArtifact = Effect.fn("Deploy.buildArtifact")(function*
|
|
|
59
62
|
export const uploadVersion = Effect.fn("Deploy.upload")(function* (
|
|
60
63
|
configuration: AppConfiguration,
|
|
61
64
|
build: ManagedVersionBuildResult,
|
|
65
|
+
savedVersionId?: VersionId,
|
|
62
66
|
) {
|
|
63
67
|
const control = yield* ControlClient;
|
|
64
|
-
const versionId = yield* (yield* IdGenerator).generate(VersionId);
|
|
65
|
-
const admission = yield* control
|
|
68
|
+
const versionId = savedVersionId ?? (yield* (yield* IdGenerator).generate(VersionId));
|
|
69
|
+
const admission = yield* control
|
|
70
|
+
.beginVersion(configuration.appId, versionId, build.declaration)
|
|
71
|
+
.pipe(
|
|
72
|
+
Effect.catchTags({
|
|
73
|
+
ControlClientUnavailable: (cause) =>
|
|
74
|
+
VersionUploadInterrupted.make({
|
|
75
|
+
cause,
|
|
76
|
+
versionId,
|
|
77
|
+
message: "Upload admission could not be confirmed. Run ignotum deploy --resume.",
|
|
78
|
+
}),
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
66
81
|
const files = yield* Effect.forEach(admission.targets, (target) => {
|
|
67
82
|
const publicArtifact = build.declaration.definition.artifacts.find(
|
|
68
83
|
(artifact) => artifact.path === target.path,
|
|
@@ -110,7 +125,7 @@ export const uploadVersion = Effect.fn("Deploy.upload")(function* (
|
|
|
110
125
|
VersionUploadInterrupted.make({
|
|
111
126
|
cause,
|
|
112
127
|
versionId,
|
|
113
|
-
message:
|
|
128
|
+
message: "Upload interrupted. Run ignotum deploy --resume.",
|
|
114
129
|
}),
|
|
115
130
|
}),
|
|
116
131
|
);
|
|
@@ -120,15 +135,15 @@ export const uploadVersion = Effect.fn("Deploy.upload")(function* (
|
|
|
120
135
|
VersionUploadInterrupted.make({
|
|
121
136
|
cause,
|
|
122
137
|
versionId,
|
|
123
|
-
message:
|
|
138
|
+
message: "Upload finalization could not be confirmed. Run ignotum deploy --resume.",
|
|
124
139
|
}),
|
|
125
140
|
}),
|
|
126
141
|
Effect.flatMap(readyVersion),
|
|
127
142
|
);
|
|
128
143
|
const selection = yield* control
|
|
129
|
-
.activateVersion(configuration.appId,
|
|
144
|
+
.activateVersion(configuration.appId, version.number)
|
|
130
145
|
.pipe(Effect.mapError((cause) => activationError(version, cause)));
|
|
131
|
-
if (selection.appId !== configuration.appId || selection.
|
|
146
|
+
if (selection.appId !== configuration.appId || selection.versionNumber !== version.number) {
|
|
132
147
|
return yield* activationError(
|
|
133
148
|
version,
|
|
134
149
|
ControlClientUnavailable.make({
|
|
@@ -146,24 +161,38 @@ export const deploy = Effect.fn("Deploy.run")(function* (
|
|
|
146
161
|
) {
|
|
147
162
|
const build = yield* buildVersionArtifact(appDirectory);
|
|
148
163
|
const configuration = yield* configureApp(appDirectory, requestedSlug);
|
|
149
|
-
const
|
|
164
|
+
const versionId = yield* (yield* IdGenerator).generate(VersionId);
|
|
165
|
+
yield* saveUpload(appDirectory, configuration, versionId, build);
|
|
166
|
+
const activated = yield* uploadVersion(configuration, build, versionId);
|
|
167
|
+
yield* clearUpload(appDirectory);
|
|
150
168
|
return { ...activated, appUrl: appUrl(configuration.slug) };
|
|
151
169
|
});
|
|
152
170
|
|
|
153
171
|
export const resumeVersion = Effect.fn("Deploy.resume")(function* (
|
|
154
172
|
appDirectory: string,
|
|
155
|
-
versionId: VersionId,
|
|
156
173
|
requestedSlug?: AppSlug,
|
|
157
174
|
) {
|
|
158
175
|
const configuration = yield* configureApp(appDirectory, requestedSlug);
|
|
159
176
|
const control = yield* ControlClient;
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
177
|
+
const journal = yield* loadUpload(appDirectory, configuration);
|
|
178
|
+
const versionId = journal.versionId;
|
|
179
|
+
const existing = yield* control.getVersion(configuration.appId, versionId).pipe(
|
|
180
|
+
Effect.catchTags({
|
|
181
|
+
ControlApiError: (error) =>
|
|
182
|
+
error.status === 404 ? Effect.succeed(undefined) : Effect.fail(error),
|
|
183
|
+
}),
|
|
184
|
+
);
|
|
185
|
+
if (existing === undefined || existing.status === "Uploading") {
|
|
186
|
+
const build = yield* restoreUploadBuild(appDirectory, journal);
|
|
187
|
+
const activated = yield* uploadVersion(configuration, build, versionId);
|
|
188
|
+
yield* clearUpload(appDirectory);
|
|
189
|
+
return { ...activated, appUrl: appUrl(configuration.slug) };
|
|
190
|
+
}
|
|
191
|
+
const version = yield* readyVersion(existing);
|
|
163
192
|
const selection = yield* control
|
|
164
|
-
.activateVersion(configuration.appId,
|
|
193
|
+
.activateVersion(configuration.appId, version.number)
|
|
165
194
|
.pipe(Effect.mapError((cause) => activationError(version, cause)));
|
|
166
|
-
if (selection.appId !== configuration.appId || selection.
|
|
195
|
+
if (selection.appId !== configuration.appId || selection.versionNumber !== version.number) {
|
|
167
196
|
return yield* activationError(
|
|
168
197
|
version,
|
|
169
198
|
ControlClientUnavailable.make({
|
|
@@ -172,6 +201,7 @@ export const resumeVersion = Effect.fn("Deploy.resume")(function* (
|
|
|
172
201
|
}),
|
|
173
202
|
);
|
|
174
203
|
}
|
|
204
|
+
yield* clearUpload(appDirectory);
|
|
175
205
|
return {
|
|
176
206
|
appUrl: appUrl(configuration.slug),
|
|
177
207
|
versionId,
|
package/src/cli/dev.ts
CHANGED
|
@@ -4,7 +4,11 @@ import tailwindcss from "@tailwindcss/vite";
|
|
|
4
4
|
import { Crypto, Effect, FileSystem, Option, Path, Schema, Scope } from "effect";
|
|
5
5
|
import { createServer, normalizePath, type Plugin, type ViteDevServer } from "vite";
|
|
6
6
|
import { ChildProcessSpawner } from "effect/unstable/process";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
PlatformRequirement,
|
|
9
|
+
revisionPrefix,
|
|
10
|
+
ServingSelection,
|
|
11
|
+
} from "@ignotum/contracts/deployment";
|
|
8
12
|
import { managedSelectionPath } from "@ignotum/contracts/managed-sync";
|
|
9
13
|
import { renderDocument } from "@ignotum/shared/document";
|
|
10
14
|
import { compilePatterns, matchLocation, resolveMetadata } from "@ignotum/shared/routing";
|
|
@@ -15,14 +19,14 @@ import { generateClientRoutes, type ClientRouteDiscovery } from "./route-codegen
|
|
|
15
19
|
import { createImageAssetsPlugin } from "./image-assets.js";
|
|
16
20
|
import { managedClientBoundariesPlugin } from "./managed-client-boundaries.js";
|
|
17
21
|
import { moduleBoundariesPlugin } from "./module-boundaries.js";
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
22
|
+
import { platformImportsPlugin } from "@ignotum/platform/compiler";
|
|
23
|
+
import { compilerExports } from "@ignotum/platform/compiler-exports";
|
|
20
24
|
import {
|
|
21
25
|
buildLocalBrowserTools,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
type
|
|
26
|
+
loadLocalPlatform,
|
|
27
|
+
localServingSelection,
|
|
28
|
+
localVersionId,
|
|
29
|
+
type LocalPlatform,
|
|
26
30
|
} from "./managed-dev-platform.js";
|
|
27
31
|
import { acquireDevDatabaseLock, devDatabasePath } from "../dev-runtime/dev-database.js";
|
|
28
32
|
import { ignotumManagedSyncPlugin } from "../dev-runtime/sync.js";
|
|
@@ -48,12 +52,10 @@ const toolingPrefix = "/_ignotum/development/tools/";
|
|
|
48
52
|
|
|
49
53
|
export interface ManagedDevOptions extends DevOptions {
|
|
50
54
|
readonly applicationName?: string;
|
|
51
|
-
readonly
|
|
52
|
-
readonly provider?: LocalManagedRelease;
|
|
55
|
+
readonly provider?: LocalPlatform;
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
export const renderDevRegistration = (discovery: ClientRouteDiscovery, applicationName: string) => `
|
|
56
|
-
import { mountClient } from "ignotum/internal/bootstrap";
|
|
57
59
|
import ${JSON.stringify(`${toolingPrefix}debug.js`)};
|
|
58
60
|
import ${JSON.stringify(stylesId)};
|
|
59
61
|
const registration = {
|
|
@@ -62,18 +64,12 @@ const registration = {
|
|
|
62
64
|
layouts: ${JSON.stringify(discovery.layouts)},
|
|
63
65
|
modules: new Map([${discovery.modules.map((module) => `[${JSON.stringify(module.id)}, { load: () => import(${JSON.stringify(`/@fs/${normalizePath(module.path)}`)}) }]`).join(",\n")}]),
|
|
64
66
|
};
|
|
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
67
|
if (import.meta.hot) {
|
|
73
|
-
import.meta.hot.accept()
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
import.meta.hot.accept((next) => {
|
|
69
|
+
window.dispatchEvent(new CustomEvent("ignotum:dev-registration", { detail: next.default }));
|
|
70
|
+
});
|
|
76
71
|
}
|
|
72
|
+
export default registration;
|
|
77
73
|
`;
|
|
78
74
|
|
|
79
75
|
/** Internal assembly until all CLI producers switch together. The caller owns its Effect scope. */
|
|
@@ -85,7 +81,6 @@ export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(fun
|
|
|
85
81
|
const appDirectory = yield* fs.realPath(options.appDirectory);
|
|
86
82
|
const appName = options.applicationName ?? path.basename(appDirectory);
|
|
87
83
|
const clientDirectory = path.join(appDirectory, "client");
|
|
88
|
-
const sdkDirectory = options.sdkDirectory ?? fileURLToPath(new URL("../../", import.meta.url));
|
|
89
84
|
const validateFiles = Effect.fn("ManagedDev.validateFiles")(function* () {
|
|
90
85
|
for (const publicPath of [
|
|
91
86
|
path.join(appDirectory, "public"),
|
|
@@ -114,9 +109,9 @@ export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(fun
|
|
|
114
109
|
let icon = yield* validateFiles();
|
|
115
110
|
let discovery = yield* generateClientRoutes(appDirectory);
|
|
116
111
|
let patterns = yield* compilePatterns(discovery.routes, discovery.layouts);
|
|
117
|
-
let provider = options.provider ?? (yield*
|
|
118
|
-
let selection =
|
|
119
|
-
let tools = yield* buildLocalBrowserTools(
|
|
112
|
+
let provider = options.provider ?? (yield* loadLocalPlatform());
|
|
113
|
+
let selection = localServingSelection(appDirectory);
|
|
114
|
+
let tools = yield* buildLocalBrowserTools();
|
|
120
115
|
const runPromise = Effect.runPromiseWith(
|
|
121
116
|
yield* Effect.context<
|
|
122
117
|
| FileSystem.FileSystem
|
|
@@ -133,48 +128,14 @@ export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(fun
|
|
|
133
128
|
let work = Promise.resolve();
|
|
134
129
|
const images = yield* createImageAssetsPlugin(appDirectory);
|
|
135
130
|
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
|
-
};
|
|
131
|
+
const platform = yield* managedClientBoundariesPlugin(appDirectory, true);
|
|
167
132
|
const databasePath = yield* devDatabasePath(appDirectory);
|
|
168
133
|
yield* fs.makeDirectory(path.dirname(databasePath), { recursive: true });
|
|
169
134
|
yield* acquireDevDatabaseLock(appDirectory);
|
|
170
135
|
let loader = yield* createManagedFunctionLoader(appDirectory, {
|
|
171
136
|
guest: provider.guest,
|
|
172
|
-
|
|
173
|
-
requirements: Schema.decodeUnknownSync(
|
|
174
|
-
clientApiVersion: 1,
|
|
175
|
-
serverApiVersion: 1,
|
|
176
|
-
capabilities: ["operations", "routing", "images"],
|
|
177
|
-
}),
|
|
137
|
+
platform: selection.platform,
|
|
138
|
+
requirements: Schema.decodeUnknownSync(PlatformRequirement)({ major: 1, minimumMinor: 0 }),
|
|
178
139
|
});
|
|
179
140
|
const compileServer = Effect.fn("ManagedDev.compileServer")(function* () {
|
|
180
141
|
const generated = yield* generate(appDirectory);
|
|
@@ -188,6 +149,7 @@ export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(fun
|
|
|
188
149
|
yield* compileServer();
|
|
189
150
|
const sync = ignotumManagedSyncPlugin(appDirectory, databasePath, {
|
|
190
151
|
selection: () => selection,
|
|
152
|
+
versionId: localVersionId(appDirectory),
|
|
191
153
|
isServerDependency: (file) => {
|
|
192
154
|
const relative = normalizePath(path.relative(appDirectory, file));
|
|
193
155
|
return (
|
|
@@ -232,7 +194,7 @@ export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(fun
|
|
|
232
194
|
id: `${toolingPrefix}${id.slice("@prefresh/".length)}.js`,
|
|
233
195
|
external: true as const,
|
|
234
196
|
};
|
|
235
|
-
if (id.startsWith(toolingPrefix) || id.startsWith("/_ignotum/
|
|
197
|
+
if (id.startsWith(toolingPrefix) || id.startsWith("/_ignotum/v"))
|
|
236
198
|
return { id, external: true as const };
|
|
237
199
|
},
|
|
238
200
|
load(id) {
|
|
@@ -247,11 +209,7 @@ export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(fun
|
|
|
247
209
|
// Prefresh adds optimizer entries. Its tools are already compiled against the managed renderer.
|
|
248
210
|
config.optimizeDeps.include = [];
|
|
249
211
|
config.optimizeDeps.noDiscovery = true;
|
|
250
|
-
config.optimizeDeps.exclude = [
|
|
251
|
-
...managedBrowserExports.map((entry) => entry.specifier),
|
|
252
|
-
"@prefresh/core",
|
|
253
|
-
"@prefresh/utils",
|
|
254
|
-
];
|
|
212
|
+
config.optimizeDeps.exclude = ["ignotum/platform", "@prefresh/core", "@prefresh/utils"];
|
|
255
213
|
},
|
|
256
214
|
configureServer(server) {
|
|
257
215
|
viteServer = server;
|
|
@@ -335,17 +293,9 @@ export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(fun
|
|
|
335
293
|
send(JSON.stringify({ protocolVersion: 1, selection }), "application/json");
|
|
336
294
|
return;
|
|
337
295
|
}
|
|
338
|
-
const
|
|
339
|
-
if (url.pathname
|
|
340
|
-
|
|
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);
|
|
296
|
+
const browserEntry = `${revisionPrefix(selection.platform)}/client.js`;
|
|
297
|
+
if (url.pathname === browserEntry) {
|
|
298
|
+
send(provider.browser, "text/javascript", true);
|
|
349
299
|
return;
|
|
350
300
|
}
|
|
351
301
|
if (url.pathname.startsWith(toolingPrefix)) {
|
|
@@ -392,20 +342,21 @@ export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(fun
|
|
|
392
342
|
outcome: outcome._tag,
|
|
393
343
|
}),
|
|
394
344
|
);
|
|
395
|
-
const
|
|
396
|
-
Object.entries(provider.browser.manifest.entries).map(([specifier, module]) => [
|
|
397
|
-
specifier,
|
|
398
|
-
localPlatformUrl(selection.platformReleaseId, module),
|
|
399
|
-
]),
|
|
400
|
-
);
|
|
345
|
+
const browserEntry = `${revisionPrefix(selection.platform)}/client.js`;
|
|
401
346
|
const html = renderDocument({
|
|
402
347
|
metadata,
|
|
403
348
|
selection,
|
|
404
|
-
importMap: {
|
|
405
|
-
|
|
349
|
+
importMap: {
|
|
350
|
+
imports: {
|
|
351
|
+
"ignotum/platform": browserEntry,
|
|
352
|
+
"/@id/ignotum/platform": browserEntry,
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
browserEntry,
|
|
406
356
|
registration: { module: moduleUrl(registrationId), exportName: "default" },
|
|
407
357
|
styles: [],
|
|
408
358
|
icon: icon?.url,
|
|
359
|
+
development: true,
|
|
409
360
|
});
|
|
410
361
|
response.statusCode =
|
|
411
362
|
outcome._tag === "NotFound" ? 404 : outcome._tag === "Invalid" ? 400 : 200;
|
|
@@ -433,7 +384,7 @@ export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(fun
|
|
|
433
384
|
images.plugin,
|
|
434
385
|
boundaries,
|
|
435
386
|
platform,
|
|
436
|
-
|
|
387
|
+
platformImportsPlugin(compilerExports),
|
|
437
388
|
sync,
|
|
438
389
|
await prefresh(),
|
|
439
390
|
tailwindcss(),
|
|
@@ -476,21 +427,21 @@ export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(fun
|
|
|
476
427
|
server,
|
|
477
428
|
selection: () => selection,
|
|
478
429
|
settled: () => work,
|
|
479
|
-
replacePlatform: (next:
|
|
430
|
+
replacePlatform: (next: LocalPlatform) => {
|
|
480
431
|
const replace = async () => {
|
|
481
|
-
const nextSelection =
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
432
|
+
const nextSelection = localServingSelection(
|
|
433
|
+
appDirectory,
|
|
434
|
+
selection.deploymentEpoch + 1,
|
|
435
|
+
selection.activationGeneration + 1,
|
|
436
|
+
);
|
|
437
|
+
const nextTools = await runPromise(buildLocalBrowserTools());
|
|
486
438
|
const nextLoader = await runPromise(
|
|
487
439
|
createManagedFunctionLoader(appDirectory, {
|
|
488
440
|
guest: next.guest,
|
|
489
|
-
|
|
490
|
-
requirements: Schema.decodeUnknownSync(
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
capabilities: ["operations", "routing", "images"],
|
|
441
|
+
platform: nextSelection.platform,
|
|
442
|
+
requirements: Schema.decodeUnknownSync(PlatformRequirement)({
|
|
443
|
+
major: 1,
|
|
444
|
+
minimumMinor: 0,
|
|
494
445
|
}),
|
|
495
446
|
}),
|
|
496
447
|
);
|
|
@@ -506,7 +457,7 @@ export const acquireManagedDevServer = Effect.fn("ManagedDev.acquireServer")(fun
|
|
|
506
457
|
loader = nextLoader;
|
|
507
458
|
provider = next;
|
|
508
459
|
tools = nextTools;
|
|
509
|
-
selection = Schema.decodeUnknownSync(
|
|
460
|
+
selection = Schema.decodeUnknownSync(ServingSelection)(nextSelection);
|
|
510
461
|
serverDiagnostic = undefined;
|
|
511
462
|
server.environments.client.moduleGraph.invalidateAll();
|
|
512
463
|
// Managed sync checks the new selection even for sockets with no active queries.
|
package/src/cli/image-assets.ts
CHANGED
|
@@ -8,7 +8,6 @@ import { normalizePath } from "vite";
|
|
|
8
8
|
import type { Plugin, ResolvedConfig, ViteDevServer } from "vite";
|
|
9
9
|
|
|
10
10
|
const imageModulePrefix = "\0ignotum:image:";
|
|
11
|
-
const assetUrlPrefix = "/_ignotum/";
|
|
12
11
|
const imageModuleId = (sourcePath: string): string =>
|
|
13
12
|
`${imageModulePrefix}${encodeURIComponent(normalizePath(sourcePath))}.js`;
|
|
14
13
|
|
|
@@ -147,7 +146,9 @@ const cssImageNodes = (parsed: ReturnType<typeof valueParser>): ReadonlyArray<va
|
|
|
147
146
|
|
|
148
147
|
export const createImageAssetsPlugin = Effect.fn("Deploy.createImageAssetsPlugin")(function* (
|
|
149
148
|
appDirectory: string,
|
|
149
|
+
deployment = false,
|
|
150
150
|
) {
|
|
151
|
+
const assetUrlPrefix = deployment ? "/_ignotum/assets/" : "/_ignotum/";
|
|
151
152
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
152
153
|
const path = yield* Path.Path;
|
|
153
154
|
const runPromise = Effect.runPromiseWith(yield* Effect.context<Crypto.Crypto>());
|
|
@@ -267,7 +268,9 @@ export const createImageAssetsPlugin = Effect.fn("Deploy.createImageAssetsPlugin
|
|
|
267
268
|
|
|
268
269
|
const digest = yield* sha256(bytes);
|
|
269
270
|
const format = imageFormats[extension];
|
|
270
|
-
const artifactPath =
|
|
271
|
+
const artifactPath = deployment
|
|
272
|
+
? `media/${path.basename(absolutePath, path.extname(absolutePath)).replace(/[^a-zA-Z0-9.-]/g, "_")}-${digest}.${format.canonicalExtension}`
|
|
273
|
+
: `assets/${digest}/image.${format.canonicalExtension}`;
|
|
271
274
|
let asset = assets.get(artifactPath);
|
|
272
275
|
if (asset === undefined) {
|
|
273
276
|
asset = {
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { Effect, FileSystem, Path, Schema } from "effect";
|
|
2
2
|
import { normalizePath, type Plugin } from "vite";
|
|
3
|
-
import {
|
|
3
|
+
import { compilerExports } from "@ignotum/platform/compiler-exports";
|
|
4
4
|
import { InvalidBuildOutput } from "./build/artifact.js";
|
|
5
5
|
|
|
6
6
|
const PackageMetadata = Schema.Struct({ name: Schema.optional(Schema.String) });
|
|
7
7
|
const externals = new Set<string>(
|
|
8
|
-
|
|
9
|
-
.filter((entry) => entry.specifier.startsWith("ignotum/"))
|
|
10
|
-
.map((entry) => entry.specifier),
|
|
8
|
+
Object.keys(compilerExports).filter((specifier) => specifier.startsWith("ignotum/")),
|
|
11
9
|
);
|
|
12
10
|
|
|
13
11
|
/** Resolve before workspace conditions or package aliases can embed SDK implementation. */
|
|
14
12
|
export const managedClientBoundariesPlugin = Effect.fn("Deploy.managedClientBoundariesPlugin")(
|
|
15
|
-
function* (appDirectory: string) {
|
|
13
|
+
function* (appDirectory: string, sharedImports = false) {
|
|
16
14
|
const fs = yield* FileSystem.FileSystem;
|
|
17
15
|
const path = yield* Path.Path;
|
|
18
16
|
const runPromise = Effect.runPromiseWith(yield* Effect.context<never>());
|
|
@@ -70,7 +68,9 @@ export const managedClientBoundariesPlugin = Effect.fn("Deploy.managedClientBoun
|
|
|
70
68
|
message: `Managed client module '${importer ?? "<entry>"}' imports unsupported platform entry '${specifier}'. Compiler-owned entries must come from generated bindings.`,
|
|
71
69
|
});
|
|
72
70
|
}
|
|
73
|
-
if (externals.has(specifier))
|
|
71
|
+
if (externals.has(specifier))
|
|
72
|
+
return sharedImports ? undefined : { id: specifier, external: true };
|
|
73
|
+
if (sharedImports && specifier === "ignotum/platform") return;
|
|
74
74
|
if (
|
|
75
75
|
specifier === "ignotum" ||
|
|
76
76
|
specifier.startsWith("ignotum/") ||
|