@avantf/dsh-plugin-base 0.3.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.
Files changed (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +303 -0
  3. package/dist/artifact.d.ts +29 -0
  4. package/dist/artifact.d.ts.map +1 -0
  5. package/dist/artifact.js +60 -0
  6. package/dist/artifact.js.map +1 -0
  7. package/dist/bootstrap.d.ts +54 -0
  8. package/dist/bootstrap.d.ts.map +1 -0
  9. package/dist/bootstrap.js +334 -0
  10. package/dist/bootstrap.js.map +1 -0
  11. package/dist/cli.d.ts +4 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +37 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/compat.d.ts +413 -0
  16. package/dist/compat.d.ts.map +1 -0
  17. package/dist/compat.js +742 -0
  18. package/dist/compat.js.map +1 -0
  19. package/dist/conformance.d.ts +55 -0
  20. package/dist/conformance.d.ts.map +1 -0
  21. package/dist/conformance.js +702 -0
  22. package/dist/conformance.js.map +1 -0
  23. package/dist/errors.d.ts +26 -0
  24. package/dist/errors.d.ts.map +1 -0
  25. package/dist/errors.js +28 -0
  26. package/dist/errors.js.map +1 -0
  27. package/dist/fs.d.ts +18 -0
  28. package/dist/fs.d.ts.map +1 -0
  29. package/dist/fs.js +152 -0
  30. package/dist/fs.js.map +1 -0
  31. package/dist/index.d.ts +22 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +35 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/integrity.d.ts +5 -0
  36. package/dist/integrity.d.ts.map +1 -0
  37. package/dist/integrity.js +33 -0
  38. package/dist/integrity.js.map +1 -0
  39. package/dist/interface.d.ts +262 -0
  40. package/dist/interface.d.ts.map +1 -0
  41. package/dist/interface.js +136 -0
  42. package/dist/interface.js.map +1 -0
  43. package/dist/interface_gate.d.ts +61 -0
  44. package/dist/interface_gate.d.ts.map +1 -0
  45. package/dist/interface_gate.js +103 -0
  46. package/dist/interface_gate.js.map +1 -0
  47. package/dist/internal.d.ts +23 -0
  48. package/dist/internal.d.ts.map +1 -0
  49. package/dist/internal.js +18 -0
  50. package/dist/internal.js.map +1 -0
  51. package/dist/kit/family.d.ts +52 -0
  52. package/dist/kit/family.d.ts.map +1 -0
  53. package/dist/kit/family.js +65 -0
  54. package/dist/kit/family.js.map +1 -0
  55. package/dist/kit/index.d.ts +26 -0
  56. package/dist/kit/index.d.ts.map +1 -0
  57. package/dist/kit/index.js +26 -0
  58. package/dist/kit/index.js.map +1 -0
  59. package/dist/kit/logger.d.ts +41 -0
  60. package/dist/kit/logger.d.ts.map +1 -0
  61. package/dist/kit/logger.js +42 -0
  62. package/dist/kit/logger.js.map +1 -0
  63. package/dist/kit/prompt_files.d.ts +90 -0
  64. package/dist/kit/prompt_files.d.ts.map +1 -0
  65. package/dist/kit/prompt_files.js +121 -0
  66. package/dist/kit/prompt_files.js.map +1 -0
  67. package/dist/kit/typert.d.ts +40 -0
  68. package/dist/kit/typert.d.ts.map +1 -0
  69. package/dist/kit/typert.js +17 -0
  70. package/dist/kit/typert.js.map +1 -0
  71. package/dist/layout.d.ts +28 -0
  72. package/dist/layout.d.ts.map +1 -0
  73. package/dist/layout.js +84 -0
  74. package/dist/layout.js.map +1 -0
  75. package/dist/lint.d.ts +33 -0
  76. package/dist/lint.d.ts.map +1 -0
  77. package/dist/lint.js +271 -0
  78. package/dist/lint.js.map +1 -0
  79. package/dist/lock.d.ts +12 -0
  80. package/dist/lock.d.ts.map +1 -0
  81. package/dist/lock.js +93 -0
  82. package/dist/lock.js.map +1 -0
  83. package/dist/manifest.d.ts +12 -0
  84. package/dist/manifest.d.ts.map +1 -0
  85. package/dist/manifest.js +75 -0
  86. package/dist/manifest.js.map +1 -0
  87. package/dist/net.d.ts +23 -0
  88. package/dist/net.d.ts.map +1 -0
  89. package/dist/net.js +112 -0
  90. package/dist/net.js.map +1 -0
  91. package/dist/package-name.d.ts +3 -0
  92. package/dist/package-name.d.ts.map +1 -0
  93. package/dist/package-name.js +13 -0
  94. package/dist/package-name.js.map +1 -0
  95. package/dist/preset.d.ts +46 -0
  96. package/dist/preset.d.ts.map +1 -0
  97. package/dist/preset.js +230 -0
  98. package/dist/preset.js.map +1 -0
  99. package/dist/providers/archive.d.ts +32 -0
  100. package/dist/providers/archive.d.ts.map +1 -0
  101. package/dist/providers/archive.js +248 -0
  102. package/dist/providers/archive.js.map +1 -0
  103. package/dist/providers/model.d.ts +25 -0
  104. package/dist/providers/model.d.ts.map +1 -0
  105. package/dist/providers/model.js +550 -0
  106. package/dist/providers/model.js.map +1 -0
  107. package/dist/providers/npm.d.ts +21 -0
  108. package/dist/providers/npm.d.ts.map +1 -0
  109. package/dist/providers/npm.js +458 -0
  110. package/dist/providers/npm.js.map +1 -0
  111. package/dist/provisioner.d.ts +21 -0
  112. package/dist/provisioner.d.ts.map +1 -0
  113. package/dist/provisioner.js +962 -0
  114. package/dist/provisioner.js.map +1 -0
  115. package/dist/semver.d.ts +31 -0
  116. package/dist/semver.d.ts.map +1 -0
  117. package/dist/semver.js +244 -0
  118. package/dist/semver.js.map +1 -0
  119. package/dist/state.d.ts +71 -0
  120. package/dist/state.d.ts.map +1 -0
  121. package/dist/state.js +225 -0
  122. package/dist/state.js.map +1 -0
  123. package/dist/tar.d.ts +10 -0
  124. package/dist/tar.d.ts.map +1 -0
  125. package/dist/tar.js +178 -0
  126. package/dist/tar.js.map +1 -0
  127. package/dist/types.d.ts +431 -0
  128. package/dist/types.d.ts.map +1 -0
  129. package/dist/types.js +2 -0
  130. package/dist/types.js.map +1 -0
  131. package/dist/zip.d.ts +8 -0
  132. package/dist/zip.d.ts.map +1 -0
  133. package/dist/zip.js +109 -0
  134. package/dist/zip.js.map +1 -0
  135. package/package.json +84 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"AAQA,qDAAqD;AACrD,eAAO,MAAM,WAAW,aAAa,CAAA;AAErC,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,MAAM,CAAA;AAEnC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AACD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AACD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AACD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AACD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AACD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AACD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AACD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGjF;AAED,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,6FAA6F;AAC7F,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAG/D;AAED,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQzD;AAED,qFAAqF;AACrF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQzD;AAED,mFAAmF;AACnF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,aAAa,GAAE,MAAyB,GACvC,MAAM,CAOR"}
