@snap-rail/plugin-kit 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/build.js +2 -1
- package/lib/index.js +2 -2
- package/lib/pack.js +48 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/pack.d.ts +46 -0
- package/package.json +16 -2
package/lib/build.js
CHANGED
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CLIENT_EXTERNALS, CONTRIBUTED_SEED_MODULES, SEED_ABI_REVISION, SEED_MODULES, checkSeedAbi } from "./seeds.js";
|
|
2
2
|
import { clientBundle, hostBundle, seedImportGuard } from "./build.js";
|
|
3
3
|
import { PLUGIN_KINDS, clientFaceSchema, seedAbiSchema, snapRailManifestSchema } from "./manifest.js";
|
|
4
|
-
import { releaseFiles, releaseManifest, zipFileName } from "./pack.js";
|
|
4
|
+
import { catalogEntryFromZip, releaseFiles, releaseManifest, zipFileName } from "./pack.js";
|
|
5
5
|
import { packageNameOf, recipeDocumentSchema, recipePackageNames, recipeRowSchema } from "./recipe.js";
|
|
6
6
|
import { RELEASE_METADATA_PATH, RELEASE_SIGNATURE_PATH, canonicalJson, releaseMetadata, sha256, signReleaseFiles, signReleaseMetadata, verifyReleaseFiles } from "./sign.js";
|
|
7
7
|
//#region lib/types/slot-vocabulary.js
|
|
@@ -40,4 +40,4 @@ function defineSlotVocabulary(ids, options) {
|
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
//#endregion
|
|
43
|
-
export { CLIENT_EXTERNALS, CONTRIBUTED_SEED_MODULES, CUSTOM_SLOT_PATTERN, PLUGIN_KINDS, RELEASE_METADATA_PATH, RELEASE_SIGNATURE_PATH, SEED_ABI_REVISION, SEED_MODULES, canonicalJson, checkSeedAbi, clientBundle, clientFaceSchema, defineSlotVocabulary, hostBundle, packageNameOf, recipeDocumentSchema, recipePackageNames, recipeRowSchema, releaseFiles, releaseManifest, releaseMetadata, seedAbiSchema, seedImportGuard, sha256, signReleaseFiles, signReleaseMetadata, snapRailManifestSchema, verifyReleaseFiles, zipFileName };
|
|
43
|
+
export { CLIENT_EXTERNALS, CONTRIBUTED_SEED_MODULES, CUSTOM_SLOT_PATTERN, PLUGIN_KINDS, RELEASE_METADATA_PATH, RELEASE_SIGNATURE_PATH, SEED_ABI_REVISION, SEED_MODULES, canonicalJson, catalogEntryFromZip, checkSeedAbi, clientBundle, clientFaceSchema, defineSlotVocabulary, hostBundle, packageNameOf, recipeDocumentSchema, recipePackageNames, recipeRowSchema, releaseFiles, releaseManifest, releaseMetadata, seedAbiSchema, seedImportGuard, sha256, signReleaseFiles, signReleaseMetadata, snapRailManifestSchema, verifyReleaseFiles, zipFileName };
|
package/lib/pack.js
CHANGED
|
@@ -2,6 +2,8 @@ import { CLIENT_EXTERNALS } from "./seeds.js";
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { readFile, readdir } from "node:fs/promises";
|
|
4
4
|
import { join, relative } from "node:path";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
import { unzipSync } from "fflate";
|
|
5
7
|
//#region lib/types/pack.js
|
|
6
8
|
/**
|
|
7
9
|
* Final-format assembly: turn a built plugin package into the file set of
|
|
@@ -154,5 +156,50 @@ async function releaseFiles(spec) {
|
|
|
154
156
|
function zipFileName(packageName) {
|
|
155
157
|
return `${packageName.replaceAll("/", "__")}.zip`;
|
|
156
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* The one feed-entry emitter every producer shares: read a plugin zip's own
|
|
161
|
+
* bytes back (release manifest + signature envelope), derive the
|
|
162
|
+
* `index.json` entry from exactly what the zip carries, and digest the exact
|
|
163
|
+
* bytes the client will download — the feed can never advertise something a
|
|
164
|
+
* zip does not. The repo's pack/collect pipeline and the standalone
|
|
165
|
+
* `snap-rail-plugin feed` command all converge here.
|
|
166
|
+
*
|
|
167
|
+
* @param zipped - the exact zip bytes the feed will serve.
|
|
168
|
+
* @param file - the pure file name the entry advertises (no path).
|
|
169
|
+
* @param fallbackName - the entry's name when the manifest carries none.
|
|
170
|
+
* @param options.requireSignature - refuse unsigned zips (feed policy).
|
|
171
|
+
* @param options.repository - an optional source-repository URL.
|
|
172
|
+
* @returns the entry, unknown fields stripped by construction.
|
|
173
|
+
* @throws when the zip has no readable manifest, or no signature while
|
|
174
|
+
* `requireSignature` is set.
|
|
175
|
+
*/
|
|
176
|
+
function catalogEntryFromZip(zipped, file, fallbackName, options = {}) {
|
|
177
|
+
const files = unzipSync(zipped);
|
|
178
|
+
const manifestFile = files["package.json"];
|
|
179
|
+
if (manifestFile === void 0) throw new Error(`catalog: ${file} 缺少 package.json`);
|
|
180
|
+
const manifest = JSON.parse(new TextDecoder().decode(manifestFile));
|
|
181
|
+
const signatureFile = files["META-INF/signature.json"];
|
|
182
|
+
if (signatureFile === void 0 && options.requireSignature === true) throw new Error(`catalog: ${file} 没有签名(META-INF/signature.json 缺失)`);
|
|
183
|
+
const signature = signatureFile === void 0 ? void 0 : JSON.parse(new TextDecoder().decode(signatureFile));
|
|
184
|
+
return {
|
|
185
|
+
name: manifest.name ?? fallbackName,
|
|
186
|
+
version: manifest.version ?? "0.0.0",
|
|
187
|
+
...manifest.description !== void 0 && manifest.description !== "" ? { description: manifest.description } : {},
|
|
188
|
+
...manifest.snapRail?.kind !== void 0 ? { kind: manifest.snapRail.kind } : {},
|
|
189
|
+
...manifest.snapRail?.title !== void 0 ? { title: manifest.snapRail.title } : {},
|
|
190
|
+
...manifest.snapRail?.category !== void 0 ? { category: manifest.snapRail.category } : {},
|
|
191
|
+
...manifest.snapRail?.requires !== void 0 ? { requires: manifest.snapRail.requires } : {},
|
|
192
|
+
...manifest.snapRail?.permissions !== void 0 ? { permissions: manifest.snapRail.permissions } : {},
|
|
193
|
+
...manifest.snapRail?.engines !== void 0 ? { engines: manifest.snapRail.engines } : {},
|
|
194
|
+
file,
|
|
195
|
+
sha256: createHash("sha256").update(zipped).digest("hex"),
|
|
196
|
+
size: zipped.length,
|
|
197
|
+
...signature === void 0 ? {} : { signature: {
|
|
198
|
+
algorithm: signature.algorithm,
|
|
199
|
+
keyId: signature.keyId
|
|
200
|
+
} },
|
|
201
|
+
...options.repository === void 0 ? {} : { repository: options.repository }
|
|
202
|
+
};
|
|
203
|
+
}
|
|
157
204
|
//#endregion
|
|
158
|
-
export { releaseFiles, releaseManifest, zipFileName };
|
|
205
|
+
export { catalogEntryFromZip, releaseFiles, releaseManifest, zipFileName };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export { SEED_MODULES } from './seeds.ts';
|
|
|
12
12
|
export { CLIENT_EXTERNALS, CONTRIBUTED_SEED_MODULES, SEED_ABI_REVISION, checkSeedAbi, type SeedAbi, type SeedAbiVerdict, } from './seeds.ts';
|
|
13
13
|
export { clientBundle, hostBundle, seedImportGuard } from './build.ts';
|
|
14
14
|
export { CUSTOM_SLOT_PATTERN, defineSlotVocabulary, type SlotIdOf, type SlotVocabulary, } from './slot-vocabulary.ts';
|
|
15
|
-
export { releaseFiles, releaseManifest, zipFileName, type ReleaseSpec } from './pack.ts';
|
|
15
|
+
export { catalogEntryFromZip, releaseFiles, releaseManifest, zipFileName, type FeedEntry, type ReleaseSpec } from './pack.ts';
|
|
16
16
|
export { packageNameOf, recipeDocumentSchema, recipePackageNames, recipeRowSchema, type RecipeDocument, type RecipeRow, } from './recipe.ts';
|
|
17
17
|
export { RELEASE_METADATA_PATH, RELEASE_SIGNATURE_PATH, canonicalJson, releaseMetadata, sha256, signReleaseFiles, signReleaseMetadata, verifyReleaseFiles, type ReleaseFileDigests, type ReleaseMetadata, type ReleaseSignature, type TrustedReleaseKey, } from './sign.ts';
|
|
18
18
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/types/pack.d.ts
CHANGED
|
@@ -75,5 +75,51 @@ export declare function releaseManifest(source: SourceManifest, main: string, ex
|
|
|
75
75
|
export declare function releaseFiles(spec: ReleaseSpec): Promise<Record<string, Uint8Array>>;
|
|
76
76
|
/** The zip file name a package's release takes under dist-plugins/. */
|
|
77
77
|
export declare function zipFileName(packageName: string): string;
|
|
78
|
+
/** One plugin entry the feed's `index.json` carries (feed facts only). */
|
|
79
|
+
export interface FeedEntry {
|
|
80
|
+
name: string;
|
|
81
|
+
version: string;
|
|
82
|
+
description?: string;
|
|
83
|
+
kind?: string;
|
|
84
|
+
title?: string;
|
|
85
|
+
category?: string;
|
|
86
|
+
requires?: string[];
|
|
87
|
+
permissions?: string[];
|
|
88
|
+
engines?: {
|
|
89
|
+
snapRail?: string;
|
|
90
|
+
hostProtocol?: string;
|
|
91
|
+
renderer?: string;
|
|
92
|
+
};
|
|
93
|
+
/** The pure file name the entry advertises (no path). */
|
|
94
|
+
file: string;
|
|
95
|
+
sha256: string;
|
|
96
|
+
size: number;
|
|
97
|
+
signature?: {
|
|
98
|
+
algorithm: 'Ed25519';
|
|
99
|
+
keyId: string;
|
|
100
|
+
};
|
|
101
|
+
repository?: string;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The one feed-entry emitter every producer shares: read a plugin zip's own
|
|
105
|
+
* bytes back (release manifest + signature envelope), derive the
|
|
106
|
+
* `index.json` entry from exactly what the zip carries, and digest the exact
|
|
107
|
+
* bytes the client will download — the feed can never advertise something a
|
|
108
|
+
* zip does not. The repo's pack/collect pipeline and the standalone
|
|
109
|
+
* `snap-rail-plugin feed` command all converge here.
|
|
110
|
+
*
|
|
111
|
+
* @param zipped - the exact zip bytes the feed will serve.
|
|
112
|
+
* @param file - the pure file name the entry advertises (no path).
|
|
113
|
+
* @param fallbackName - the entry's name when the manifest carries none.
|
|
114
|
+
* @param options.requireSignature - refuse unsigned zips (feed policy).
|
|
115
|
+
* @param options.repository - an optional source-repository URL.
|
|
116
|
+
* @returns the entry, unknown fields stripped by construction.
|
|
117
|
+
* @throws when the zip has no readable manifest, or no signature while
|
|
118
|
+
* `requireSignature` is set.
|
|
119
|
+
*/
|
|
120
|
+
export declare function catalogEntryFromZip(zipped: Uint8Array, file: string, fallbackName: string, options?: {
|
|
121
|
+
requireSignature?: boolean;
|
|
122
|
+
repository?: string;
|
|
123
|
+
}): FeedEntry;
|
|
78
124
|
export {};
|
|
79
125
|
//# sourceMappingURL=pack.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snap-rail/plugin-kit",
|
|
3
|
-
"description": "The plugin author's kit: snapRail manifest vocabulary, the renderer seed whitelist,
|
|
4
|
-
"version": "0.2.
|
|
3
|
+
"description": "The plugin author's kit: snapRail manifest vocabulary, the renderer seed whitelist, tsdown presets for installable host + client faces, release signing, and the final-format packer",
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/types/index.d.ts",
|
|
8
|
+
"homepage": "https://www.snap-rail.top/dev.html",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/yansijian/snap-rail.git",
|
|
12
|
+
"directory": "packages/base/plugin-kit"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"snap-rail",
|
|
16
|
+
"plugin",
|
|
17
|
+
"cordis",
|
|
18
|
+
"industrial",
|
|
19
|
+
"electron"
|
|
20
|
+
],
|
|
8
21
|
"exports": {
|
|
9
22
|
".": {
|
|
10
23
|
"types": "./lib/types/index.d.ts",
|
|
@@ -43,6 +56,7 @@
|
|
|
43
56
|
],
|
|
44
57
|
"license": "Apache-2.0",
|
|
45
58
|
"dependencies": {
|
|
59
|
+
"fflate": "^0.8.3",
|
|
46
60
|
"zod": "^4.4.3",
|
|
47
61
|
"@snap-rail/util": "^0.1.2"
|
|
48
62
|
},
|