@markii/bundle 0.10.0 → 0.12.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/manifest.d.ts +23 -4
- package/dist/manifest.js +48 -7
- package/package.json +1 -1
package/dist/manifest.d.ts
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import type { BundleFsGrant } from './paths.js';
|
|
2
2
|
/**
|
|
3
|
-
* `manifest.json`'s contract (spec §9–§11). `
|
|
3
|
+
* `manifest.json`'s contract (spec §9–§11). `spec` is the only required
|
|
4
4
|
* field. The index signature keeps unrecognized top-level keys typed as
|
|
5
5
|
* `unknown` rather than dropped — `parseManifest` preserves them verbatim
|
|
6
|
-
* (see the "forward compatibility" note there) so a manifest
|
|
7
|
-
* newer spec version round-trips through an older
|
|
6
|
+
* (see the "forward compatibility" note there) so a manifest field
|
|
7
|
+
* introduced by a newer spec version round-trips through an older
|
|
8
|
+
* implementation intact.
|
|
9
|
+
*
|
|
10
|
+
* `mark` is the retired name for this field (pre-rename). It is still
|
|
11
|
+
* accepted on read (see `parseManifest`) but is never written; keep it as
|
|
12
|
+
* an explicit optional field, rather than relying on the index signature,
|
|
13
|
+
* so a reader can name it without an `as` cast.
|
|
8
14
|
*/
|
|
9
15
|
export interface BundleManifest {
|
|
10
16
|
/** Spec semver this bundle was authored against, e.g. `"0.1.0"`. */
|
|
11
|
-
|
|
17
|
+
spec: string;
|
|
18
|
+
/** Retired name for `spec`. Read-only compatibility; never written. */
|
|
19
|
+
mark?: string;
|
|
12
20
|
permissions?: BundlePermissions;
|
|
13
21
|
uses?: string[];
|
|
14
22
|
/**
|
|
@@ -61,6 +69,17 @@ export declare const CURRENT_SPEC_VERSION = "0.1.0";
|
|
|
61
69
|
* rather than preserved, since `permissions` itself is a known, normalized
|
|
62
70
|
* key. Extending preservation to arbitrary nesting depth would be a
|
|
63
71
|
* reasonable follow-up but wasn't asked for here.
|
|
72
|
+
*
|
|
73
|
+
* `spec`/`mark` compatibility: `spec` is the current, required field name.
|
|
74
|
+
* `mark` is the retired name. If `spec` is present and valid it is always
|
|
75
|
+
* used, regardless of whether `mark` is also present. If `spec` is absent
|
|
76
|
+
* but a valid `mark` is present, `mark`'s value is used as `spec` and a
|
|
77
|
+
* warning is recorded (never an error) so legacy manifests keep working.
|
|
78
|
+
* If both are present, `mark` is ignored and a warning names it, since a
|
|
79
|
+
* manifest author who sets both most likely left `mark` behind while
|
|
80
|
+
* migrating to `spec` — preferring the new field is the least surprising
|
|
81
|
+
* behavior and matches how unknown-key forward-compat already favors the
|
|
82
|
+
* newer shape.
|
|
64
83
|
*/
|
|
65
84
|
export declare function parseManifest(json: string): ManifestParseResult;
|
|
66
85
|
/** A minimal, valid manifest for a freshly promoted bundle: no permissions granted, no packs declared. */
|
package/dist/manifest.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** The current spec version this package's default manifests declare. */
|
|
2
2
|
export const CURRENT_SPEC_VERSION = '0.1.0';
|
|
3
3
|
const KNOWN_TOP_LEVEL_KEYS = new Set([
|
|
4
|
+
'spec',
|
|
4
5
|
'mark',
|
|
5
6
|
'permissions',
|
|
6
7
|
'uses',
|
|
@@ -20,6 +21,9 @@ function isStringArray(value) {
|
|
|
20
21
|
function isPlainObject(value) {
|
|
21
22
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
22
23
|
}
|
|
24
|
+
function isValidSpecVersion(value) {
|
|
25
|
+
return typeof value === 'string' && SEMVER_RE.test(value);
|
|
26
|
+
}
|
|
23
27
|
/**
|
|
24
28
|
* Hand-rolled `manifest.json` validation (no schema library — see AGENTS.md
|
|
25
29
|
* dependency policy). Never throws: malformed JSON, a non-object root, or
|
|
@@ -37,6 +41,17 @@ function isPlainObject(value) {
|
|
|
37
41
|
* rather than preserved, since `permissions` itself is a known, normalized
|
|
38
42
|
* key. Extending preservation to arbitrary nesting depth would be a
|
|
39
43
|
* reasonable follow-up but wasn't asked for here.
|
|
44
|
+
*
|
|
45
|
+
* `spec`/`mark` compatibility: `spec` is the current, required field name.
|
|
46
|
+
* `mark` is the retired name. If `spec` is present and valid it is always
|
|
47
|
+
* used, regardless of whether `mark` is also present. If `spec` is absent
|
|
48
|
+
* but a valid `mark` is present, `mark`'s value is used as `spec` and a
|
|
49
|
+
* warning is recorded (never an error) so legacy manifests keep working.
|
|
50
|
+
* If both are present, `mark` is ignored and a warning names it, since a
|
|
51
|
+
* manifest author who sets both most likely left `mark` behind while
|
|
52
|
+
* migrating to `spec` — preferring the new field is the least surprising
|
|
53
|
+
* behavior and matches how unknown-key forward-compat already favors the
|
|
54
|
+
* newer shape.
|
|
40
55
|
*/
|
|
41
56
|
export function parseManifest(json) {
|
|
42
57
|
let raw;
|
|
@@ -57,13 +72,35 @@ export function parseManifest(json) {
|
|
|
57
72
|
const obj = raw;
|
|
58
73
|
const errors = [];
|
|
59
74
|
const warnings = [];
|
|
60
|
-
// ---
|
|
75
|
+
// --- spec (required, with legacy `mark` fallback) ---
|
|
76
|
+
const specRaw = obj.spec;
|
|
61
77
|
const markRaw = obj.mark;
|
|
62
|
-
|
|
63
|
-
|
|
78
|
+
const specPresent = specRaw !== undefined;
|
|
79
|
+
const markPresent = markRaw !== undefined;
|
|
80
|
+
let resolvedSpec;
|
|
81
|
+
if (specPresent) {
|
|
82
|
+
if (!isValidSpecVersion(specRaw)) {
|
|
83
|
+
errors.push(`"spec" must be a semver string (got ${JSON.stringify(specRaw)})`);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
resolvedSpec = specRaw;
|
|
87
|
+
if (markPresent) {
|
|
88
|
+
warnings.push('"mark" is ignored because "spec" is also present; remove "mark" ' +
|
|
89
|
+
'from this manifest');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (markPresent) {
|
|
94
|
+
if (!isValidSpecVersion(markRaw)) {
|
|
95
|
+
errors.push(`"mark" must be a semver string (got ${JSON.stringify(markRaw)})`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
resolvedSpec = markRaw;
|
|
99
|
+
warnings.push('"mark" is a retired field name; rename it to "spec" in this manifest');
|
|
100
|
+
}
|
|
64
101
|
}
|
|
65
|
-
else
|
|
66
|
-
errors.push(
|
|
102
|
+
else {
|
|
103
|
+
errors.push('"spec" is required and must be a string');
|
|
67
104
|
}
|
|
68
105
|
// --- permissions (optional) ---
|
|
69
106
|
let permissions;
|
|
@@ -154,7 +191,11 @@ export function parseManifest(json) {
|
|
|
154
191
|
if (errors.length > 0) {
|
|
155
192
|
return { ok: false, errors };
|
|
156
193
|
}
|
|
157
|
-
const manifest = {
|
|
194
|
+
const manifest = {
|
|
195
|
+
...obj,
|
|
196
|
+
spec: resolvedSpec,
|
|
197
|
+
};
|
|
198
|
+
delete manifest.mark;
|
|
158
199
|
if (permissions !== undefined)
|
|
159
200
|
manifest.permissions = permissions;
|
|
160
201
|
if (uses !== undefined)
|
|
@@ -165,5 +206,5 @@ export function parseManifest(json) {
|
|
|
165
206
|
}
|
|
166
207
|
/** A minimal, valid manifest for a freshly promoted bundle: no permissions granted, no packs declared. */
|
|
167
208
|
export function createDefaultManifest(specVersion = CURRENT_SPEC_VERSION) {
|
|
168
|
-
return {
|
|
209
|
+
return { spec: specVersion };
|
|
169
210
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markii/bundle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Bundle (.mkz, formerly .mkbundle) storage and policy layer for Markii: manifest handling, the bundle-relative path-jail, zip (fflate) and Node directory storage forms, and a capability-restricted script view. No React, no parsing.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|