package/dist/layout.js ADDED
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Disk layout: control-plane and resource directories under `<home>`.
3
+ * @module layout
4
+ */
5
+ import { createHash } from 'node:crypto';
6
+ import { join, relative, sep } from 'node:path';
7
+ import { ProvisionError } from './errors.js';
8
+ /** The control-plane directory name under `home`. */
9
+ export const CONTROL_DIR = '.envinit';
10
+ /** Default path budget before the version segment switches to a short hash. */
11
+ export const DEFAULT_MAX_PATH = 200;
12
+ export function controlRoot(home) {
13
+ return join(home, CONTROL_DIR);
14
+ }
15
+ export function lockPath(home) {
16
+ return join(controlRoot(home), '.lock');
17
+ }
18
+ export function statusLockPath(home) {
19
+ return join(controlRoot(home), '.status.lock');
20
+ }
21
+ export function layoutPath(home) {
22
+ return join(controlRoot(home), '.layout.json');
23
+ }
24
+ export function statusPath(home) {
25
+ return join(controlRoot(home), 'status.json');
26
+ }
27
+ export function declaredPath(home) {
28
+ return join(controlRoot(home), 'declared.json');
29
+ }
30
+ export function tempRoot(home) {
31
+ return join(controlRoot(home), '.tmp');
32
+ }
33
+ export function quarantineRoot(home) {
34
+ return join(controlRoot(home), '.quarantine');
35
+ }
36
+ /**
37
+ * A staging directory for one install attempt under {@link tempRoot}.
38
+ * `sequence` must be monotonic per process.
39
+ */
40
+ export function stagingDir(home, itemId, sequence) {
41
+ const safe = itemId.replaceAll(/[^A-Za-z0-9._-]/g, '-');
42
+ return join(tempRoot(home), `${safe}-${String(process.pid)}-${String(sequence)}`);
43
+ }
44
+ /** A quarantine directory for one bad version directory. */
45
+ export function quarantineDir(home, sequence) {
46
+ return join(quarantineRoot(home), `${String(Date.now())}-${String(process.pid)}-${String(sequence)}`);
47
+ }
48
+ /** Is `child` inside `parent` (or equal to it)? Both are absolute and already normalised. */
49
+ export function isInside(parent, child) {
50
+ const rel = relative(parent, child);
51
+ return rel === '' || (!rel.startsWith('..') && !rel.startsWith(`..${sep}`));
52
+ }
53
+ /** Reject a `target.root` that is absolute or escapes `home` (`invalid-option`). */
54
+ export function assertSafeRelativeRoot(root) {
55
+ if (root === '' || root.startsWith('/') || /^[a-zA-Z]:[\\/]/.test(root) || root.includes('\0')) {
56
+ throw new ProvisionError('invalid-option', `target.root 必须是 home 下的相对路径:${JSON.stringify(root)}`);
57
+ }
58
+ const parts = root.replaceAll('\\', '/').split('/');
59
+ if (parts.some(part => part === '..')) {
60
+ throw new ProvisionError('invalid-option', `target.root 不得跳出 home:${JSON.stringify(root)}`);
61
+ }
62
+ }
63
+ /** Reject a provider-supplied relative path that is absolute or escapes its root. */
64
+ export function assertSafeRelativePath(path) {
65
+ if (path === '' || path.startsWith('/') || /^[a-zA-Z]:[\\/]/.test(path) || path.includes('\0')) {
66
+ throw new ProvisionError('invalid-option', `provider 给出的相对路径不安全:${JSON.stringify(path)}`);
67
+ }
68
+ const parts = path.replaceAll('\\', '/').split('/');
69
+ if (parts.some(part => part === '..')) {
70
+ throw new ProvisionError('invalid-option', `provider 给出的相对路径跳出目标根:${JSON.stringify(path)}`);
71
+ }
72
+ }
73
+ /** The version segment: the version, or a short hash when the path is too long. */
74
+ export function versionSegment(home, targetRoot, name, version, maxPathLength = DEFAULT_MAX_PATH) {
75
+ const candidate = join(home, targetRoot, ...name.split('/'), version);
76
+ if (candidate.length <= maxPathLength)
77
+ return version;
78
+ const digest = createHash('sha256').update(`${name}@${version}`).digest('hex');
79
+ const short8 = digest.slice(0, 8);
80
+ if (join(home, targetRoot, ...name.split('/'), short8).length <= maxPathLength)
81
+ return short8;
82
+ return digest.slice(0, 12);
83
+ }
84
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"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"}
package/dist/lint.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ /** The built-in kinds whose names are reserved. */
2
+ export declare const BUILTIN_KINDS: readonly string[];
3
+ /** Item policy keys the core reads. */
4
+ export declare const IMPLEMENTED_POLICY_KEYS: readonly string[];
5
+ /** Item policy keys the surface declares but this build does not read. */
6
+ export declare const UNIMPLEMENTED_POLICY_KEYS: readonly string[];
7
+ /** Provision-policy keys the surface declares but this build does not read. */
8
+ export declare const UNIMPLEMENTED_PROVISION_POLICY_KEYS: readonly string[];
9
+ /** The fields a manifest may carry; anything else is `ignored-field` at runtime. */
10
+ export declare const MANIFEST_FIELDS: readonly string[];
11
+ /** The fields an item may carry. */
12
+ export declare const ITEM_FIELDS: readonly string[];
13
+ /** The manifest keys this build does not know; empty when the surface matches exactly. */
14
+ export declare function unknownFields(value: unknown, known: readonly string[]): readonly string[];
15
+ export interface LintFinding {
16
+ /** A rule id, stable enough to assert on (`lint/id-prefix`, …). */
17
+ readonly rule: string;
18
+ readonly itemId?: string;
19
+ readonly message: string;
20
+ }
21
+ export interface LintResult {
22
+ readonly ok: boolean;
23
+ readonly findings: readonly LintFinding[];
24
+ }
25
+ /** Does any `||` branch contain a bare `*` token (or consist only of `*`)? */
26
+ export declare function hasStarBranch(range: string): boolean;
27
+ /** A third-party kind must be namespaced (`@scope/…` or `plugin:…`). */
28
+ export declare function isNamespacedKind(kind: string): boolean;
29
+ /** Lint a manifest value (already parsed JSON, or a typed object). */
30
+ export declare function lintManifest(manifest: unknown): LintResult;
31
+ /** Lint a manifest file's text; a JSON parse failure is itself a finding. */
32
+ export declare function lintManifestText(text: string): LintResult;
33
+ //# sourceMappingURL=lint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"AASA,mDAAmD;AACnD,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAAsF,CAAA;AAEjI,uCAAuC;AACvC,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EAAgB,CAAA;AAErE,0EAA0E;AAC1E,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAA8C,CAAA;AAErG,+EAA+E;AAC/E,eAAO,MAAM,mCAAmC,EAAE,SAAS,MAAM,EAMhE,CAAA;AAED,oFAAoF;AACpF,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAAoC,CAAA;AAEjF,oCAAoC;AACpC,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAUxC,CAAA;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CAGzF;AAED,MAAM,WAAW,WAAW;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;CAC1C;AAUD,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAIpD;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAqDD,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,UAAU,CAgJ1D;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CASzD"}
package/dist/lint.js ADDED
@@ -0,0 +1,271 @@
1
+ /**
2
+ * `provision lint` — the offline, purely static manifest check.
3
+ * @module lint
4
+ */
5
+ import { ProvisionError } from './errors.js';
6
+ import { assertPackageName } from './package-name.js';
7
+ import { assertRange } from './semver.js';
8
+ /** The built-in kinds whose names are reserved. */
9
+ export const BUILTIN_KINDS = ['npm-package', 'binary-archive', 'model-cache'];
10
+ /** Item policy keys the core reads. */
11
+ export const IMPLEMENTED_POLICY_KEYS = ['mirrors'];
12
+ /** Item policy keys the surface declares but this build does not read. */
13
+ export const UNIMPLEMENTED_POLICY_KEYS = ['concurrency', 'timeoutMs', 'platforms'];
14
+ /** Provision-policy keys the surface declares but this build does not read. */
15
+ export const UNIMPLEMENTED_PROVISION_POLICY_KEYS = [
16
+ 'packumentMirrors',
17
+ 'quotaBytes',
18
+ 'trashGraceMs',
19
+ 'gc',
20
+ 'preloaded',
21
+ ];
22
+ /** The fields a manifest may carry; anything else is `ignored-field` at runtime. */
23
+ export const MANIFEST_FIELDS = ['plugin', 'items', 'requires'];
24
+ /** The fields an item may carry. */
25
+ export const ITEM_FIELDS = [
26
+ 'id',
27
+ 'kind',
28
+ 'spec',
29
+ 'target',
30
+ 'onMissing',
31
+ 'startup',
32
+ 'needs',
33
+ 'policy',
34
+ 'schemaVersion',
35
+ ];
36
+ /** The manifest keys this build does not know; empty when the surface matches exactly. */
37
+ export function unknownFields(value, known) {
38
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
39
+ return [];
40
+ return Object.keys(value).filter(key => !known.includes(key));
41
+ }
42
+ function isRecord(value) {
43
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
44
+ }
45
+ function str(value) {
46
+ return typeof value === 'string' && value !== '' ? value : undefined;
47
+ }
48
+ /** Does any `||` branch contain a bare `*` token (or consist only of `*`)? */
49
+ export function hasStarBranch(range) {
50
+ return range
51
+ .split('||')
52
+ .some(branch => branch.split(/[\s,]+/).filter(token => token !== '').includes('*') || branch.trim() === '*');
53
+ }
54
+ /** A third-party kind must be namespaced (`@scope/…` or `plugin:…`). */
55
+ export function isNamespacedKind(kind) {
56
+ return /^@[^/]+\/.+/.test(kind) || /^plugin:.+/.test(kind);
57
+ }
58
+ function checkSpec(kind, spec, itemId, findings) {
59
+ if (kind === 'npm-package') {
60
+ if (!isRecord(spec)) {
61
+ findings.push({ rule: 'lint/spec-shape', itemId, message: 'npm-package 的 spec 必须是 {name, range}' });
62
+ return;
63
+ }
64
+ const name = str(spec['name']);
65
+ if (name === undefined) {
66
+ findings.push({ rule: 'lint/spec-shape', itemId, message: 'npm-package 缺少 spec.name' });
67
+ }
68
+ else {
69
+ try {
70
+ assertPackageName(name);
71
+ }
72
+ catch (error) {
73
+ findings.push({ rule: 'lint/spec-shape', itemId, message: error instanceof ProvisionError ? error.message : `非法的包名:${name}` });
74
+ }
75
+ }
76
+ const range = str(spec['range']);
77
+ if (range === undefined) {
78
+ findings.push({ rule: 'lint/spec-shape', itemId, message: 'npm-package 缺少 spec.range' });
79
+ }
80
+ else if (hasStarBranch(range)) {
81
+ findings.push({
82
+ rule: 'lint/range-star',
83
+ itemId,
84
+ message: '清单区间不得含 `*`(会匹配一切:既可能跨大版本,也会让"未知版本"通过校验)',
85
+ });
86
+ }
87
+ else {
88
+ try {
89
+ assertRange(range);
90
+ }
91
+ catch (error) {
92
+ findings.push({
93
+ rule: 'lint/range-subset',
94
+ itemId,
95
+ message: error instanceof ProvisionError ? error.message : `无法解析区间 ${range}`,
96
+ });
97
+ }
98
+ }
99
+ return;
100
+ }
101
+ if (kind === 'binary-archive') {
102
+ if (!isRecord(spec) || str(spec['id']) === undefined || str(spec['version']) === undefined || !isRecord(spec['packs'])) {
103
+ findings.push({ rule: 'lint/spec-shape', itemId, message: 'binary-archive 的 spec 必须是 {id, version, packs}' });
104
+ }
105
+ return;
106
+ }
107
+ if (kind === 'model-cache') {
108
+ if (!isRecord(spec) || str(spec['repo']) === undefined) {
109
+ findings.push({ rule: 'lint/spec-shape', itemId, message: 'model-cache 的 spec 必须是 {repo, revision?}' });
110
+ }
111
+ }
112
+ }
113
+ /** Lint a manifest value (already parsed JSON, or a typed object). */
114
+ export function lintManifest(manifest) {
115
+ const findings = [];
116
+ if (!isRecord(manifest)) {
117
+ return { ok: false, findings: [{ rule: 'lint/manifest-shape', message: 'manifest 必须是对象' }] };
118
+ }
119
+ for (const key of unknownFields(manifest, MANIFEST_FIELDS)) {
120
+ findings.push({ rule: 'lint/unknown-field', message: `manifest 携带框架不认识的字段:${key}` });
121
+ }
122
+ const plugin = str(manifest['plugin']);
123
+ if (plugin === undefined)
124
+ findings.push({ rule: 'lint/plugin-missing', message: 'Manifest.plugin 缺失' });
125
+ const items = manifest['items'];
126
+ if (!Array.isArray(items)) {
127
+ findings.push({ rule: 'lint/manifest-shape', message: 'Manifest.items 必须是数组' });
128
+ return { ok: findings.length === 0, findings };
129
+ }
130
+ const ids = new Set();
131
+ const needsOf = new Map();
132
+ for (const raw of items) {
133
+ if (!isRecord(raw)) {
134
+ findings.push({ rule: 'lint/item-shape', message: 'item 必须是对象' });
135
+ continue;
136
+ }
137
+ const id = str(raw['id']);
138
+ if (id === undefined) {
139
+ findings.push({ rule: 'lint/item-shape', message: 'item.id 缺失' });
140
+ continue;
141
+ }
142
+ for (const key of unknownFields(raw, ITEM_FIELDS)) {
143
+ findings.push({ rule: 'lint/unknown-field', itemId: id, message: `item 携带框架不认识的字段:${key}` });
144
+ }
145
+ if (ids.has(id))
146
+ findings.push({ rule: 'lint/id-duplicate', itemId: id, message: `item id 重复:${id}` });
147
+ ids.add(id);
148
+ if (plugin !== undefined && !id.startsWith(`${plugin}:`)) {
149
+ findings.push({ rule: 'lint/id-prefix', itemId: id, message: `item id 必须以 "${plugin}:" 前缀化` });
150
+ }
151
+ const kind = str(raw['kind']);
152
+ if (kind === undefined) {
153
+ findings.push({ rule: 'lint/item-shape', itemId: id, message: 'item.kind 缺失' });
154
+ }
155
+ else {
156
+ if (!BUILTIN_KINDS.includes(kind) && !isNamespacedKind(kind)) {
157
+ findings.push({ rule: 'lint/kind-namespace', itemId: id, message: `自定义 kind "${kind}" 必须带 @scope/ 或 plugin: 前缀` });
158
+ }
159
+ checkSpec(kind, raw['spec'], id, findings);
160
+ }
161
+ if (typeof raw['schemaVersion'] !== 'number') {
162
+ findings.push({ rule: 'lint/item-shape', itemId: id, message: 'item.schemaVersion 必须是数字' });
163
+ }
164
+ const target = raw['target'];
165
+ if (!isRecord(target)) {
166
+ findings.push({ rule: 'lint/target-root', itemId: id, message: 'item.target 必须是 {root}' });
167
+ }
168
+ else {
169
+ const root = target['root'];
170
+ if (typeof root !== 'string' || root === '') {
171
+ findings.push({ rule: 'lint/target-root', itemId: id, message: 'item.target.root 缺失' });
172
+ }
173
+ else if (root.startsWith('/') || /^[a-zA-Z]:[\\/]/.test(root) || root.replaceAll('\\', '/').split('/').includes('..')) {
174
+ findings.push({ rule: 'lint/target-root', itemId: id, message: `target.root 必须是 home 下的相对路径:${root}` });
175
+ }
176
+ for (const forbidden of ['version', 'layout']) {
177
+ if (forbidden in target) {
178
+ findings.push({ rule: 'lint/target-forbidden', itemId: id, message: `target 不得携带 ${forbidden}` });
179
+ }
180
+ }
181
+ }
182
+ const onMissing = raw['onMissing'];
183
+ if (onMissing !== undefined) {
184
+ if (!isRecord(onMissing)) {
185
+ findings.push({ rule: 'lint/on-missing', itemId: id, message: 'onMissing 必须是对象' });
186
+ }
187
+ else {
188
+ const atStartup = onMissing['atStartup'];
189
+ if (atStartup !== undefined && atStartup !== 'degrade' && atStartup !== 'refuse') {
190
+ findings.push({ rule: 'lint/on-missing', itemId: id, message: `onMissing.atStartup 非法:${String(atStartup)}` });
191
+ }
192
+ const atUse = onMissing['atUse'];
193
+ if (atUse !== undefined && atUse !== 'degrade' && atUse !== 'error') {
194
+ findings.push({ rule: 'lint/on-missing', itemId: id, message: `onMissing.atUse 非法:${String(atUse)}` });
195
+ }
196
+ }
197
+ }
198
+ const startup = raw['startup'];
199
+ if (startup !== undefined && startup !== 'blocking' && startup !== 'background') {
200
+ findings.push({ rule: 'lint/startup', itemId: id, message: `item.startup 非法:${String(startup)}(只能是 blocking / background)` });
201
+ }
202
+ const policy = raw['policy'];
203
+ if (policy !== undefined && isRecord(policy)) {
204
+ for (const key of Object.keys(policy)) {
205
+ if (IMPLEMENTED_POLICY_KEYS.includes(key))
206
+ continue;
207
+ if (UNIMPLEMENTED_POLICY_KEYS.includes(key)) {
208
+ findings.push({ rule: 'lint/policy-unimplemented', itemId: id, message: `policy.${key} 本实现不读取,设置它不会生效` });
209
+ continue;
210
+ }
211
+ if (!isNamespacedKind(key)) {
212
+ findings.push({ rule: 'lint/policy-key', itemId: id, message: `policy 的 provider 私有键必须带前缀:${key}` });
213
+ }
214
+ }
215
+ }
216
+ const needs = raw['needs'];
217
+ if (needs !== undefined) {
218
+ if (!Array.isArray(needs) || needs.some(need => typeof need !== 'string')) {
219
+ findings.push({ rule: 'lint/needs-shape', itemId: id, message: 'needs 必须是字符串数组' });
220
+ }
221
+ else {
222
+ needsOf.set(id, needs);
223
+ }
224
+ }
225
+ }
226
+ // Check needs for existence, cross-plugin references and cycles.
227
+ for (const [id, needs] of needsOf) {
228
+ for (const need of needs) {
229
+ if (!ids.has(need)) {
230
+ if (plugin !== undefined && need.includes(':') && !need.startsWith(`${plugin}:`)) {
231
+ findings.push({ rule: 'lint/needs-cross-plugin', itemId: id, message: `needs 不得跨插件引用:${need}` });
232
+ }
233
+ else {
234
+ findings.push({ rule: 'lint/needs-missing', itemId: id, message: `needs 引用了不存在的 id:${need}` });
235
+ }
236
+ }
237
+ }
238
+ }
239
+ const visiting = new Set();
240
+ const visited = new Set();
241
+ const visit = (id, path) => {
242
+ if (visited.has(id))
243
+ return;
244
+ if (visiting.has(id)) {
245
+ findings.push({ rule: 'lint/needs-cycle', itemId: id, message: `needs 成环:${[...path, id].join(' → ')}` });
246
+ return;
247
+ }
248
+ visiting.add(id);
249
+ for (const need of needsOf.get(id) ?? [])
250
+ if (ids.has(need))
251
+ visit(need, [...path, id]);
252
+ visiting.delete(id);
253
+ visited.add(id);
254
+ };
255
+ for (const id of needsOf.keys())
256
+ visit(id, []);
257
+ return { ok: findings.length === 0, findings };
258
+ }
259
+ /** Lint a manifest file's text; a JSON parse failure is itself a finding. */
260
+ export function lintManifestText(text) {
261
+ try {
262
+ return lintManifest(JSON.parse(text));
263
+ }
264
+ catch (error) {
265
+ return {
266
+ ok: false,
267
+ findings: [{ rule: 'lint/json', message: `manifest 不是合法 JSON:${error instanceof Error ? error.message : String(error)}` }],
268
+ };
269
+ }
270
+ }
271
+ //# sourceMappingURL=lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.js","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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"}
package/dist/lock.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { ProvisionLock } from './types.js';
2
+ /** `true` when the pid exists; `EPERM` counts as alive. */
3
+ export declare function pidIsAlive(pid: number): boolean;
4
+ export interface DefaultLockOptions {
5
+ /** Clock source; defaults to `Date.now`. */
6
+ readonly clock?: () => number;
7
+ /** Poll interval while waiting; defaults to 25 ms. */
8
+ readonly pollMs?: number;
9
+ }
10
+ /** The default {@link ProvisionLock}. */
11
+ export declare function defaultLock(options?: DefaultLockOptions): ProvisionLock;
12
+ //# sourceMappingURL=lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAc,aAAa,EAAE,MAAM,YAAY,CAAA;AAO3D,2DAA2D;AAC3D,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C;AAoBD,MAAM,WAAW,kBAAkB;IACjC,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAA;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,aAAa,CA2D3E"}
package/dist/lock.js ADDED
@@ -0,0 +1,93 @@
1
+ /**
2
+ * The default control-plane lock at `<home>/.envinit/.lock`.
3
+ * @module lock
4
+ */
5
+ import { mkdir, open, readFile, stat, unlink } from 'node:fs/promises';
6
+ import { dirname } from 'node:path';
7
+ import { ProvisionError } from './errors.js';
8
+ /** `true` when the pid exists; `EPERM` counts as alive. */
9
+ export function pidIsAlive(pid) {
10
+ try {
11
+ process.kill(pid, 0);
12
+ return true;
13
+ }
14
+ catch (error) {
15
+ return error.code === 'EPERM';
16
+ }
17
+ }
18
+ async function readHolder(path) {
19
+ try {
20
+ const parsed = JSON.parse(await readFile(path, 'utf8'));
21
+ if (typeof parsed !== 'object' || parsed === null)
22
+ return undefined;
23
+ const record = parsed;
24
+ const pid = record['pid'];
25
+ const startedAt = record['startedAt'];
26
+ if (typeof pid !== 'number' || typeof startedAt !== 'number')
27
+ return undefined;
28
+ return { pid, startedAt };
29
+ }
30
+ catch {
31
+ return undefined;
32
+ }
33
+ }
34
+ function sleep(ms) {
35
+ return new Promise(resolve => setTimeout(resolve, ms));
36
+ }
37
+ /** The default {@link ProvisionLock}. */
38
+ export function defaultLock(options = {}) {
39
+ const clock = options.clock ?? Date.now;
40
+ const pollMs = options.pollMs ?? 25;
41
+ return {
42
+ async acquire(path, { timeoutMs, staleMs }) {
43
+ // Ensure the control-plane directory exists.
44
+ await mkdir(dirname(path), { recursive: true });
45
+ const deadline = clock() + timeoutMs;
46
+ for (;;) {
47
+ const mine = { pid: process.pid, startedAt: clock() };
48
+ try {
49
+ const handle = await open(path, 'wx');
50
+ await handle.writeFile(JSON.stringify(mine), 'utf8');
51
+ await handle.close();
52
+ return {
53
+ dispose: () => {
54
+ // Remove the lock only while it is still ours.
55
+ void (async () => {
56
+ const holder = await readHolder(path);
57
+ if (holder?.pid === mine.pid && holder.startedAt === mine.startedAt) {
58
+ await unlink(path).catch(() => undefined);
59
+ }
60
+ })();
61
+ },
62
+ };
63
+ }
64
+ catch (error) {
65
+ // Only EEXIST is contention; any other error is rethrown.
66
+ if (error.code !== 'EEXIST') {
67
+ throw new ProvisionError('unknown-error', `无法创建锁 ${path}:${error instanceof Error ? error.message : String(error)}`);
68
+ }
69
+ }
70
+ const holder = await readHolder(path);
71
+ if (holder === undefined) {
72
+ // A missing or unreadable holder still honours the timeout budget.
73
+ if (clock() >= deadline) {
74
+ throw new ProvisionError('lock/timeout', `等待发布锁超时(${String(timeoutMs)} ms):${path} 存在但不是可读的锁文件`);
75
+ }
76
+ const stillThere = await stat(path).then(() => true, () => false);
77
+ if (stillThere)
78
+ await sleep(pollMs);
79
+ continue;
80
+ }
81
+ if (!pidIsAlive(holder.pid) && clock() - holder.startedAt > staleMs) {
82
+ await unlink(path).catch(() => undefined);
83
+ continue;
84
+ }
85
+ if (clock() >= deadline) {
86
+ throw new ProvisionError('lock/timeout', `等待发布锁超时(${String(timeoutMs)} ms):${path} 由 pid ${String(holder.pid)} 持有`);
87
+ }
88
+ await sleep(pollMs);
89
+ }
90
+ },
91
+ };
92
+ }
93
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { InstallManifest } from './types.js';
2
+ export declare const INSTALL_MANIFEST_FILE = "install.json";
3
+ export declare const MANIFEST_SCHEMA_VERSION = 1;
4
+ /** Map a legacy manifest onto today's field names. */
5
+ export declare function aliasLegacyManifest(raw: Record<string, unknown>, kind?: string): Record<string, unknown>;
6
+ /** Parse a manifest, applying the alias table; `undefined` when it is not a usable manifest. */
7
+ export declare function readInstallManifest(raw: unknown, kind?: string): InstallManifest | undefined;
8
+ /** Serialise a manifest to JSON bytes. */
9
+ export declare function encodeInstallManifest(manifest: InstallManifest): Uint8Array;
10
+ /** Decode bytes that are expected to be JSON; `undefined` when they are not. */
11
+ export declare function decodeJson(bytes: Uint8Array): unknown;
12
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,YAAY,CAAA;AAEjE,eAAO,MAAM,qBAAqB,iBAAiB,CAAA;AACnD,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAYxC,sDAAsD;AACtD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAaxG;AAED,gGAAgG;AAChG,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAyB5F;AAED,0CAA0C;AAC1C,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,CAE3E;AAED,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAMrD"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * `install.json` — the per-version-directory manifest.
3
+ * @module manifest
4
+ */
5
+ import { sriOfSha256 } from './integrity.js';
6
+ export const INSTALL_MANIFEST_FILE = 'install.json';
7
+ export const MANIFEST_SCHEMA_VERSION = 1;
8
+ const SOURCES = ['resolved', 'managed', 'installed', 'system', 'explicit'];
9
+ function isRecord(value) {
10
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
11
+ }
12
+ function str(value) {
13
+ return typeof value === 'string' && value !== '' ? value : undefined;
14
+ }
15
+ /** Map a legacy manifest onto today's field names. */
16
+ export function aliasLegacyManifest(raw, kind) {
17
+ const aliased = { ...raw };
18
+ if (aliased['name'] === undefined && raw['id'] !== undefined)
19
+ aliased['name'] = raw['id'];
20
+ if (aliased['integrity'] === undefined && raw['sha256'] !== undefined) {
21
+ // Hex digests are stored as SRI base64.
22
+ aliased['integrity'] = sriOfSha256(String(raw['sha256']));
23
+ }
24
+ if (aliased['tarball'] === undefined && raw['url'] !== undefined)
25
+ aliased['tarball'] = raw['url'];
26
+ if (aliased['entry'] === undefined && raw['binary'] !== undefined && kind === 'binary-archive') {
27
+ aliased['entry'] = `bin/${String(raw['binary'])}`;
28
+ }
29
+ if (aliased['schemaVersion'] === undefined)
30
+ aliased['schemaVersion'] = 0;
31
+ return aliased;
32
+ }
33
+ /** Parse a manifest, applying the alias table; `undefined` when it is not a usable manifest. */
34
+ export function readInstallManifest(raw, kind) {
35
+ if (!isRecord(raw))
36
+ return undefined;
37
+ const aliased = aliasLegacyManifest(raw, kind);
38
+ const name = str(aliased['name']);
39
+ const version = str(aliased['version']);
40
+ const dir = str(aliased['dir']) ?? version;
41
+ if (name === undefined || version === undefined || dir === undefined)
42
+ return undefined;
43
+ const source = str(aliased['source']);
44
+ const integrity = str(aliased['integrity']);
45
+ const tarball = str(aliased['tarball']);
46
+ const entry = str(aliased['entry']);
47
+ const entryDir = str(aliased['entryDir']);
48
+ return {
49
+ schemaVersion: typeof aliased['schemaVersion'] === 'number' ? aliased['schemaVersion'] : 0,
50
+ name,
51
+ version,
52
+ dir,
53
+ ...(integrity === undefined ? {} : { integrity }),
54
+ ...(tarball === undefined ? {} : { tarball }),
55
+ ...(entry === undefined ? {} : { entry }),
56
+ ...(entryDir === undefined ? {} : { entryDir }),
57
+ installed_at: str(aliased['installed_at']) ?? '',
58
+ source: source !== undefined && SOURCES.includes(source) ? source : 'managed',
59
+ layout: str(aliased['layout']) ?? '',
60
+ };
61
+ }
62
+ /** Serialise a manifest to JSON bytes. */
63
+ export function encodeInstallManifest(manifest) {
64
+ return new TextEncoder().encode(`${JSON.stringify(manifest, null, 2)}\n`);
65
+ }
66
+ /** Decode bytes that are expected to be JSON; `undefined` when they are not. */
67
+ export function decodeJson(bytes) {
68
+ try {
69
+ return JSON.parse(new TextDecoder().decode(bytes));
70
+ }
71
+ catch {
72
+ return undefined;
73
+ }
74
+ }
75
+ //# sourceMappingURL=manifest.js.map