@xtrable-ltd/nanoesis 0.1.32 → 0.1.34
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/dist/adapter-azure-blob.d.ts +41 -6
- package/dist/adapter-azure-blob.js +74 -12
- package/dist/{chunk-6Y3I6SYT.js → chunk-C3QPGXG5.js} +7 -3
- package/dist/{chunk-D5G56CA4.js → chunk-P6NDWIKK.js} +12 -5
- package/dist/editor-api.d.ts +11 -5
- package/dist/editor-api.js +2 -2
- package/dist/index.d.ts +11 -0
- package/dist/index.js +1 -1
- package/dist/mcp.js +3 -3
- package/package.json +1 -1
|
@@ -23,11 +23,23 @@ interface BlobContainer {
|
|
|
23
23
|
/**
|
|
24
24
|
* Create or overwrite a blob with the given bytes and content type. `cacheControl`, when
|
|
25
25
|
* given, is stored as the blob's `Cache-Control` so a static-website read serves the right
|
|
26
|
-
* freshness (DESIGN §11); omitted for the editor's working blobs.
|
|
26
|
+
* freshness (DESIGN §11); omitted for the editor's working blobs. `hash`, when given, is
|
|
27
|
+
* stored as blob metadata (`nanohash`) so a later publish can tell whether the content is
|
|
28
|
+
* unchanged and skip the upload (see docs/change-detection-on-publish.md); a write *without*
|
|
29
|
+
* a `hash` clears any prior stored hash, matching Azure's overwrite-replaces-metadata
|
|
30
|
+
* semantics, so a stale hash can never outlive the bytes it described.
|
|
27
31
|
*/
|
|
28
|
-
write(name: string, data: Uint8Array, contentType: string, cacheControl?: string): Promise<void>;
|
|
32
|
+
write(name: string, data: Uint8Array, contentType: string, cacheControl?: string, hash?: string): Promise<void>;
|
|
29
33
|
/** Delete a blob; a missing blob is a no-op (idempotent). */
|
|
30
34
|
remove(name: string): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Every blob name beginning with `prefix` mapped to its stored content hash (the `nanohash`
|
|
37
|
+
* metadata, `undefined` for a blob written without one), for change detection on publish.
|
|
38
|
+
* Reads metadata from the same listing as {@link list} (one round trip, no blob bodies), so
|
|
39
|
+
* a host can diff a candidate artifact's hash against what is live and skip an unchanged
|
|
40
|
+
* upload. Sorted by name, like {@link list}, to keep any downstream walk deterministic.
|
|
41
|
+
*/
|
|
42
|
+
listWithHashes(prefix: string): Promise<ReadonlyMap<string, string | undefined>>;
|
|
31
43
|
/**
|
|
32
44
|
* A blob's bytes plus its current version tag (the Azure ETag), or null if absent. Pairs
|
|
33
45
|
* with {@link writeConditional} for the optimistic-concurrency the content index needs
|
|
@@ -53,6 +65,8 @@ interface BlobContainer {
|
|
|
53
65
|
declare class InMemoryBlobContainer implements BlobContainer {
|
|
54
66
|
private readonly blobs;
|
|
55
67
|
private readonly cacheControls;
|
|
68
|
+
/** Per-blob `nanohash` metadata, the in-memory stand-in for the real blob metadata. */
|
|
69
|
+
private readonly hashes;
|
|
56
70
|
/** Per-blob version, bumped on every write, the in-memory stand-in for an ETag. */
|
|
57
71
|
private readonly versions;
|
|
58
72
|
private nextVersion;
|
|
@@ -60,8 +74,9 @@ declare class InMemoryBlobContainer implements BlobContainer {
|
|
|
60
74
|
private store;
|
|
61
75
|
list(prefix: string): Promise<readonly string[]>;
|
|
62
76
|
read(name: string): Promise<Uint8Array | null>;
|
|
63
|
-
write(name: string, data: Uint8Array, contentType?: string, cacheControl?: string): Promise<void>;
|
|
77
|
+
write(name: string, data: Uint8Array, contentType?: string, cacheControl?: string, hash?: string): Promise<void>;
|
|
64
78
|
remove(name: string): Promise<void>;
|
|
79
|
+
listWithHashes(prefix: string): Promise<ReadonlyMap<string, string | undefined>>;
|
|
65
80
|
readVersioned(name: string): Promise<{
|
|
66
81
|
bytes: Uint8Array;
|
|
67
82
|
version: string;
|
|
@@ -71,6 +86,8 @@ declare class InMemoryBlobContainer implements BlobContainer {
|
|
|
71
86
|
get names(): readonly string[];
|
|
72
87
|
/** Test helper: the `Cache-Control` a blob was written with, if any. */
|
|
73
88
|
cacheControlOf(name: string): string | undefined;
|
|
89
|
+
/** Test helper: the `nanohash` metadata a blob was written with, if any. */
|
|
90
|
+
hashOf(name: string): string | undefined;
|
|
74
91
|
}
|
|
75
92
|
|
|
76
93
|
/**
|
|
@@ -88,8 +105,9 @@ declare class AzureBlobContainer implements BlobContainer {
|
|
|
88
105
|
/** Create the container if it does not exist (idempotent host start-up step). */
|
|
89
106
|
ensureContainer(): Promise<void>;
|
|
90
107
|
list(prefix: string): Promise<readonly string[]>;
|
|
108
|
+
listWithHashes(prefix: string): Promise<ReadonlyMap<string, string | undefined>>;
|
|
91
109
|
read(name: string): Promise<Uint8Array | null>;
|
|
92
|
-
write(name: string, data: Uint8Array, contentType: string, cacheControl?: string): Promise<void>;
|
|
110
|
+
write(name: string, data: Uint8Array, contentType: string, cacheControl?: string, hash?: string): Promise<void>;
|
|
93
111
|
remove(name: string): Promise<void>;
|
|
94
112
|
readVersioned(name: string): Promise<{
|
|
95
113
|
bytes: Uint8Array;
|
|
@@ -133,14 +151,31 @@ declare class BlobArtifactSink implements ArtifactSink {
|
|
|
133
151
|
write(path: string, contents: string | Uint8Array, cacheControl?: string): Promise<void>;
|
|
134
152
|
}
|
|
135
153
|
|
|
154
|
+
/** Options for {@link azureStorage}. */
|
|
155
|
+
interface AzureStorageOptions {
|
|
156
|
+
/**
|
|
157
|
+
* Skip re-uploading a blob whose content is byte-identical to what is already stored
|
|
158
|
+
* (docs/change-detection-on-publish.md). On every `put` the store hashes the bytes and
|
|
159
|
+
* compares against the live `nanohash` metadata (read once per publish, no blob bodies);
|
|
160
|
+
* an unchanged blob is not written, a changed/new one is written and re-stamped. Default
|
|
161
|
+
* **off**, so existing behaviour (always write) is unchanged. Enable it only on the
|
|
162
|
+
* **published** container, never the working store, whose conditional index writes must
|
|
163
|
+
* not be skipped.
|
|
164
|
+
*/
|
|
165
|
+
readonly changeDetection?: boolean;
|
|
166
|
+
}
|
|
136
167
|
/**
|
|
137
168
|
* A ready-made {@link Storage} over an Azure Blob container: get/put/delete (via
|
|
138
|
-
* {@link BlobContainerStore}) plus `wipe` (delete every blob)
|
|
169
|
+
* {@link BlobContainerStore}) plus `wipe` (delete every blob) and `prune` (delete every blob
|
|
170
|
+
* not in a keep set, the zero-downtime publish sweep). Pass it to `createEditor`
|
|
139
171
|
* as `editorFiles` (the working container) and `website` (the published `$web` container).
|
|
140
172
|
* For the working container, also pass `enumerate: () => container.list('')` so the editor
|
|
141
173
|
* can reconcile its content index.
|
|
174
|
+
*
|
|
175
|
+
* Pass `{ changeDetection: true }` on the **published** container to skip uploads of unchanged
|
|
176
|
+
* blobs (see {@link AzureStorageOptions.changeDetection}).
|
|
142
177
|
*/
|
|
143
|
-
declare function azureStorage(container: BlobContainer): Storage & ConditionalBlobStore;
|
|
178
|
+
declare function azureStorage(container: BlobContainer, options?: AzureStorageOptions): Storage & ConditionalBlobStore;
|
|
144
179
|
|
|
145
180
|
/**
|
|
146
181
|
* Pure path/name helper for the blob adapters. Blob storage is a *flat* namespace, a blob
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
+
contentHash,
|
|
2
3
|
contentTypeFor
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-P6NDWIKK.js";
|
|
4
5
|
|
|
5
6
|
// ../../adapters/azure-blob/src/container.ts
|
|
6
7
|
var InMemoryBlobContainer = class {
|
|
7
8
|
blobs = /* @__PURE__ */ new Map();
|
|
8
9
|
cacheControls = /* @__PURE__ */ new Map();
|
|
10
|
+
/** Per-blob `nanohash` metadata, the in-memory stand-in for the real blob metadata. */
|
|
11
|
+
hashes = /* @__PURE__ */ new Map();
|
|
9
12
|
/** Per-blob version, bumped on every write, the in-memory stand-in for an ETag. */
|
|
10
13
|
versions = /* @__PURE__ */ new Map();
|
|
11
14
|
nextVersion = 1;
|
|
@@ -31,14 +34,22 @@ var InMemoryBlobContainer = class {
|
|
|
31
34
|
async read(name) {
|
|
32
35
|
return this.blobs.get(name) ?? null;
|
|
33
36
|
}
|
|
34
|
-
async write(name, data, contentType, cacheControl) {
|
|
37
|
+
async write(name, data, contentType, cacheControl, hash) {
|
|
35
38
|
void contentType;
|
|
36
39
|
this.store(name, data);
|
|
37
40
|
if (cacheControl !== void 0) this.cacheControls.set(name, cacheControl);
|
|
41
|
+
if (hash !== void 0) this.hashes.set(name, hash);
|
|
42
|
+
else this.hashes.delete(name);
|
|
38
43
|
}
|
|
39
44
|
async remove(name) {
|
|
40
45
|
this.blobs.delete(name);
|
|
41
46
|
this.versions.delete(name);
|
|
47
|
+
this.hashes.delete(name);
|
|
48
|
+
}
|
|
49
|
+
async listWithHashes(prefix) {
|
|
50
|
+
const out = /* @__PURE__ */ new Map();
|
|
51
|
+
for (const name of await this.list(prefix)) out.set(name, this.hashes.get(name));
|
|
52
|
+
return out;
|
|
42
53
|
}
|
|
43
54
|
async readVersioned(name) {
|
|
44
55
|
const bytes = this.blobs.get(name);
|
|
@@ -60,6 +71,10 @@ var InMemoryBlobContainer = class {
|
|
|
60
71
|
cacheControlOf(name) {
|
|
61
72
|
return this.cacheControls.get(name);
|
|
62
73
|
}
|
|
74
|
+
/** Test helper: the `nanohash` metadata a blob was written with, if any. */
|
|
75
|
+
hashOf(name) {
|
|
76
|
+
return this.hashes.get(name);
|
|
77
|
+
}
|
|
63
78
|
};
|
|
64
79
|
|
|
65
80
|
// ../../adapters/azure-blob/src/azure-container.ts
|
|
@@ -95,6 +110,14 @@ var AzureBlobContainer = class _AzureBlobContainer {
|
|
|
95
110
|
}
|
|
96
111
|
return names.sort();
|
|
97
112
|
}
|
|
113
|
+
async listWithHashes(prefix) {
|
|
114
|
+
const entries = [];
|
|
115
|
+
for await (const blob of this.client.listBlobsFlat({ prefix, includeMetadata: true })) {
|
|
116
|
+
entries.push([blob.name, blob.metadata?.["nanohash"]]);
|
|
117
|
+
}
|
|
118
|
+
entries.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
119
|
+
return new Map(entries);
|
|
120
|
+
}
|
|
98
121
|
async read(name) {
|
|
99
122
|
try {
|
|
100
123
|
const buffer = await this.client.getBlockBlobClient(name).downloadToBuffer();
|
|
@@ -104,12 +127,16 @@ var AzureBlobContainer = class _AzureBlobContainer {
|
|
|
104
127
|
throw error;
|
|
105
128
|
}
|
|
106
129
|
}
|
|
107
|
-
async write(name, data, contentType, cacheControl) {
|
|
130
|
+
async write(name, data, contentType, cacheControl, hash) {
|
|
108
131
|
await this.client.getBlockBlobClient(name).uploadData(Buffer.from(data), {
|
|
109
132
|
blobHTTPHeaders: {
|
|
110
133
|
blobContentType: contentType,
|
|
111
134
|
...cacheControl !== void 0 && { blobCacheControl: cacheControl }
|
|
112
|
-
}
|
|
135
|
+
},
|
|
136
|
+
// Stamp the content hash as metadata for change detection on the next publish. Azure
|
|
137
|
+
// lowercases metadata keys, so the key is already lowercase. An upload with no `hash`
|
|
138
|
+
// omits metadata, which (since uploadData replaces the blob) clears any prior hash.
|
|
139
|
+
...hash !== void 0 && { metadata: { nanohash: hash } }
|
|
113
140
|
});
|
|
114
141
|
}
|
|
115
142
|
async remove(name) {
|
|
@@ -200,23 +227,58 @@ var BlobArtifactSink = class {
|
|
|
200
227
|
};
|
|
201
228
|
|
|
202
229
|
// ../../adapters/azure-blob/src/azure-storage.ts
|
|
203
|
-
function azureStorage(container) {
|
|
230
|
+
function azureStorage(container, options = {}) {
|
|
204
231
|
const store = new BlobContainerStore(container);
|
|
205
|
-
|
|
232
|
+
const wipe = async () => {
|
|
233
|
+
for (const name of await container.list("")) await container.remove(name);
|
|
234
|
+
};
|
|
235
|
+
const prune = async (keep) => {
|
|
236
|
+
for (const name of await container.list("")) {
|
|
237
|
+
if (!keep.has(name)) await container.remove(name);
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
const common = {
|
|
206
241
|
get: (key) => store.get(key),
|
|
207
|
-
// Forward `cacheControl` (DESIGN §11): this is the published-site sink `createEditor`
|
|
208
|
-
// actually wires (`asSink(azureStorage(website))`), so dropping the arg here silently
|
|
209
|
-
// strips the publish Cache-Control before it reaches the blob.
|
|
210
|
-
put: (key, bytes, cacheControl) => store.put(key, bytes, cacheControl),
|
|
211
242
|
delete: (key) => store.delete(key),
|
|
212
243
|
// Optimistic-concurrency capability (DESIGN §11d): surfaced so a horizontally-scaled
|
|
213
244
|
// host's IndexedStore compare-and-sets the content index instead of blind-overwriting
|
|
214
245
|
// it, which is what stops two instances losing each other's updates
|
|
215
246
|
// (NANOESIS-MCP-ISSUES Issue 1). Azure blobs back this with native ETag conditions.
|
|
216
247
|
getVersioned: (key) => store.getVersioned(key),
|
|
217
|
-
putConditional: (key, bytes, expected) => store.putConditional(key, bytes, expected)
|
|
248
|
+
putConditional: (key, bytes, expected) => store.putConditional(key, bytes, expected)
|
|
249
|
+
};
|
|
250
|
+
if (!options.changeDetection) {
|
|
251
|
+
return {
|
|
252
|
+
...common,
|
|
253
|
+
// Forward `cacheControl` (DESIGN §11): this is the published-site sink `createEditor`
|
|
254
|
+
// actually wires (`asSink(azureStorage(website))`), so dropping the arg here silently
|
|
255
|
+
// strips the publish Cache-Control before it reaches the blob.
|
|
256
|
+
put: (key, bytes, cacheControl) => store.put(key, bytes, cacheControl),
|
|
257
|
+
wipe,
|
|
258
|
+
prune
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
let live = null;
|
|
262
|
+
const reset = () => {
|
|
263
|
+
live = null;
|
|
264
|
+
};
|
|
265
|
+
return {
|
|
266
|
+
...common,
|
|
267
|
+
put: async (key, bytes, cacheControl) => {
|
|
268
|
+
if (live === null) live = new Map(await container.listWithHashes(""));
|
|
269
|
+
const name = normalizeBlobName(key);
|
|
270
|
+
const hash = contentHash(bytes);
|
|
271
|
+
if (live.get(name) === hash) return;
|
|
272
|
+
await container.write(name, bytes, contentTypeFor(name), cacheControl, hash);
|
|
273
|
+
live.set(name, hash);
|
|
274
|
+
},
|
|
218
275
|
wipe: async () => {
|
|
219
|
-
|
|
276
|
+
await wipe();
|
|
277
|
+
reset();
|
|
278
|
+
},
|
|
279
|
+
prune: async (keep) => {
|
|
280
|
+
await prune(keep);
|
|
281
|
+
reset();
|
|
220
282
|
}
|
|
221
283
|
};
|
|
222
284
|
}
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
renderReferenceMarkdown,
|
|
19
19
|
validateSite,
|
|
20
20
|
workingStoreRoundTripDiagnostic
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-P6NDWIKK.js";
|
|
22
22
|
|
|
23
23
|
// ../editor-api/src/scaffold.ts
|
|
24
24
|
var HOME_HTML = `<!doctype html>
|
|
@@ -949,12 +949,12 @@ function createEditor(config) {
|
|
|
949
949
|
};
|
|
950
950
|
try {
|
|
951
951
|
const validation = await validateSite(working);
|
|
952
|
-
if (validation.ok && wipeBeforePublish && config.website.wipe !== void 0) {
|
|
952
|
+
if (validation.ok && wipeBeforePublish && config.website.prune === void 0 && config.website.wipe !== void 0) {
|
|
953
953
|
await config.website.wipe();
|
|
954
954
|
}
|
|
955
955
|
const dir = config.users === void 0 ? void 0 : authorDirectory(await config.users());
|
|
956
956
|
const prebuild = typeof config.prebuild === "function" ? await config.prebuild() : config.prebuild;
|
|
957
|
-
|
|
957
|
+
const result = await publishSite(working, sink, {
|
|
958
958
|
...config.images !== void 0 && { imageEncoder: config.images },
|
|
959
959
|
...config.purge !== void 0 && { purge: config.purge },
|
|
960
960
|
...config.baseUrl !== void 0 && { baseUrl: config.baseUrl },
|
|
@@ -962,6 +962,10 @@ function createEditor(config) {
|
|
|
962
962
|
...prebuild !== void 0 && { prebuild },
|
|
963
963
|
onProgress: record
|
|
964
964
|
});
|
|
965
|
+
if (result.ok && wipeBeforePublish && config.website.prune !== void 0) {
|
|
966
|
+
await config.website.prune(new Set(result.written));
|
|
967
|
+
}
|
|
968
|
+
return result;
|
|
965
969
|
} finally {
|
|
966
970
|
progressRunning = false;
|
|
967
971
|
}
|
|
@@ -3319,13 +3319,20 @@ async function publishSite(source, sink, options = {}) {
|
|
|
3319
3319
|
);
|
|
3320
3320
|
const byPath = /* @__PURE__ */ new Map();
|
|
3321
3321
|
for (const artifact of [...stamped, ...passthrough]) byPath.set(artifact.path, artifact);
|
|
3322
|
+
const everything = [...byPath.values()];
|
|
3323
|
+
const pages = everything.filter((artifact) => artifact.path.endsWith(".html"));
|
|
3324
|
+
const resources = everything.filter((artifact) => !artifact.path.endsWith(".html"));
|
|
3322
3325
|
const uploadTotal = byPath.size;
|
|
3323
3326
|
let uploaded = 0;
|
|
3324
|
-
|
|
3325
|
-
await
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3327
|
+
const writeGroup = async (group) => {
|
|
3328
|
+
await mapWithConcurrency(group, writeConcurrency, async (artifact) => {
|
|
3329
|
+
await sink.write(artifact.path, artifact.contents, cacheControlFor(artifact));
|
|
3330
|
+
uploaded += 1;
|
|
3331
|
+
onProgress?.({ phase: "upload", written: uploaded, total: uploadTotal });
|
|
3332
|
+
});
|
|
3333
|
+
};
|
|
3334
|
+
await writeGroup(resources);
|
|
3335
|
+
await writeGroup(pages);
|
|
3329
3336
|
if (purge !== noopPurgeService) onProgress?.({ phase: "purge" });
|
|
3330
3337
|
await purge.purgeAll();
|
|
3331
3338
|
onProgress?.({ phase: "done", written: uploadTotal, summary });
|
package/dist/editor-api.d.ts
CHANGED
|
@@ -222,7 +222,12 @@ interface EditorConfig {
|
|
|
222
222
|
readonly prebuild?: PreBuildHook | (() => Promise<PreBuildHook | undefined>);
|
|
223
223
|
/** Admin diagnostics/self-heal; defaults to {@link buildDefaultDiagnostics}. */
|
|
224
224
|
readonly diagnostics?: DiagnosticRegistry;
|
|
225
|
-
/**
|
|
225
|
+
/**
|
|
226
|
+
* Whether a publish clears pages the new build no longer emits (default true). A
|
|
227
|
+
* `prune`-capable website does this as a post-publish orphan sweep (overwrite-in-place,
|
|
228
|
+
* zero downtime); a wipe-only website clears up front instead. Set false to never delete
|
|
229
|
+
* (overwrite-only, stale pages linger). Names `wipeBeforePublish` for back-compat.
|
|
230
|
+
*/
|
|
226
231
|
readonly wipeBeforePublish?: boolean;
|
|
227
232
|
}
|
|
228
233
|
/** A wired editor: mount {@link handleApi} at `/api/*` and call {@link publish} to go live. */
|
|
@@ -244,12 +249,13 @@ interface Editor {
|
|
|
244
249
|
* Wire a complete nanoesis editor from a storage pair, a login, and a few optional
|
|
245
250
|
* capabilities. This is the whole integration surface (DESIGN §11c): everything that used
|
|
246
251
|
* to be hand-assembled per host, the content index over the store, the publish source/sink,
|
|
247
|
-
* index reconcile, the
|
|
252
|
+
* index reconcile, the orphan sweep, and the {@link ApiDeps} bag, is built here, so
|
|
248
253
|
* internals (`IndexedStore`, `ArtifactSink`, reconcile plumbing) never reach the adopter.
|
|
249
254
|
*
|
|
250
|
-
* `publish()` validates **
|
|
251
|
-
*
|
|
252
|
-
*
|
|
255
|
+
* `publish()` validates **first**: an invalid site returns its errors and never touches the
|
|
256
|
+
* live files. A `prune`-capable website then overwrites every artifact in place and sweeps
|
|
257
|
+
* the orphans afterwards, so a publish never blanks the live site, not even for the upload
|
|
258
|
+
* window (the footgun the old "host wipes, then publishes" wiring carried).
|
|
253
259
|
*/
|
|
254
260
|
declare function createEditor(config: EditorConfig): Editor;
|
|
255
261
|
/**
|
package/dist/editor-api.js
CHANGED
|
@@ -21,8 +21,8 @@ import {
|
|
|
21
21
|
serveEditorAsset,
|
|
22
22
|
templateSnapshotIntegrityDiagnostic,
|
|
23
23
|
templateSuffixConflictDiagnostic
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-C3QPGXG5.js";
|
|
25
|
+
import "./chunk-P6NDWIKK.js";
|
|
26
26
|
export {
|
|
27
27
|
FileBrandingStore,
|
|
28
28
|
InMemoryBrandingStore,
|
package/dist/index.d.ts
CHANGED
|
@@ -204,6 +204,17 @@ interface Storage extends BlobStore {
|
|
|
204
204
|
* (and so cannot clear itself) omits it; the publish then only overwrites.
|
|
205
205
|
*/
|
|
206
206
|
wipe?(): Promise<void>;
|
|
207
|
+
/**
|
|
208
|
+
* Optional: delete every key **not** in `keep`, leaving the kept keys untouched. The
|
|
209
|
+
* zero-downtime alternative to {@link wipe} for a published website: the host overwrites
|
|
210
|
+
* every artifact in place (each key flips old→new atomically, so no URL is ever missing),
|
|
211
|
+
* then calls `prune` with the just-written path set to sweep only the orphans, pages that
|
|
212
|
+
* no longer exist. Unlike `wipe` (clear *before* the upload, blanking the live site for the
|
|
213
|
+
* whole write), `prune` runs *after* a successful upload and only removes what the new
|
|
214
|
+
* publish did not write. A store that cannot enumerate omits it; the host falls back to
|
|
215
|
+
* `wipe`, or to overwrite-only when neither is available.
|
|
216
|
+
*/
|
|
217
|
+
prune?(keep: ReadonlySet<string>): Promise<void>;
|
|
207
218
|
}
|
|
208
219
|
/**
|
|
209
220
|
* In-memory {@link BlobStore} backed by a plain map, the test double the engine's
|
package/dist/index.js
CHANGED
package/dist/mcp.js
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
MCP_TOOLS,
|
|
4
4
|
callMcpTool,
|
|
5
5
|
readMcpResource
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-C3QPGXG5.js";
|
|
7
|
+
import "./chunk-P6NDWIKK.js";
|
|
8
8
|
|
|
9
9
|
// ../../hosts/host-mcp/src/http.ts
|
|
10
10
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
@@ -56,7 +56,7 @@ function createMcpServer(deps, identity) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// ../../hosts/host-mcp/src/http.ts
|
|
59
|
-
var DEFAULT_VERSION = true ? "0.1.
|
|
59
|
+
var DEFAULT_VERSION = true ? "0.1.34" : "0.0.0-workspace";
|
|
60
60
|
async function handleMcpRequest(deps, request, opts) {
|
|
61
61
|
const server = createMcpServer(deps, {
|
|
62
62
|
name: opts?.name ?? "nanoesis",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xtrable-ltd/nanoesis",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.34",
|
|
4
4
|
"description": "nanoesis: a static-first publishing compiler. The engine, the mountable editor API, the storage/image/auth adapters, and the editor UI bundle, in one package (DESIGN 11c).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Xtrable Ltd",
|