@cervio/plugin-core 0.1.1 → 1.0.0

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/index.cjs DELETED
@@ -1,549 +0,0 @@
1
- 'use strict';
2
-
3
- var zod = require('zod');
4
- var JSZip = require('jszip');
5
- var crypto = require('crypto');
6
- var fs = require('fs');
7
- var path = require('path');
8
-
9
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
-
11
- var JSZip__default = /*#__PURE__*/_interopDefault(JSZip);
12
- var path__default = /*#__PURE__*/_interopDefault(path);
13
-
14
- // src/types.ts
15
- var PLUGIN_ARTIFACT_BUCKET = "plugin-artifacts";
16
- var MAX_PLUGIN_ZIP_BYTES = 50 * 1024 * 1024;
17
- var MAX_PLUGIN_ZIP_ENTRIES = 5e3;
18
- var MAX_PLUGIN_UNCOMPRESSED_BYTES = 250 * 1024 * 1024;
19
- var PLUGIN_KEY_RE = /^[a-z0-9][a-z0-9-_]{1,62}$/;
20
- var PLUGIN_VERSION_SELECT = "id, plugin_id, version, changelog, artifact_path, artifact_entry_path, artifact_sha256, content_sha256, artifact_size_bytes, created_at, deleted_at, deleted_by";
21
- var DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES = ["calendar"];
22
-
23
- // src/entity-requirements.ts
24
- var ENTITY_NAME_RE = /^[a-z][a-z0-9_-]{0,62}$/i;
25
- var FIELD_NAME_RE = /^[a-z][a-z0-9_]{0,62}$/i;
26
- var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "*"]);
27
- function asStringArray(raw, nameRe) {
28
- if (!Array.isArray(raw)) return [];
29
- const out = [];
30
- const seen = /* @__PURE__ */ new Set();
31
- for (const item of raw) {
32
- if (typeof item !== "string") continue;
33
- const v = item.trim();
34
- if (!v || !nameRe.test(v) || seen.has(v)) continue;
35
- seen.add(v);
36
- out.push(v);
37
- }
38
- return out;
39
- }
40
- function parseAccess(raw) {
41
- if (!Array.isArray(raw)) return ["read"];
42
- const out = [];
43
- for (const item of raw) {
44
- if (item === "read" || item === "write") {
45
- if (!out.includes(item)) out.push(item);
46
- }
47
- }
48
- return out.length ? out : ["read"];
49
- }
50
- function parsePluginEntityRequirements(raw) {
51
- if (!Array.isArray(raw)) return [];
52
- const out = [];
53
- const seen = /* @__PURE__ */ new Set();
54
- for (const item of raw) {
55
- if (!item || typeof item !== "object") continue;
56
- const row = item;
57
- const name = typeof row.name === "string" ? row.name.trim() : "";
58
- if (!name || !ENTITY_NAME_RE.test(name) || seen.has(name.toLowerCase())) continue;
59
- seen.add(name.toLowerCase());
60
- out.push({
61
- name,
62
- fields: asStringArray(row.fields, FIELD_NAME_RE),
63
- forms: asStringArray(row.forms, FIELD_NAME_RE),
64
- access: parseAccess(row.access)
65
- });
66
- }
67
- return out;
68
- }
69
- function parsePluginCervioApiRequirements(raw) {
70
- if (!Array.isArray(raw)) return [];
71
- const out = [];
72
- const seen = /* @__PURE__ */ new Set();
73
- for (const item of raw) {
74
- if (!item || typeof item !== "object") continue;
75
- const row = item;
76
- const methodRaw = typeof row.method === "string" ? row.method.trim().toUpperCase() : "GET";
77
- const method = HTTP_METHODS.has(methodRaw) ? methodRaw : "GET";
78
- const path2 = typeof row.path_prefix === "string" ? row.path_prefix.trim() : typeof row.pathPrefix === "string" ? row.pathPrefix.trim() : "";
79
- if (!path2 || !path2.startsWith("/")) continue;
80
- const key = `${method}:${path2}`;
81
- if (seen.has(key)) continue;
82
- seen.add(key);
83
- out.push({ method, path_prefix: path2 });
84
- }
85
- return out;
86
- }
87
-
88
- // src/connections.ts
89
- var EXTERNAL_CONNECTION_ALLOWED_HOSTS = {
90
- microsoft: ["graph.microsoft.com"],
91
- google: ["googleapis.com", "www.googleapis.com"]
92
- };
93
- var EXTERNAL_CONNECTION_HTTP_METHODS = [
94
- "GET",
95
- "POST",
96
- "PATCH",
97
- "PUT",
98
- "DELETE"
99
- ];
100
- var CONNECTION_ID_RE = /^[a-z0-9][a-z0-9-_]{0,62}$/;
101
- var OAUTH_PROVIDER_KEY_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/;
102
- var MAX_SCOPES = 32;
103
- var MAX_ALLOWED_APIS = 24;
104
- var MAX_SCOPE_LEN = 200;
105
- var BLOCKED_HOST_SUFFIXES = [".localhost", ".local", ".internal", ".home", ".lan"];
106
- function normalizeExactApiHost(raw) {
107
- const host = raw.trim().toLowerCase().replace(/\.$/, "");
108
- if (!host || host.length > 253 || host.includes("/") || host.includes(":") || host.includes("*") || host === "localhost" || BLOCKED_HOST_SUFFIXES.some((suffix) => host.endsWith(suffix))) {
109
- return null;
110
- }
111
- if (!/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(
112
- host
113
- )) {
114
- return null;
115
- }
116
- if (/^\d{1,3}(\.\d{1,3}){3}$/.test(host)) return null;
117
- return host;
118
- }
119
- function isExternalConnectionProvider(v) {
120
- return OAUTH_PROVIDER_KEY_RE.test(v);
121
- }
122
- function parseAllowedApi(raw, provider) {
123
- if (!raw || typeof raw !== "object") return null;
124
- const o = raw;
125
- const host = typeof o.host === "string" ? o.host.trim().toLowerCase() : "";
126
- const pathPrefix = typeof o.path_prefix === "string" ? o.path_prefix.trim() : typeof o.pathPrefix === "string" ? o.pathPrefix.trim() : "";
127
- const methodsRaw = o.methods;
128
- if (!host || !pathPrefix || !normalizeExactApiHost(host)) return null;
129
- const builtinHosts = EXTERNAL_CONNECTION_ALLOWED_HOSTS[provider];
130
- if (builtinHosts && !builtinHosts.includes(host)) return null;
131
- if (!pathPrefix.startsWith("/") || pathPrefix.includes("..") || pathPrefix.includes("\\")) {
132
- return null;
133
- }
134
- if (!Array.isArray(methodsRaw) || methodsRaw.length === 0) return null;
135
- const methods = [];
136
- for (const m of methodsRaw) {
137
- if (typeof m !== "string") return null;
138
- const up = m.trim().toUpperCase();
139
- if (!EXTERNAL_CONNECTION_HTTP_METHODS.includes(up)) return null;
140
- if (!methods.includes(up)) {
141
- methods.push(up);
142
- }
143
- }
144
- if (!methods.length) return null;
145
- return { host, methods, path_prefix: pathPrefix };
146
- }
147
- function parsePluginConnections(raw) {
148
- if (!Array.isArray(raw)) return [];
149
- const out = [];
150
- const seen = /* @__PURE__ */ new Set();
151
- for (const item of raw) {
152
- if (!item || typeof item !== "object") continue;
153
- const o = item;
154
- const id = typeof o.id === "string" ? o.id.trim().toLowerCase() : "";
155
- if (!id || !CONNECTION_ID_RE.test(id) || seen.has(id)) continue;
156
- const providerRaw = typeof o.provider === "string" ? o.provider.trim().toLowerCase() : "";
157
- if (!isExternalConnectionProvider(providerRaw)) continue;
158
- const scopesRaw = o.scopes;
159
- if (!Array.isArray(scopesRaw) || scopesRaw.length === 0 || scopesRaw.length > MAX_SCOPES) continue;
160
- const scopes = [];
161
- for (const s of scopesRaw) {
162
- if (typeof s !== "string") continue;
163
- const t = s.trim();
164
- if (!t || t.length > MAX_SCOPE_LEN) continue;
165
- if (!scopes.includes(t)) scopes.push(t);
166
- }
167
- if (!scopes.length) continue;
168
- const apisRaw = o.allowed_apis ?? o.allowedApis;
169
- if (!Array.isArray(apisRaw) || apisRaw.length === 0 || apisRaw.length > MAX_ALLOWED_APIS) continue;
170
- const allowed_apis = [];
171
- for (const a of apisRaw) {
172
- const rule = parseAllowedApi(a, providerRaw);
173
- if (rule) allowed_apis.push(rule);
174
- }
175
- if (!allowed_apis.length) continue;
176
- seen.add(id);
177
- out.push({
178
- id,
179
- provider: providerRaw,
180
- consent: "user",
181
- scopes,
182
- allowed_apis
183
- });
184
- }
185
- return out;
186
- }
187
-
188
- // src/zip-safety.ts
189
- function assertZipSafe(zip) {
190
- const names = Object.keys(zip.files);
191
- if (names.length > MAX_PLUGIN_ZIP_ENTRIES) {
192
- return { ok: false, error: "zip_too_many_entries" };
193
- }
194
- let totalUncompressed = 0;
195
- for (const name of names) {
196
- if (name.includes("..") || name.includes("\\") || name.startsWith("/")) {
197
- return { ok: false, error: "zip_unsafe_entry_path" };
198
- }
199
- const entry = zip.files[name];
200
- totalUncompressed += entry._data?.uncompressedSize ?? 0;
201
- if (totalUncompressed > MAX_PLUGIN_UNCOMPRESSED_BYTES) {
202
- return { ok: false, error: "zip_uncompressed_too_large" };
203
- }
204
- }
205
- return { ok: true, value: true };
206
- }
207
- function assertZipFile(file) {
208
- const name = (file.name ?? "upload.zip").toLowerCase();
209
- if (!name.endsWith(".zip")) return { ok: false, error: "invalid_file_extension" };
210
- if (file.size <= 0) return { ok: false, error: "empty_file" };
211
- if (file.size > MAX_PLUGIN_ZIP_BYTES) return { ok: false, error: "file_too_large" };
212
- return { ok: true, value: true };
213
- }
214
-
215
- // src/semver.ts
216
- var CORE_SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)/;
217
- function nextPatchVersion(latest) {
218
- if (!latest || typeof latest !== "string") return "0.1.0";
219
- const m = latest.trim().match(CORE_SEMVER_RE);
220
- if (!m) return "0.1.0";
221
- const major = Number(m[1]);
222
- const minor = Number(m[2]);
223
- const patch = Number(m[3]);
224
- if (![major, minor, patch].every((n) => Number.isFinite(n) && n >= 0)) return "0.1.0";
225
- return `${major}.${minor}.${patch + 1}`;
226
- }
227
- function compareSemverDesc(a, b) {
228
- const pa = a.match(CORE_SEMVER_RE);
229
- const pb = b.match(CORE_SEMVER_RE);
230
- if (!pa && !pb) return 0;
231
- if (!pa) return 1;
232
- if (!pb) return -1;
233
- for (let i = 1; i <= 3; i++) {
234
- const da = Number(pa[i]) - Number(pb[i]);
235
- if (da !== 0) return da > 0 ? -1 : 1;
236
- }
237
- return 0;
238
- }
239
- var pluginManifestZodSchema = zod.z.object({
240
- plugin_key: zod.z.string().regex(/^[a-z0-9][a-z0-9-_]{1,62}$/).optional().describe("Stable plugin id. Prefer this over legacy `id`."),
241
- id: zod.z.string().optional().describe("Legacy alias for plugin_key (slashes become dashes)."),
242
- plugin_name: zod.z.string().optional(),
243
- name: zod.z.string().optional().describe("Legacy alias for plugin_name."),
244
- plugin_type: zod.z.enum(["task", "form", "task_form", "route"]).optional(),
245
- kind: zod.z.string().optional().describe("Legacy alias for plugin_type (task_widget\u2192task, record_panel\u2192form)."),
246
- version: zod.z.string().optional().describe("Ignored by Cervio \u2014 the host assigns release versions."),
247
- required_connection_capabilities: zod.z.array(zod.z.string()).optional(),
248
- requiredConnectionCapabilities: zod.z.array(zod.z.string()).optional(),
249
- connections: zod.z.array(
250
- zod.z.object({
251
- id: zod.z.string(),
252
- provider: zod.z.string(),
253
- scopes: zod.z.array(zod.z.string()),
254
- allowed_apis: zod.z.array(
255
- zod.z.object({
256
- host: zod.z.string(),
257
- methods: zod.z.array(zod.z.string()),
258
- path_prefix: zod.z.string().optional(),
259
- pathPrefix: zod.z.string().optional()
260
- })
261
- ).optional(),
262
- allowedApis: zod.z.array(zod.z.unknown()).optional()
263
- })
264
- ).optional(),
265
- entities: zod.z.array(
266
- zod.z.object({
267
- name: zod.z.string(),
268
- fields: zod.z.array(zod.z.string()).optional(),
269
- forms: zod.z.array(zod.z.string()).optional(),
270
- access: zod.z.array(zod.z.enum(["read", "write"])).optional()
271
- })
272
- ).optional(),
273
- cervio_apis: zod.z.array(
274
- zod.z.object({
275
- method: zod.z.string().optional(),
276
- path_prefix: zod.z.string().optional(),
277
- pathPrefix: zod.z.string().optional()
278
- })
279
- ).optional(),
280
- cervioApis: zod.z.array(zod.z.unknown()).optional()
281
- }).passthrough();
282
- function normalizePluginKey(raw) {
283
- return raw.trim().toLowerCase().replace(/[\/\s]+/g, "-").replace(/[^a-z0-9-_]/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
284
- }
285
- function resolvePluginType(raw) {
286
- const kindMap = {
287
- route: "route",
288
- task: "task",
289
- form: "form",
290
- task_form: "task_form",
291
- task_widget: "task",
292
- record_panel: "form"
293
- };
294
- const candidate = kindMap[raw] ?? raw;
295
- return ["task", "form", "task_form", "route"].includes(candidate) ? candidate : null;
296
- }
297
- function parseRequiredCapabilities(raw, allowed) {
298
- if (!Array.isArray(raw)) return [];
299
- const allowedSet = new Set(allowed);
300
- const out = [];
301
- const seen = /* @__PURE__ */ new Set();
302
- for (const item of raw) {
303
- if (typeof item !== "string") continue;
304
- const id = item.trim().toLowerCase();
305
- if (!id || !allowedSet.has(id) || seen.has(id)) continue;
306
- seen.add(id);
307
- out.push(id);
308
- }
309
- return out;
310
- }
311
- function parseManifestObject(parsed, options) {
312
- const allowedCapabilities = options?.allowedCapabilities ?? DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES;
313
- const pluginKeyRaw = typeof parsed.plugin_key === "string" ? parsed.plugin_key : typeof parsed.id === "string" ? parsed.id.split("/").filter(Boolean).join("-") : "";
314
- const pluginKey = normalizePluginKey(pluginKeyRaw);
315
- if (!pluginKey || !PLUGIN_KEY_RE.test(pluginKey)) {
316
- return { ok: false, error: "manifest_plugin_key_invalid" };
317
- }
318
- const pluginName = typeof parsed.plugin_name === "string" && parsed.plugin_name.trim() ? parsed.plugin_name.trim() : typeof parsed.name === "string" && parsed.name.trim() ? parsed.name.trim() : null;
319
- const pluginTypeRaw = typeof parsed.plugin_type === "string" ? parsed.plugin_type.trim() : typeof parsed.kind === "string" ? parsed.kind.trim() : "";
320
- const pluginType = resolvePluginType(pluginTypeRaw);
321
- const manifestVersion = typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null;
322
- const requiredRaw = parsed.required_connection_capabilities ?? parsed.requiredConnectionCapabilities ?? [];
323
- const requiredConnectionCapabilities = parseRequiredCapabilities(
324
- requiredRaw,
325
- allowedCapabilities
326
- );
327
- const connections = parsePluginConnections(parsed.connections);
328
- const entities = parsePluginEntityRequirements(parsed.entities);
329
- const cervioApis = parsePluginCervioApiRequirements(
330
- parsed.cervio_apis ?? parsed.cervioApis ?? []
331
- );
332
- return {
333
- ok: true,
334
- value: {
335
- pluginKey,
336
- pluginName,
337
- pluginType,
338
- manifestVersion,
339
- requiredConnectionCapabilities,
340
- connections,
341
- entities,
342
- cervioApis
343
- }
344
- };
345
- }
346
- function manifestJsonForContentHash(raw) {
347
- const clone = { ...raw };
348
- delete clone.version;
349
- return JSON.stringify(clone);
350
- }
351
- async function loadZipFromBuffer(buffer) {
352
- try {
353
- const zip = await JSZip__default.default.loadAsync(buffer);
354
- const safe = assertZipSafe(zip);
355
- if (!safe.ok) return safe;
356
- return { ok: true, value: zip };
357
- } catch {
358
- return { ok: false, error: "zip_invalid" };
359
- }
360
- }
361
- async function parseZipManifest(file, options) {
362
- const buffer = await file.arrayBuffer();
363
- const zipRes = await loadZipFromBuffer(buffer);
364
- if (!zipRes.ok) return zipRes;
365
- const zip = zipRes.value;
366
- const manifestEntry = zip.file("manifest.json") ?? zip.file("manifest.example.json") ?? Object.values(zip.files).find(
367
- (f) => f.name.endsWith("/manifest.json") || f.name.endsWith("/manifest.example.json")
368
- );
369
- if (!manifestEntry) return { ok: false, error: "manifest_not_found_in_zip" };
370
- const jsonText = await manifestEntry.async("text");
371
- let parsed;
372
- try {
373
- parsed = JSON.parse(jsonText);
374
- } catch {
375
- return { ok: false, error: "manifest_invalid_json" };
376
- }
377
- const fields = parseManifestObject(parsed, options);
378
- if (!fields.ok) return fields;
379
- const hasDistIndex = !!zip.file("dist/index.html");
380
- if (!hasDistIndex) return { ok: false, error: "build_index_missing" };
381
- const hasDistAssets = Object.keys(zip.files).some((name) => /^dist\/assets\/.+/.test(name));
382
- if (!hasDistAssets) return { ok: false, error: "build_assets_missing" };
383
- return {
384
- ok: true,
385
- value: {
386
- ...fields.value,
387
- artifactEntryPath: "dist/index.html",
388
- rawManifest: parsed,
389
- manifestEntryName: manifestEntry.name
390
- }
391
- };
392
- }
393
- async function computePluginContentSha256(zip, rawManifest) {
394
- try {
395
- const hash = crypto.createHash("sha256");
396
- hash.update("manifest\0");
397
- hash.update(manifestJsonForContentHash(rawManifest));
398
- hash.update("\0");
399
- const distPaths = Object.keys(zip.files).filter((name) => {
400
- const entry = zip.files[name];
401
- if (!entry || entry.dir) return false;
402
- const normalized = name.replace(/^\.\//, "");
403
- return normalized === "dist" || normalized.startsWith("dist/");
404
- }).map((name) => name.replace(/^\.\//, "")).sort((a, b) => a.localeCompare(b));
405
- for (const path2 of distPaths) {
406
- const entry = zip.file(path2);
407
- if (!entry || entry.dir) continue;
408
- const bytes = await entry.async("uint8array");
409
- hash.update("file\0");
410
- hash.update(path2);
411
- hash.update("\0");
412
- hash.update(bytes);
413
- hash.update("\0");
414
- }
415
- return { ok: true, value: hash.digest("hex") };
416
- } catch {
417
- return { ok: false, error: "content_hash_failed" };
418
- }
419
- }
420
- function sha256Hex(buffer) {
421
- return crypto.createHash("sha256").update(buffer).digest("hex");
422
- }
423
- async function collectFiles(dir, base = "") {
424
- const entries = await fs.promises.readdir(dir, { withFileTypes: true });
425
- const out = [];
426
- for (const entry of entries) {
427
- const abs = path__default.default.join(dir, entry.name);
428
- const rel = base ? `${base}/${entry.name}` : entry.name;
429
- if (entry.isDirectory()) {
430
- out.push(...await collectFiles(abs, rel));
431
- } else if (entry.isFile()) {
432
- out.push({ rel: rel.replace(/\\/g, "/"), abs });
433
- }
434
- }
435
- return out;
436
- }
437
- async function packPlugin(opts) {
438
- const root = path__default.default.resolve(opts.dir);
439
- const manifestPath = path__default.default.join(root, "manifest.json");
440
- let manifestRaw;
441
- try {
442
- const text = await fs.promises.readFile(manifestPath, "utf8");
443
- manifestRaw = JSON.parse(text);
444
- } catch {
445
- return { ok: false, error: "manifest_not_found_in_zip" };
446
- }
447
- const fields = parseManifestObject(manifestRaw, opts.options);
448
- if (!fields.ok) return fields;
449
- const distIndex = path__default.default.join(root, "dist", "index.html");
450
- try {
451
- await fs.promises.access(distIndex);
452
- } catch {
453
- return { ok: false, error: "build_index_missing" };
454
- }
455
- const zip = new JSZip__default.default();
456
- const files = await collectFiles(root);
457
- let hasAssets = false;
458
- for (const file of files) {
459
- if (file.rel.startsWith(".cervio/") || file.rel === "node_modules" || file.rel.startsWith("node_modules/")) {
460
- continue;
461
- }
462
- if (file.rel.startsWith("dist/assets/") && file.rel !== "dist/assets/") {
463
- hasAssets = true;
464
- }
465
- const data = await fs.promises.readFile(file.abs);
466
- zip.file(file.rel, data);
467
- }
468
- if (!hasAssets) return { ok: false, error: "build_assets_missing" };
469
- const safe = assertZipSafe(zip);
470
- if (!safe.ok) return safe;
471
- const buffer = Buffer.from(await zip.generateAsync({ type: "uint8array", compression: "DEFLATE" }));
472
- const fileCheck = assertZipFile({ name: `${fields.value.pluginKey}.zip`, size: buffer.length });
473
- if (!fileCheck.ok) return fileCheck;
474
- const loaded = await loadZipFromBuffer(buffer);
475
- if (!loaded.ok) return loaded;
476
- const hash = await computePluginContentSha256(loaded.value, manifestRaw);
477
- if (!hash.ok) return hash;
478
- return {
479
- ok: true,
480
- value: {
481
- buffer,
482
- pluginKey: fields.value.pluginKey,
483
- contentSha256: hash.value,
484
- sizeBytes: buffer.length
485
- }
486
- };
487
- }
488
- async function validatePluginDir(dir, options) {
489
- const packed = await packPlugin({ dir, options });
490
- if (!packed.ok) return packed;
491
- const blob = new Blob([packed.value.buffer], { type: "application/zip" });
492
- const parsed = await parseZipManifest(blob, options);
493
- if (!parsed.ok) return parsed;
494
- return {
495
- ok: true,
496
- value: {
497
- pluginKey: packed.value.pluginKey,
498
- contentSha256: packed.value.contentSha256
499
- }
500
- };
501
- }
502
- async function validatePluginZipBuffer(buffer, options) {
503
- const fileCheck = assertZipFile({ name: "plugin.zip", size: buffer.length });
504
- if (!fileCheck.ok) return fileCheck;
505
- const blob = new Blob([buffer], { type: "application/zip" });
506
- const parsed = await parseZipManifest(blob, options);
507
- if (!parsed.ok) return parsed;
508
- const zipRes = await loadZipFromBuffer(buffer);
509
- if (!zipRes.ok) return zipRes;
510
- const hash = await computePluginContentSha256(zipRes.value, parsed.value.rawManifest);
511
- if (!hash.ok) return hash;
512
- return {
513
- ok: true,
514
- value: { pluginKey: parsed.value.pluginKey, contentSha256: hash.value }
515
- };
516
- }
517
-
518
- exports.DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES = DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES;
519
- exports.EXTERNAL_CONNECTION_ALLOWED_HOSTS = EXTERNAL_CONNECTION_ALLOWED_HOSTS;
520
- exports.EXTERNAL_CONNECTION_HTTP_METHODS = EXTERNAL_CONNECTION_HTTP_METHODS;
521
- exports.MAX_PLUGIN_UNCOMPRESSED_BYTES = MAX_PLUGIN_UNCOMPRESSED_BYTES;
522
- exports.MAX_PLUGIN_ZIP_BYTES = MAX_PLUGIN_ZIP_BYTES;
523
- exports.MAX_PLUGIN_ZIP_ENTRIES = MAX_PLUGIN_ZIP_ENTRIES;
524
- exports.OAUTH_PROVIDER_KEY_RE = OAUTH_PROVIDER_KEY_RE;
525
- exports.PLUGIN_ARTIFACT_BUCKET = PLUGIN_ARTIFACT_BUCKET;
526
- exports.PLUGIN_KEY_RE = PLUGIN_KEY_RE;
527
- exports.PLUGIN_VERSION_SELECT = PLUGIN_VERSION_SELECT;
528
- exports.assertZipFile = assertZipFile;
529
- exports.assertZipSafe = assertZipSafe;
530
- exports.compareSemverDesc = compareSemverDesc;
531
- exports.computePluginContentSha256 = computePluginContentSha256;
532
- exports.isExternalConnectionProvider = isExternalConnectionProvider;
533
- exports.loadZipFromBuffer = loadZipFromBuffer;
534
- exports.manifestJsonForContentHash = manifestJsonForContentHash;
535
- exports.nextPatchVersion = nextPatchVersion;
536
- exports.normalizeExactApiHost = normalizeExactApiHost;
537
- exports.normalizePluginKey = normalizePluginKey;
538
- exports.packPlugin = packPlugin;
539
- exports.parseManifestObject = parseManifestObject;
540
- exports.parsePluginCervioApiRequirements = parsePluginCervioApiRequirements;
541
- exports.parsePluginConnections = parsePluginConnections;
542
- exports.parsePluginEntityRequirements = parsePluginEntityRequirements;
543
- exports.parseZipManifest = parseZipManifest;
544
- exports.pluginManifestZodSchema = pluginManifestZodSchema;
545
- exports.sha256Hex = sha256Hex;
546
- exports.validatePluginDir = validatePluginDir;
547
- exports.validatePluginZipBuffer = validatePluginZipBuffer;
548
- //# sourceMappingURL=index.cjs.map
549
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/types.ts","../src/entity-requirements.ts","../src/connections.ts","../src/zip-safety.ts","../src/semver.ts","../src/manifest-schema.ts","../src/manifest.ts","../src/content-hash.ts","../src/pack.ts"],"names":["path","z","JSZip","createHash","fs"],"mappings":"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","file":"index.cjs","sourcesContent":["export type PluginType = 'task' | 'form' | 'task_form' | 'route'\n\nexport type PluginActionResult<T> = { ok: true; value: T } | { ok: false; error: string }\n\nexport interface PluginVersionRow {\n id: string\n plugin_id: string\n version: string\n changelog: string | null\n artifact_path: string | null\n artifact_entry_path?: string | null\n artifact_sha256: string | null\n content_sha256?: string | null\n artifact_size_bytes: number | null\n created_at: string\n /** Soft-delete timestamp; when set the row is history-only (strikethrough in Admin). */\n deleted_at?: string | null\n deleted_by?: string | null\n}\n\nexport interface ParsedPluginManifest {\n pluginKey: string\n pluginName: string | null\n pluginType: PluginType | null\n /** Present in ZIP but ignored for assignment; Cervio owns release versions. */\n manifestVersion: string | null\n /** Catalog capability ids the plugin needs (e.g. calendar). */\n requiredConnectionCapabilities: string[]\n /** External Connections requirements (OAuth broker). */\n connections: PluginConnectionRequirement[]\n /** Declared Cervio entity deps (name-based; for Admin + future export). */\n entities: PluginEntityRequirement[]\n /** Declared Cervio API path prefixes (documentation / future allowlist). */\n cervioApis: PluginCervioApiRequirement[]\n artifactEntryPath: string\n rawManifest: Record<string, unknown>\n manifestEntryName: string\n}\n\nexport type PluginEntityAccess = 'read' | 'write'\n\nexport type PluginEntityRequirement = {\n name: string\n fields: string[]\n forms: string[]\n access: PluginEntityAccess[]\n}\n\nexport type PluginCervioApiRequirement = {\n method: string\n path_prefix: string\n}\n\nexport type ExternalConnectionHttpMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'\n\nexport type AllowedApiRule = {\n host: string\n methods: ExternalConnectionHttpMethod[]\n path_prefix: string\n}\n\nexport type PluginConnectionRequirement = {\n id: string\n provider: string\n consent: 'user'\n scopes: string[]\n allowed_apis: AllowedApiRule[]\n}\n\nexport type ParseManifestOptions = {\n /**\n * Capability ids a plugin may declare in `required_connection_capabilities`.\n * Host passes the live catalog; CLI uses {@link DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES}.\n */\n allowedCapabilities?: readonly string[]\n}\n\nexport const PLUGIN_ARTIFACT_BUCKET = 'plugin-artifacts'\nexport const MAX_PLUGIN_ZIP_BYTES = 50 * 1024 * 1024\nexport const MAX_PLUGIN_ZIP_ENTRIES = 5000\nexport const MAX_PLUGIN_UNCOMPRESSED_BYTES = 250 * 1024 * 1024\nexport const PLUGIN_KEY_RE = /^[a-z0-9][a-z0-9-_]{1,62}$/\n\nexport const PLUGIN_VERSION_SELECT =\n 'id, plugin_id, version, changelog, artifact_path, artifact_entry_path, artifact_sha256, content_sha256, artifact_size_bytes, created_at, deleted_at, deleted_by'\n\n/**\n * Static default for CLI validate. Generated from host `CONNECTION_CAPABILITY_CATALOG`\n * where `pluginDeclarable === true`. Guarded by drift test against the host catalog.\n */\nexport const DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES = ['calendar'] as const\n","import type {\n PluginCervioApiRequirement,\n PluginEntityAccess,\n PluginEntityRequirement,\n} from './types.js'\n\nconst ENTITY_NAME_RE = /^[a-z][a-z0-9_-]{0,62}$/i\nconst FIELD_NAME_RE = /^[a-z][a-z0-9_]{0,62}$/i\nconst HTTP_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', '*'])\n\nfunction asStringArray(raw: unknown, nameRe: RegExp): string[] {\n if (!Array.isArray(raw)) return []\n const out: string[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (typeof item !== 'string') continue\n const v = item.trim()\n if (!v || !nameRe.test(v) || seen.has(v)) continue\n seen.add(v)\n out.push(v)\n }\n return out\n}\n\nfunction parseAccess(raw: unknown): PluginEntityAccess[] {\n if (!Array.isArray(raw)) return ['read']\n const out: PluginEntityAccess[] = []\n for (const item of raw) {\n if (item === 'read' || item === 'write') {\n if (!out.includes(item)) out.push(item)\n }\n }\n return out.length ? out : ['read']\n}\n\n/** Parse `entities` from manifest.json (invalid entries skipped). */\nexport function parsePluginEntityRequirements(raw: unknown): PluginEntityRequirement[] {\n if (!Array.isArray(raw)) return []\n const out: PluginEntityRequirement[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const row = item as Record<string, unknown>\n const name = typeof row.name === 'string' ? row.name.trim() : ''\n if (!name || !ENTITY_NAME_RE.test(name) || seen.has(name.toLowerCase())) continue\n seen.add(name.toLowerCase())\n out.push({\n name,\n fields: asStringArray(row.fields, FIELD_NAME_RE),\n forms: asStringArray(row.forms, FIELD_NAME_RE),\n access: parseAccess(row.access),\n })\n }\n return out\n}\n\n/** Parse `cervio_apis` from manifest.json. */\nexport function parsePluginCervioApiRequirements(raw: unknown): PluginCervioApiRequirement[] {\n if (!Array.isArray(raw)) return []\n const out: PluginCervioApiRequirement[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const row = item as Record<string, unknown>\n const methodRaw = typeof row.method === 'string' ? row.method.trim().toUpperCase() : 'GET'\n const method = HTTP_METHODS.has(methodRaw) ? methodRaw : 'GET'\n const path =\n typeof row.path_prefix === 'string'\n ? row.path_prefix.trim()\n : typeof row.pathPrefix === 'string'\n ? row.pathPrefix.trim()\n : ''\n if (!path || !path.startsWith('/')) continue\n const key = `${method}:${path}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push({ method, path_prefix: path })\n }\n return out\n}\n","import type {\n AllowedApiRule,\n ExternalConnectionHttpMethod,\n PluginConnectionRequirement,\n} from './types.js'\n\nexport const EXTERNAL_CONNECTION_ALLOWED_HOSTS: Record<string, readonly string[]> = {\n microsoft: ['graph.microsoft.com'],\n google: ['googleapis.com', 'www.googleapis.com'],\n}\n\nexport const EXTERNAL_CONNECTION_HTTP_METHODS = [\n 'GET',\n 'POST',\n 'PATCH',\n 'PUT',\n 'DELETE',\n] as const\n\nconst CONNECTION_ID_RE = /^[a-z0-9][a-z0-9-_]{0,62}$/\nexport const OAUTH_PROVIDER_KEY_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/\nconst MAX_SCOPES = 32\nconst MAX_ALLOWED_APIS = 24\nconst MAX_SCOPE_LEN = 200\n\nconst BLOCKED_HOST_SUFFIXES = ['.localhost', '.local', '.internal', '.home', '.lan']\n\n/** Lightweight host check (no DNS); mirrors host `normalizeExactApiHost` shape rules. */\nexport function normalizeExactApiHost(raw: string): string | null {\n const host = raw.trim().toLowerCase().replace(/\\.$/, '')\n if (\n !host ||\n host.length > 253 ||\n host.includes('/') ||\n host.includes(':') ||\n host.includes('*') ||\n host === 'localhost' ||\n BLOCKED_HOST_SUFFIXES.some((suffix) => host.endsWith(suffix))\n ) {\n return null\n }\n if (\n !/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(\n host,\n )\n ) {\n return null\n }\n if (/^\\d{1,3}(\\.\\d{1,3}){3}$/.test(host)) return null\n return host\n}\n\nexport function isExternalConnectionProvider(v: string): boolean {\n return OAUTH_PROVIDER_KEY_RE.test(v)\n}\n\nfunction parseAllowedApi(raw: unknown, provider: string): AllowedApiRule | null {\n if (!raw || typeof raw !== 'object') return null\n const o = raw as Record<string, unknown>\n const host = typeof o.host === 'string' ? o.host.trim().toLowerCase() : ''\n const pathPrefix =\n typeof o.path_prefix === 'string'\n ? o.path_prefix.trim()\n : typeof o.pathPrefix === 'string'\n ? o.pathPrefix.trim()\n : ''\n const methodsRaw = o.methods\n if (!host || !pathPrefix || !normalizeExactApiHost(host)) return null\n const builtinHosts = EXTERNAL_CONNECTION_ALLOWED_HOSTS[provider]\n if (builtinHosts && !builtinHosts.includes(host)) return null\n if (!pathPrefix.startsWith('/') || pathPrefix.includes('..') || pathPrefix.includes('\\\\')) {\n return null\n }\n if (!Array.isArray(methodsRaw) || methodsRaw.length === 0) return null\n const methods: ExternalConnectionHttpMethod[] = []\n for (const m of methodsRaw) {\n if (typeof m !== 'string') return null\n const up = m.trim().toUpperCase()\n if (!(EXTERNAL_CONNECTION_HTTP_METHODS as readonly string[]).includes(up)) return null\n if (!methods.includes(up as ExternalConnectionHttpMethod)) {\n methods.push(up as ExternalConnectionHttpMethod)\n }\n }\n if (!methods.length) return null\n return { host, methods, path_prefix: pathPrefix }\n}\n\n/** Parse manifest `connections` array; drops invalid entries. */\nexport function parsePluginConnections(raw: unknown): PluginConnectionRequirement[] {\n if (!Array.isArray(raw)) return []\n const out: PluginConnectionRequirement[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const o = item as Record<string, unknown>\n const id = typeof o.id === 'string' ? o.id.trim().toLowerCase() : ''\n if (!id || !CONNECTION_ID_RE.test(id) || seen.has(id)) continue\n const providerRaw = typeof o.provider === 'string' ? o.provider.trim().toLowerCase() : ''\n if (!isExternalConnectionProvider(providerRaw)) continue\n const scopesRaw = o.scopes\n if (!Array.isArray(scopesRaw) || scopesRaw.length === 0 || scopesRaw.length > MAX_SCOPES) continue\n const scopes: string[] = []\n for (const s of scopesRaw) {\n if (typeof s !== 'string') continue\n const t = s.trim()\n if (!t || t.length > MAX_SCOPE_LEN) continue\n if (!scopes.includes(t)) scopes.push(t)\n }\n if (!scopes.length) continue\n const apisRaw = o.allowed_apis ?? o.allowedApis\n if (!Array.isArray(apisRaw) || apisRaw.length === 0 || apisRaw.length > MAX_ALLOWED_APIS) continue\n const allowed_apis: AllowedApiRule[] = []\n for (const a of apisRaw) {\n const rule = parseAllowedApi(a, providerRaw)\n if (rule) allowed_apis.push(rule)\n }\n if (!allowed_apis.length) continue\n seen.add(id)\n out.push({\n id,\n provider: providerRaw,\n consent: 'user',\n scopes,\n allowed_apis,\n })\n }\n return out\n}\n","import type JSZip from 'jszip'\nimport {\n MAX_PLUGIN_UNCOMPRESSED_BYTES,\n MAX_PLUGIN_ZIP_BYTES,\n MAX_PLUGIN_ZIP_ENTRIES,\n type PluginActionResult,\n} from './types.js'\n\n/**\n * Validates a loaded plugin ZIP before any entry is inflated (CERVIO-SEC-014):\n * caps the entry count and total declared uncompressed size to stop zip bombs,\n * and rejects path-traversal / absolute entry names as defense-in-depth.\n */\nexport function assertZipSafe(zip: JSZip): PluginActionResult<true> {\n const names = Object.keys(zip.files)\n if (names.length > MAX_PLUGIN_ZIP_ENTRIES) {\n return { ok: false, error: 'zip_too_many_entries' }\n }\n let totalUncompressed = 0\n for (const name of names) {\n if (name.includes('..') || name.includes('\\\\') || name.startsWith('/')) {\n return { ok: false, error: 'zip_unsafe_entry_path' }\n }\n const entry = zip.files[name] as JSZip.JSZipObject & {\n _data?: { uncompressedSize?: number }\n }\n totalUncompressed += entry._data?.uncompressedSize ?? 0\n if (totalUncompressed > MAX_PLUGIN_UNCOMPRESSED_BYTES) {\n return { ok: false, error: 'zip_uncompressed_too_large' }\n }\n }\n return { ok: true, value: true }\n}\n\nexport function assertZipFile(file: { name?: string; size: number }): PluginActionResult<true> {\n const name = (file.name ?? 'upload.zip').toLowerCase()\n if (!name.endsWith('.zip')) return { ok: false, error: 'invalid_file_extension' }\n if (file.size <= 0) return { ok: false, error: 'empty_file' }\n if (file.size > MAX_PLUGIN_ZIP_BYTES) return { ok: false, error: 'file_too_large' }\n return { ok: true, value: true }\n}\n","const CORE_SEMVER_RE = /^(\\d+)\\.(\\d+)\\.(\\d+)/\n\n/**\n * Next patch version assigned by Cervio. Ignores pre-release/build metadata on\n * the previous label and bumps the patch component only.\n */\nexport function nextPatchVersion(latest: string | null | undefined): string {\n if (!latest || typeof latest !== 'string') return '0.1.0'\n const m = latest.trim().match(CORE_SEMVER_RE)\n if (!m) return '0.1.0'\n const major = Number(m[1])\n const minor = Number(m[2])\n const patch = Number(m[3])\n if (![major, minor, patch].every((n) => Number.isFinite(n) && n >= 0)) return '0.1.0'\n return `${major}.${minor}.${patch + 1}`\n}\n\n/** Compare core x.y.z numerically (descending sort helper). */\nexport function compareSemverDesc(a: string, b: string): number {\n const pa = a.match(CORE_SEMVER_RE)\n const pb = b.match(CORE_SEMVER_RE)\n if (!pa && !pb) return 0\n if (!pa) return 1\n if (!pb) return -1\n for (let i = 1; i <= 3; i++) {\n const da = Number(pa[i]) - Number(pb[i])\n if (da !== 0) return da > 0 ? -1 : 1\n }\n return 0\n}\n","import { z } from 'zod'\n\n/** Zod schema documenting the author-facing manifest shape (source of truth for JSON Schema). */\nexport const pluginManifestZodSchema = z\n .object({\n plugin_key: z\n .string()\n .regex(/^[a-z0-9][a-z0-9-_]{1,62}$/)\n .optional()\n .describe('Stable plugin id. Prefer this over legacy `id`.'),\n id: z.string().optional().describe('Legacy alias for plugin_key (slashes become dashes).'),\n plugin_name: z.string().optional(),\n name: z.string().optional().describe('Legacy alias for plugin_name.'),\n plugin_type: z.enum(['task', 'form', 'task_form', 'route']).optional(),\n kind: z\n .string()\n .optional()\n .describe('Legacy alias for plugin_type (task_widget→task, record_panel→form).'),\n version: z\n .string()\n .optional()\n .describe('Ignored by Cervio — the host assigns release versions.'),\n required_connection_capabilities: z.array(z.string()).optional(),\n requiredConnectionCapabilities: z.array(z.string()).optional(),\n connections: z\n .array(\n z.object({\n id: z.string(),\n provider: z.string(),\n scopes: z.array(z.string()),\n allowed_apis: z\n .array(\n z.object({\n host: z.string(),\n methods: z.array(z.string()),\n path_prefix: z.string().optional(),\n pathPrefix: z.string().optional(),\n }),\n )\n .optional(),\n allowedApis: z.array(z.unknown()).optional(),\n }),\n )\n .optional(),\n entities: z\n .array(\n z.object({\n name: z.string(),\n fields: z.array(z.string()).optional(),\n forms: z.array(z.string()).optional(),\n access: z.array(z.enum(['read', 'write'])).optional(),\n }),\n )\n .optional(),\n cervio_apis: z\n .array(\n z.object({\n method: z.string().optional(),\n path_prefix: z.string().optional(),\n pathPrefix: z.string().optional(),\n }),\n )\n .optional(),\n cervioApis: z.array(z.unknown()).optional(),\n })\n .passthrough()\n\nexport type PluginManifestZod = z.infer<typeof pluginManifestZodSchema>\n","import JSZip from 'jszip'\nimport { parsePluginConnections } from './connections.js'\nimport {\n parsePluginCervioApiRequirements,\n parsePluginEntityRequirements,\n} from './entity-requirements.js'\nimport {\n DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES,\n PLUGIN_KEY_RE,\n type ParseManifestOptions,\n type ParsedPluginManifest,\n type PluginActionResult,\n type PluginCervioApiRequirement,\n type PluginConnectionRequirement,\n type PluginEntityRequirement,\n type PluginType,\n} from './types.js'\nimport { assertZipSafe } from './zip-safety.js'\n\nexport function normalizePluginKey(raw: string): string {\n return raw\n .trim()\n .toLowerCase()\n .replace(/[\\/\\s]+/g, '-')\n .replace(/[^a-z0-9-_]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\nfunction resolvePluginType(raw: string): PluginType | null {\n const kindMap: Record<string, PluginType> = {\n route: 'route',\n task: 'task',\n form: 'form',\n task_form: 'task_form',\n task_widget: 'task',\n record_panel: 'form',\n }\n const candidate = kindMap[raw] ?? raw\n return (['task', 'form', 'task_form', 'route'] as const).includes(candidate as PluginType)\n ? (candidate as PluginType)\n : null\n}\n\nfunction parseRequiredCapabilities(\n raw: unknown,\n allowed: readonly string[],\n): string[] {\n if (!Array.isArray(raw)) return []\n const allowedSet = new Set(allowed)\n const out: string[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (typeof item !== 'string') continue\n const id = item.trim().toLowerCase()\n if (!id || !allowedSet.has(id) || seen.has(id)) continue\n seen.add(id)\n out.push(id)\n }\n return out\n}\n\nexport function parseManifestObject(\n parsed: Record<string, unknown>,\n options?: ParseManifestOptions,\n): PluginActionResult<{\n pluginKey: string\n pluginName: string | null\n pluginType: PluginType | null\n manifestVersion: string | null\n requiredConnectionCapabilities: string[]\n connections: PluginConnectionRequirement[]\n entities: PluginEntityRequirement[]\n cervioApis: PluginCervioApiRequirement[]\n}> {\n const allowedCapabilities =\n options?.allowedCapabilities ?? DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES\n\n const pluginKeyRaw =\n typeof parsed.plugin_key === 'string'\n ? parsed.plugin_key\n : typeof parsed.id === 'string'\n ? parsed.id.split('/').filter(Boolean).join('-')\n : ''\n const pluginKey = normalizePluginKey(pluginKeyRaw)\n if (!pluginKey || !PLUGIN_KEY_RE.test(pluginKey)) {\n return { ok: false, error: 'manifest_plugin_key_invalid' }\n }\n const pluginName =\n typeof parsed.plugin_name === 'string' && parsed.plugin_name.trim()\n ? parsed.plugin_name.trim()\n : typeof parsed.name === 'string' && parsed.name.trim()\n ? parsed.name.trim()\n : null\n\n const pluginTypeRaw =\n typeof parsed.plugin_type === 'string'\n ? parsed.plugin_type.trim()\n : typeof parsed.kind === 'string'\n ? parsed.kind.trim()\n : ''\n const pluginType = resolvePluginType(pluginTypeRaw)\n\n const manifestVersion =\n typeof parsed.version === 'string' && parsed.version.trim() ? parsed.version.trim() : null\n\n const requiredRaw =\n parsed.required_connection_capabilities ?? parsed.requiredConnectionCapabilities ?? []\n const requiredConnectionCapabilities = parseRequiredCapabilities(\n requiredRaw,\n allowedCapabilities,\n )\n\n const connections = parsePluginConnections(parsed.connections)\n const entities = parsePluginEntityRequirements(parsed.entities)\n const cervioApis = parsePluginCervioApiRequirements(\n parsed.cervio_apis ?? parsed.cervioApis ?? [],\n )\n\n return {\n ok: true,\n value: {\n pluginKey,\n pluginName,\n pluginType,\n manifestVersion,\n requiredConnectionCapabilities,\n connections,\n entities,\n cervioApis,\n },\n }\n}\n\n/** Manifest JSON for hashing: drop author `version` so Cervio-owned labels do not affect dedup. */\nexport function manifestJsonForContentHash(raw: Record<string, unknown>): string {\n const clone: Record<string, unknown> = { ...raw }\n delete clone.version\n return JSON.stringify(clone)\n}\n\nexport async function loadZipFromBuffer(\n buffer: ArrayBuffer | Buffer,\n): Promise<PluginActionResult<JSZip>> {\n try {\n const zip = await JSZip.loadAsync(buffer)\n const safe = assertZipSafe(zip)\n if (!safe.ok) return safe\n return { ok: true, value: zip }\n } catch {\n return { ok: false, error: 'zip_invalid' }\n }\n}\n\nexport async function parseZipManifest(\n file: File | Blob,\n options?: ParseManifestOptions,\n): Promise<PluginActionResult<ParsedPluginManifest>> {\n const buffer = await file.arrayBuffer()\n const zipRes = await loadZipFromBuffer(buffer)\n if (!zipRes.ok) return zipRes\n const zip = zipRes.value\n\n const manifestEntry =\n zip.file('manifest.json') ??\n zip.file('manifest.example.json') ??\n Object.values(zip.files).find(\n (f) => f.name.endsWith('/manifest.json') || f.name.endsWith('/manifest.example.json'),\n )\n if (!manifestEntry) return { ok: false, error: 'manifest_not_found_in_zip' }\n\n const jsonText = await manifestEntry.async('text')\n let parsed: Record<string, unknown>\n try {\n parsed = JSON.parse(jsonText) as Record<string, unknown>\n } catch {\n return { ok: false, error: 'manifest_invalid_json' }\n }\n\n const fields = parseManifestObject(parsed, options)\n if (!fields.ok) return fields\n\n const hasDistIndex = !!zip.file('dist/index.html')\n if (!hasDistIndex) return { ok: false, error: 'build_index_missing' }\n const hasDistAssets = Object.keys(zip.files).some((name) => /^dist\\/assets\\/.+/.test(name))\n if (!hasDistAssets) return { ok: false, error: 'build_assets_missing' }\n\n return {\n ok: true,\n value: {\n ...fields.value,\n artifactEntryPath: 'dist/index.html',\n rawManifest: parsed,\n manifestEntryName: manifestEntry.name,\n },\n }\n}\n","import { createHash } from 'node:crypto'\nimport type JSZip from 'jszip'\nimport { manifestJsonForContentHash } from './manifest.js'\nimport type { PluginActionResult } from './types.js'\n\n/**\n * Deterministic SHA-256 over:\n * - manifest.json (JSON without `version` field)\n * - every non-directory entry under dist/** (paths sorted)\n *\n * README / other root files and ZIP compression metadata do not affect the hash.\n */\nexport async function computePluginContentSha256(\n zip: JSZip,\n rawManifest: Record<string, unknown>,\n): Promise<PluginActionResult<string>> {\n try {\n const hash = createHash('sha256')\n hash.update('manifest\\0')\n hash.update(manifestJsonForContentHash(rawManifest))\n hash.update('\\0')\n\n const distPaths = Object.keys(zip.files)\n .filter((name) => {\n const entry = zip.files[name]\n if (!entry || entry.dir) return false\n const normalized = name.replace(/^\\.\\//, '')\n return normalized === 'dist' || normalized.startsWith('dist/')\n })\n .map((name) => name.replace(/^\\.\\//, ''))\n .sort((a, b) => a.localeCompare(b))\n\n for (const path of distPaths) {\n const entry = zip.file(path)\n if (!entry || entry.dir) continue\n const bytes = await entry.async('uint8array')\n hash.update('file\\0')\n hash.update(path)\n hash.update('\\0')\n hash.update(bytes)\n hash.update('\\0')\n }\n\n return { ok: true, value: hash.digest('hex') }\n } catch {\n return { ok: false, error: 'content_hash_failed' }\n }\n}\n\nexport function sha256Hex(buffer: Buffer | Uint8Array): string {\n return createHash('sha256').update(buffer).digest('hex')\n}\n","import { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport JSZip from 'jszip'\nimport { computePluginContentSha256 } from './content-hash.js'\nimport { loadZipFromBuffer, parseManifestObject, parseZipManifest } from './manifest.js'\nimport type { ParseManifestOptions, PluginActionResult } from './types.js'\nimport { assertZipFile, assertZipSafe } from './zip-safety.js'\n\nexport type PackPluginResult = {\n buffer: Buffer\n pluginKey: string\n contentSha256: string\n sizeBytes: number\n}\n\nasync function collectFiles(dir: string, base = ''): Promise<Array<{ rel: string; abs: string }>> {\n const entries = await fs.readdir(dir, { withFileTypes: true })\n const out: Array<{ rel: string; abs: string }> = []\n for (const entry of entries) {\n const abs = path.join(dir, entry.name)\n const rel = base ? `${base}/${entry.name}` : entry.name\n if (entry.isDirectory()) {\n out.push(...(await collectFiles(abs, rel)))\n } else if (entry.isFile()) {\n out.push({ rel: rel.replace(/\\\\/g, '/'), abs })\n }\n }\n return out\n}\n\n/**\n * Pack a built plugin directory into a ZIP buffer.\n * Expects `manifest.json` at root and `dist/index.html` + `dist/assets/*`.\n */\nexport async function packPlugin(opts: {\n dir: string\n options?: ParseManifestOptions\n}): Promise<PluginActionResult<PackPluginResult>> {\n const root = path.resolve(opts.dir)\n const manifestPath = path.join(root, 'manifest.json')\n let manifestRaw: Record<string, unknown>\n try {\n const text = await fs.readFile(manifestPath, 'utf8')\n manifestRaw = JSON.parse(text) as Record<string, unknown>\n } catch {\n return { ok: false, error: 'manifest_not_found_in_zip' }\n }\n\n const fields = parseManifestObject(manifestRaw, opts.options)\n if (!fields.ok) return fields\n\n const distIndex = path.join(root, 'dist', 'index.html')\n try {\n await fs.access(distIndex)\n } catch {\n return { ok: false, error: 'build_index_missing' }\n }\n\n const zip = new JSZip()\n const files = await collectFiles(root)\n let hasAssets = false\n for (const file of files) {\n if (file.rel.startsWith('.cervio/') || file.rel === 'node_modules' || file.rel.startsWith('node_modules/')) {\n continue\n }\n if (file.rel.startsWith('dist/assets/') && file.rel !== 'dist/assets/') {\n hasAssets = true\n }\n const data = await fs.readFile(file.abs)\n zip.file(file.rel, data)\n }\n if (!hasAssets) return { ok: false, error: 'build_assets_missing' }\n\n const safe = assertZipSafe(zip)\n if (!safe.ok) return safe\n\n const buffer = Buffer.from(await zip.generateAsync({ type: 'uint8array', compression: 'DEFLATE' }))\n const fileCheck = assertZipFile({ name: `${fields.value.pluginKey}.zip`, size: buffer.length })\n if (!fileCheck.ok) return fileCheck\n\n const loaded = await loadZipFromBuffer(buffer)\n if (!loaded.ok) return loaded\n const hash = await computePluginContentSha256(loaded.value, manifestRaw)\n if (!hash.ok) return hash\n\n return {\n ok: true,\n value: {\n buffer,\n pluginKey: fields.value.pluginKey,\n contentSha256: hash.value,\n sizeBytes: buffer.length,\n },\n }\n}\n\n/** Validate an on-disk plugin directory (or an existing ZIP) without uploading. */\nexport async function validatePluginDir(\n dir: string,\n options?: ParseManifestOptions,\n): Promise<PluginActionResult<{ pluginKey: string; contentSha256: string }>> {\n const packed = await packPlugin({ dir, options })\n if (!packed.ok) return packed\n const blob = new Blob([packed.value.buffer], { type: 'application/zip' })\n const parsed = await parseZipManifest(blob, options)\n if (!parsed.ok) return parsed\n return {\n ok: true,\n value: {\n pluginKey: packed.value.pluginKey,\n contentSha256: packed.value.contentSha256,\n },\n }\n}\n\nexport async function validatePluginZipBuffer(\n buffer: Buffer,\n options?: ParseManifestOptions,\n): Promise<PluginActionResult<{ pluginKey: string; contentSha256: string }>> {\n const fileCheck = assertZipFile({ name: 'plugin.zip', size: buffer.length })\n if (!fileCheck.ok) return fileCheck\n const blob = new Blob([buffer], { type: 'application/zip' })\n const parsed = await parseZipManifest(blob, options)\n if (!parsed.ok) return parsed\n const zipRes = await loadZipFromBuffer(buffer)\n if (!zipRes.ok) return zipRes\n const hash = await computePluginContentSha256(zipRes.value, parsed.value.rawManifest)\n if (!hash.ok) return hash\n return {\n ok: true,\n value: { pluginKey: parsed.value.pluginKey, contentSha256: hash.value },\n }\n}\n"]}