zyrk 0.3.7 → 0.3.9

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 (189) hide show
  1. package/VERSION +1 -1
  2. package/bin/zyrk.js +1 -1
  3. package/dist/cli/main.d.ts +54 -0
  4. package/dist/cli/main.d.ts.map +1 -0
  5. package/dist/cli/main.js +473 -0
  6. package/dist/cli/npm-delegate.d.ts +38 -0
  7. package/dist/cli/npm-delegate.d.ts.map +1 -0
  8. package/{src/cli/npm-delegate.ts → dist/cli/npm-delegate.js} +26 -55
  9. package/dist/cli/parse.d.ts +40 -0
  10. package/dist/cli/parse.d.ts.map +1 -0
  11. package/dist/cli/parse.js +78 -0
  12. package/dist/commands/dependencies.d.ts +12 -0
  13. package/dist/commands/dependencies.d.ts.map +1 -0
  14. package/dist/commands/dependencies.js +118 -0
  15. package/dist/commands/deploy.d.ts +15 -0
  16. package/dist/commands/deploy.d.ts.map +1 -0
  17. package/dist/commands/deploy.js +506 -0
  18. package/dist/commands/maintenance.d.ts +27 -0
  19. package/dist/commands/maintenance.d.ts.map +1 -0
  20. package/dist/commands/maintenance.js +198 -0
  21. package/dist/commands/patch.d.ts +38 -0
  22. package/dist/commands/patch.d.ts.map +1 -0
  23. package/dist/commands/patch.js +336 -0
  24. package/dist/commands/project.d.ts +15 -0
  25. package/dist/commands/project.d.ts.map +1 -0
  26. package/dist/commands/project.js +396 -0
  27. package/dist/commands/store.d.ts +10 -0
  28. package/dist/commands/store.d.ts.map +1 -0
  29. package/dist/commands/store.js +551 -0
  30. package/dist/config/paths.d.ts +37 -0
  31. package/dist/config/paths.d.ts.map +1 -0
  32. package/dist/config/paths.js +66 -0
  33. package/dist/dlx/create.d.ts +23 -0
  34. package/dist/dlx/create.d.ts.map +1 -0
  35. package/dist/dlx/create.js +59 -0
  36. package/dist/dlx/run.d.ts +54 -0
  37. package/dist/dlx/run.d.ts.map +1 -0
  38. package/dist/dlx/run.js +274 -0
  39. package/dist/errors.d.ts +68 -0
  40. package/dist/errors.d.ts.map +1 -0
  41. package/dist/errors.js +111 -0
  42. package/dist/extract/tarball.d.ts +82 -0
  43. package/dist/extract/tarball.d.ts.map +1 -0
  44. package/dist/extract/tarball.js +645 -0
  45. package/dist/fetch/all.d.ts +48 -0
  46. package/dist/fetch/all.d.ts.map +1 -0
  47. package/dist/fetch/all.js +127 -0
  48. package/dist/fetch/package.d.ts +45 -0
  49. package/dist/fetch/package.d.ts.map +1 -0
  50. package/dist/fetch/package.js +124 -0
  51. package/dist/fetch/registry.d.ts +109 -0
  52. package/dist/fetch/registry.d.ts.map +1 -0
  53. package/dist/fetch/registry.js +418 -0
  54. package/dist/install/import-npm.d.ts +4 -0
  55. package/dist/install/import-npm.d.ts.map +1 -0
  56. package/dist/install/import-npm.js +147 -0
  57. package/dist/install/lock.d.ts +8 -0
  58. package/dist/install/lock.d.ts.map +1 -0
  59. package/dist/install/lock.js +146 -0
  60. package/dist/install/metadata.d.ts +19 -0
  61. package/dist/install/metadata.d.ts.map +1 -0
  62. package/dist/install/metadata.js +79 -0
  63. package/dist/install/registry.d.ts +8 -0
  64. package/dist/install/registry.d.ts.map +1 -0
  65. package/dist/install/registry.js +59 -0
  66. package/dist/install/run.d.ts +32 -0
  67. package/dist/install/run.d.ts.map +1 -0
  68. package/dist/install/run.js +545 -0
  69. package/dist/lockfile/fingerprints.d.ts +35 -0
  70. package/dist/lockfile/fingerprints.d.ts.map +1 -0
  71. package/dist/lockfile/fingerprints.js +56 -0
  72. package/dist/lockfile/read.d.ts +27 -0
  73. package/dist/lockfile/read.d.ts.map +1 -0
  74. package/dist/lockfile/read.js +126 -0
  75. package/dist/lockfile/types.d.ts +74 -0
  76. package/dist/lockfile/types.d.ts.map +1 -0
  77. package/dist/lockfile/types.js +17 -0
  78. package/dist/lockfile/write.d.ts +39 -0
  79. package/dist/lockfile/write.d.ts.map +1 -0
  80. package/dist/lockfile/write.js +180 -0
  81. package/dist/log.d.ts +21 -0
  82. package/dist/log.d.ts.map +1 -0
  83. package/dist/log.js +79 -0
  84. package/dist/project/projection.d.ts +50 -0
  85. package/dist/project/projection.d.ts.map +1 -0
  86. package/dist/project/projection.js +276 -0
  87. package/dist/resolve/resolver.d.ts +75 -0
  88. package/dist/resolve/resolver.d.ts.map +1 -0
  89. package/dist/resolve/resolver.js +533 -0
  90. package/dist/resolve/spec.d.ts +26 -0
  91. package/dist/resolve/spec.d.ts.map +1 -0
  92. package/dist/resolve/spec.js +87 -0
  93. package/dist/store/db.d.ts +49 -0
  94. package/dist/store/db.d.ts.map +1 -0
  95. package/{src/store/db.ts → dist/store/db.js} +106 -206
  96. package/dist/store/graph.d.ts +60 -0
  97. package/dist/store/graph.d.ts.map +1 -0
  98. package/dist/store/graph.js +115 -0
  99. package/dist/store/layout.d.ts +71 -0
  100. package/dist/store/layout.d.ts.map +1 -0
  101. package/dist/store/layout.js +282 -0
  102. package/dist/store/manifests.d.ts +78 -0
  103. package/dist/store/manifests.d.ts.map +1 -0
  104. package/dist/store/manifests.js +238 -0
  105. package/dist/store/objects.d.ts +56 -0
  106. package/dist/store/objects.d.ts.map +1 -0
  107. package/dist/store/objects.js +157 -0
  108. package/dist/store/realize.d.ts +38 -0
  109. package/dist/store/realize.d.ts.map +1 -0
  110. package/dist/store/realize.js +227 -0
  111. package/dist/store/source.d.ts +42 -0
  112. package/dist/store/source.d.ts.map +1 -0
  113. package/dist/store/source.js +169 -0
  114. package/dist/store/txn.d.ts +37 -0
  115. package/dist/store/txn.d.ts.map +1 -0
  116. package/dist/store/txn.js +97 -0
  117. package/dist/store/verify.d.ts +40 -0
  118. package/dist/store/verify.d.ts.map +1 -0
  119. package/dist/store/verify.js +396 -0
  120. package/dist/util/fsx.d.ts +54 -0
  121. package/dist/util/fsx.d.ts.map +1 -0
  122. package/dist/util/fsx.js +259 -0
  123. package/dist/util/hash.d.ts +48 -0
  124. package/dist/util/hash.d.ts.map +1 -0
  125. package/dist/util/hash.js +80 -0
  126. package/dist/util/ids.d.ts +19 -0
  127. package/dist/util/ids.d.ts.map +1 -0
  128. package/dist/util/ids.js +38 -0
  129. package/dist/util/integrity.d.ts +97 -0
  130. package/dist/util/integrity.d.ts.map +1 -0
  131. package/dist/util/integrity.js +192 -0
  132. package/dist/util/json.d.ts +14 -0
  133. package/dist/util/json.d.ts.map +1 -0
  134. package/dist/util/json.js +78 -0
  135. package/dist/util/locks.d.ts +40 -0
  136. package/dist/util/locks.d.ts.map +1 -0
  137. package/dist/util/locks.js +186 -0
  138. package/dist/util/proc.d.ts +32 -0
  139. package/dist/util/proc.d.ts.map +1 -0
  140. package/dist/util/proc.js +84 -0
  141. package/dist/version.d.ts +27 -0
  142. package/dist/version.d.ts.map +1 -0
  143. package/{src/version.ts → dist/version.js} +0 -8
  144. package/package.json +5 -3
  145. package/src/cli/main.ts +0 -468
  146. package/src/cli/parse.ts +0 -106
  147. package/src/commands/dependencies.ts +0 -154
  148. package/src/commands/deploy.ts +0 -777
  149. package/src/commands/maintenance.ts +0 -260
  150. package/src/commands/patch.ts +0 -408
  151. package/src/commands/project.ts +0 -598
  152. package/src/commands/store.ts +0 -689
  153. package/src/config/paths.ts +0 -119
  154. package/src/dlx/create.ts +0 -69
  155. package/src/dlx/run.ts +0 -389
  156. package/src/errors.ts +0 -142
  157. package/src/extract/tarball.ts +0 -868
  158. package/src/fetch/all.ts +0 -206
  159. package/src/fetch/package.ts +0 -181
  160. package/src/fetch/registry.ts +0 -615
  161. package/src/install/import-npm.ts +0 -177
  162. package/src/install/lock.ts +0 -176
  163. package/src/install/metadata.ts +0 -122
  164. package/src/install/registry.ts +0 -88
  165. package/src/install/run.ts +0 -760
  166. package/src/lockfile/fingerprints.ts +0 -74
  167. package/src/lockfile/read.ts +0 -198
  168. package/src/lockfile/types.ts +0 -75
  169. package/src/lockfile/write.ts +0 -257
  170. package/src/log.ts +0 -100
  171. package/src/project/projection.ts +0 -390
  172. package/src/resolve/resolver.ts +0 -757
  173. package/src/resolve/spec.ts +0 -131
  174. package/src/store/graph.ts +0 -175
  175. package/src/store/layout.ts +0 -431
  176. package/src/store/manifests.ts +0 -347
  177. package/src/store/objects.ts +0 -229
  178. package/src/store/realize.ts +0 -322
  179. package/src/store/source.ts +0 -249
  180. package/src/store/txn.ts +0 -118
  181. package/src/store/verify.ts +0 -433
  182. package/src/types/vendor.d.ts +0 -120
  183. package/src/util/fsx.ts +0 -289
  184. package/src/util/hash.ts +0 -117
  185. package/src/util/ids.ts +0 -42
  186. package/src/util/integrity.ts +0 -269
  187. package/src/util/json.ts +0 -89
  188. package/src/util/locks.ts +0 -266
  189. package/src/util/proc.ts +0 -108
@@ -1,177 +0,0 @@
1
- /** Adopt npm v2/v3 exact selections without asking the registry to pick versions. */
2
- import { valid, satisfies } from "semver";
3
- import type { NpmLockDoc } from "../lockfile/types.ts";
4
- import type {
5
- FinalizedGraph,
6
- ResolvedOccurrence,
7
- } from "../resolve/resolver.ts";
8
- import { parseRequirement } from "../resolve/spec.ts";
9
- import { sourceIdOf, sha512Hex } from "../util/hash.ts";
10
- import { cleanUrl, lockMismatch, packageName } from "./lock.ts";
11
-
12
- export function importNpmLock(
13
- doc: NpmLockDoc,
14
- requirements: Record<string, string>,
15
- origin: string,
16
- ): FinalizedGraph {
17
- const packages = doc.packages;
18
- if (!packages || !packages[""])
19
- throw lockMismatch("npm lockfile lacks an importer manifest");
20
- const locations = new Map<string, ResolvedOccurrence>();
21
- const find = (from: string, name: string): string | undefined => {
22
- let current = from;
23
- for (;;) {
24
- if (!current.endsWith("node_modules")) {
25
- const candidate = `${current ? `${current}/` : ""}node_modules/${name}`;
26
- if (packages[candidate]) return candidate;
27
- }
28
- if (!current) return undefined;
29
- current = current.includes("/")
30
- ? current.slice(0, current.lastIndexOf("/"))
31
- : "";
32
- }
33
- };
34
- const load = (
35
- location: string,
36
- edgeName: string,
37
- spec: string,
38
- ): ResolvedOccurrence => {
39
- const existing = locations.get(location);
40
- const entry = packages[location];
41
- if (!entry || entry.link === true || entry.inBundle === true)
42
- throw lockMismatch(
43
- "npm lock contains an unsupported linked or bundled selection",
44
- );
45
- const request = parseRequirement(edgeName, spec);
46
- const name = typeof entry.name === "string" ? entry.name : request.realName;
47
- if (
48
- !packageName(name) ||
49
- name !== request.realName ||
50
- typeof entry.version !== "string" ||
51
- valid(entry.version) === null ||
52
- typeof entry.resolved !== "string" ||
53
- !cleanUrl(entry.resolved) ||
54
- typeof entry.integrity !== "string" ||
55
- !/^sha512-[A-Za-z0-9+/]{86}==$/.test(entry.integrity)
56
- )
57
- throw lockMismatch(
58
- "npm selection lacks a valid name, version, archive, or SHA-512 integrity",
59
- );
60
- if (
61
- request.targetKind !== "tag" &&
62
- !satisfies(entry.version, request.targetSpec)
63
- )
64
- throw lockMismatch("npm selection disagrees with a manifest requirement");
65
- // Every incoming edge must satisfy its requirement, including a cycle or
66
- // a location already selected by a different dependency.
67
- if (existing) return existing;
68
- const node: ResolvedOccurrence = {
69
- key: `${name}@${entry.version}#${sha512Hex(location).slice(0, 16)}`,
70
- name,
71
- version: entry.version,
72
- origin,
73
- integrity: entry.integrity,
74
- sourceId: sourceIdOf({
75
- sourceType: "registry",
76
- name,
77
- version: entry.version,
78
- origin,
79
- integrity: entry.integrity,
80
- }),
81
- tarballUrl: entry.resolved,
82
- bin: {},
83
- platform: {},
84
- edges: [],
85
- peerBindings: [],
86
- };
87
- if (entry.engines !== undefined) {
88
- if (
89
- typeof entry.engines !== "object" ||
90
- entry.engines === null ||
91
- Array.isArray(entry.engines) ||
92
- Object.values(entry.engines).some((value) => typeof value !== "string")
93
- )
94
- throw lockMismatch("invalid npm engine constraint");
95
- node.engines = entry.engines as Record<string, string>;
96
- }
97
- if (
98
- typeof entry.bin === "object" &&
99
- entry.bin !== null &&
100
- !Array.isArray(entry.bin)
101
- ) {
102
- for (const [key, value] of Object.entries(entry.bin)) {
103
- if (typeof value !== "string")
104
- throw lockMismatch("invalid npm binary entry");
105
- node.bin[key] = value;
106
- }
107
- }
108
- for (const field of ["os", "cpu", "libc"] as const) {
109
- const value = entry[field];
110
- if (value !== undefined) {
111
- if (!Array.isArray(value) || !value.every((v) => typeof v === "string"))
112
- throw lockMismatch("invalid npm platform constraint");
113
- node.platform[field] = value as string[];
114
- }
115
- }
116
- locations.set(location, node);
117
- const dependencies: Record<
118
- string,
119
- { spec: string; kind: "prod" | "optional" | "peer" }
120
- > = Object.create(null) as Record<
121
- string,
122
- { spec: string; kind: "prod" | "optional" | "peer" }
123
- >;
124
- for (const [group, kind] of [
125
- ["dependencies", "prod"],
126
- ["optionalDependencies", "optional"],
127
- ["peerDependencies", "peer"],
128
- ] as const) {
129
- const entries = entry[group];
130
- if (entries === undefined) continue;
131
- if (
132
- typeof entries !== "object" ||
133
- entries === null ||
134
- Array.isArray(entries)
135
- )
136
- throw lockMismatch("invalid npm dependency declarations");
137
- for (const [dep, range] of Object.entries(entries)) {
138
- if (!packageName(dep) || typeof range !== "string")
139
- throw lockMismatch("invalid npm dependency requirement");
140
- dependencies[dep] = { spec: range, kind };
141
- }
142
- }
143
- for (const [dep, requirement] of Object.entries(dependencies)) {
144
- const targetLocation = find(location, dep);
145
- const meta = entry.peerDependenciesMeta as
146
- Record<string, { optional?: boolean }> | undefined;
147
- const optionalPeer =
148
- requirement.kind === "peer" && meta?.[dep]?.optional === true;
149
- if (!targetLocation) {
150
- if (requirement.kind === "optional" || optionalPeer) {
151
- if (optionalPeer) node.peerBindings.push({ name: dep, target: null });
152
- continue;
153
- }
154
- throw lockMismatch("npm lock is missing a required dependency");
155
- }
156
- const target = load(targetLocation, dep, requirement.spec);
157
- node.edges.push({
158
- name: dep,
159
- target: target.key,
160
- kind: requirement.kind,
161
- spec: requirement.spec,
162
- });
163
- if (requirement.kind === "peer")
164
- node.peerBindings.push({ name: dep, target: target.key });
165
- }
166
- return node;
167
- };
168
- const roots = Object.entries(requirements).map(([name, spec]) => {
169
- const location = find("", name);
170
- if (!location) throw lockMismatch("npm lock is missing a direct selection");
171
- return { name, target: load(location, name, spec).key };
172
- });
173
- return {
174
- nodes: [...locations.values()].sort((a, b) => a.key.localeCompare(b.key)),
175
- roots,
176
- };
177
- }
@@ -1,176 +0,0 @@
1
- /** Validate locked graph data before it can address any store/project paths. */
2
- import { valid } from "semver";
3
- import { ZyrkError } from "../errors.ts";
4
- import type { NpmLockDoc } from "../lockfile/types.ts";
5
- import { ZYRK_RESOLVER_POLICY } from "../lockfile/types.ts";
6
- import type {
7
- FinalizedGraph,
8
- ResolvedOccurrence,
9
- } from "../resolve/resolver.ts";
10
- import { sourceIdOf } from "../util/hash.ts";
11
- import { CONTEXT_CANONICALIZATION_VERSION } from "../version.ts";
12
- import { createGraphDoc } from "../store/graph.ts";
13
-
14
- export function packageName(name: string): boolean {
15
- return (
16
- /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/.test(name) &&
17
- !["node_modules", "__proto__", "constructor", "prototype"].includes(name) &&
18
- name.length <= 214
19
- );
20
- }
21
- export function cleanUrl(value: string): boolean {
22
- try {
23
- const url = new URL(value);
24
- return (
25
- ["https:", "http:"].includes(url.protocol) &&
26
- !url.username &&
27
- !url.password &&
28
- !url.search &&
29
- !url.hash
30
- );
31
- } catch {
32
- return false;
33
- }
34
- }
35
- export function lockMismatch(why: string): ZyrkError {
36
- return new ZyrkError(
37
- "ZYRK_LOCK_MISMATCH",
38
- `cannot install the locked graph (${why}).`,
39
- {
40
- remedy:
41
- "Restore a compatible package-lock.json, or refresh it intentionally with zyrk install after reviewing dependency changes.",
42
- },
43
- );
44
- }
45
- function record(value: unknown): value is Record<string, unknown> {
46
- return typeof value === "object" && value !== null && !Array.isArray(value);
47
- }
48
- export function lockedGraph(doc: NpmLockDoc): FinalizedGraph {
49
- const ext = doc.zyrk;
50
- if (
51
- !ext ||
52
- ext.resolver !== ZYRK_RESOLVER_POLICY ||
53
- ext.contextCanonicalization !== CONTEXT_CANONICALIZATION_VERSION ||
54
- !record(ext.nodes) ||
55
- !record(ext.roots) ||
56
- !record(ext.roots["."])
57
- )
58
- throw lockMismatch("unsupported graph metadata");
59
- const nodes: ResolvedOccurrence[] = [];
60
- for (const [key, raw] of Object.entries(ext.nodes)) {
61
- if (
62
- !record(raw) ||
63
- typeof raw.name !== "string" ||
64
- !packageName(raw.name) ||
65
- typeof raw.version !== "string" ||
66
- valid(raw.version) === null ||
67
- typeof raw.integrity !== "string" ||
68
- !/^sha512-[A-Za-z0-9+/]{86}==$/.test(raw.integrity) ||
69
- typeof raw.origin !== "string" ||
70
- !cleanUrl(raw.origin) ||
71
- typeof raw.tarball !== "string" ||
72
- !cleanUrl(raw.tarball) ||
73
- !record(raw.edges) ||
74
- !record(raw.edgeKinds) ||
75
- !record(raw.peers) ||
76
- !record(raw.bin) ||
77
- !record(raw.platform)
78
- )
79
- throw lockMismatch("invalid node record");
80
- const identity = {
81
- sourceType: "registry" as const,
82
- name: raw.name,
83
- version: raw.version,
84
- origin: raw.origin,
85
- integrity: raw.integrity,
86
- };
87
- if (sourceIdOf(identity) !== raw.source)
88
- throw lockMismatch("source identity disagrees with locked inputs");
89
- const edges: ResolvedOccurrence["edges"] = [];
90
- for (const [name, target] of Object.entries(raw.edges)) {
91
- const kind = raw.edgeKinds[name];
92
- if (
93
- !packageName(name) ||
94
- typeof target !== "string" ||
95
- !["prod", "optional", "peer"].includes(String(kind))
96
- )
97
- throw lockMismatch("invalid dependency edge");
98
- edges.push({
99
- name,
100
- target,
101
- kind: kind as "prod" | "optional" | "peer",
102
- spec: "",
103
- });
104
- }
105
- const peers: ResolvedOccurrence["peerBindings"] = [];
106
- for (const [name, target] of Object.entries(raw.peers)) {
107
- if (
108
- !packageName(name) ||
109
- (target !== null && typeof target !== "string") ||
110
- (target !== null && raw.edges[name] !== target)
111
- )
112
- throw lockMismatch("invalid peer binding");
113
- peers.push({ name, target });
114
- }
115
- const bin: Record<string, string> = Object.create(null) as Record<
116
- string,
117
- string
118
- >;
119
- for (const [name, target] of Object.entries(raw.bin)) {
120
- if (
121
- !/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(name) ||
122
- typeof target !== "string"
123
- )
124
- throw lockMismatch("invalid binary entry");
125
- bin[name] = target;
126
- }
127
- const platform: ResolvedOccurrence["platform"] = {};
128
- for (const field of ["os", "cpu", "libc"] as const) {
129
- const list = raw.platform[field];
130
- if (list !== undefined) {
131
- if (
132
- !Array.isArray(list) ||
133
- !list.every((item: unknown) => typeof item === "string")
134
- )
135
- throw lockMismatch("invalid platform constraints");
136
- platform[field] = list as string[];
137
- }
138
- }
139
- const engines: Record<string, string> = {};
140
- if (raw.engines !== undefined) {
141
- if (!record(raw.engines))
142
- throw lockMismatch("invalid engine constraints");
143
- for (const [name, value] of Object.entries(raw.engines)) {
144
- if (typeof value !== "string")
145
- throw lockMismatch("invalid engine constraint");
146
- engines[name] = value;
147
- }
148
- }
149
- nodes.push({
150
- key,
151
- ...identity,
152
- sourceId: raw.source as string,
153
- tarballUrl: raw.tarball,
154
- bin,
155
- engines,
156
- platform,
157
- edges,
158
- peerBindings: peers,
159
- });
160
- }
161
- const roots = Object.entries(ext.roots["."]).map(([name, target]) => {
162
- if (
163
- !packageName(name) ||
164
- typeof target !== "string" ||
165
- !nodes.some((node) => node.key === target)
166
- )
167
- throw lockMismatch("invalid importer root");
168
- return { name, target: target as string };
169
- });
170
- try {
171
- createGraphDoc(nodes.map((n) => ({ ...n, deps: n.edges })));
172
- } catch {
173
- throw lockMismatch("invalid dependency graph");
174
- }
175
- return { nodes, roots };
176
- }
@@ -1,122 +0,0 @@
1
- /** Durable project roots and exact physical instances (SPEC 14.4, 18, 30). */
2
- import { stat } from "node:fs/promises";
3
- import * as path from "node:path";
4
- import {
5
- openStoreDb,
6
- recordSource,
7
- recordObject,
8
- withTransaction,
9
- } from "../store/db.ts";
10
- import { Store } from "../store/layout.ts";
11
- import { readSourceManifest } from "../store/manifests.ts";
12
- import { contextIdFor, graphHash, type GraphDoc } from "../store/graph.ts";
13
- import type { RealizeResult } from "../store/realize.ts";
14
- import { sha512Hex } from "../util/hash.ts";
15
- import { STORE_FORMAT_VERSION } from "../version.ts";
16
-
17
- export async function registerGeneration(options: {
18
- store: Store;
19
- project: string;
20
- projectId: string;
21
- generationId: string;
22
- graph: GraphDoc;
23
- realized: RealizeResult;
24
- roots: readonly string[];
25
- readiness: "ready" | "intentionally-unbuilt";
26
- }): Promise<{
27
- instances: string[];
28
- contexts: string[];
29
- activate(): void;
30
- close(): void;
31
- }> {
32
- const { store, project, projectId, generationId, graph, realized } = options;
33
- const db = openStoreDb(store.paths.dbFile);
34
- try {
35
- for (const node of graph.nodes) {
36
- const doc = await readSourceManifest(store, node.sourceId);
37
- const m = doc.manifest;
38
- recordSource(db, {
39
- sourceId: m.sourceId,
40
- sourceType: "registry",
41
- name: m.name,
42
- version: m.version,
43
- origin: m.origin,
44
- integrity: m.integrity,
45
- manifestHash: doc.manifestHash,
46
- extractionPolicyVersion: m.extractionPolicyVersion,
47
- logicalBytes: m.totals.logicalBytes,
48
- fileCount: m.totals.files,
49
- entryCount: m.entries.length,
50
- verifiedAt: doc.provenance.verifiedAt,
51
- });
52
- for (const entry of m.entries)
53
- if (entry.type === "file")
54
- recordObject(db, {
55
- objectId: entry.objectId,
56
- innerDigest: entry.innerDigest,
57
- modeClass: entry.mode,
58
- bytes: entry.size,
59
- committedAt: doc.provenance.verifiedAt,
60
- });
61
- }
62
- const now = new Date().toISOString();
63
- const fs = await stat(project);
64
- const contexts: string[] = [];
65
- const instances: string[] = [];
66
- withTransaction(db, () => {
67
- db.prepare(
68
- "INSERT INTO projects(project_id,canonical_path,fs_dev,fs_ino,created_at,last_seen_at) VALUES(?,?,?,?,?,?) ON CONFLICT(project_id) DO UPDATE SET last_seen_at=excluded.last_seen_at",
69
- ).run(projectId, project, String(fs.dev), String(fs.ino), now, now);
70
- db.prepare(
71
- "INSERT INTO generations(generation_id,project_id,graph_digest,readiness,state,created_at) VALUES(?,?,?,?,'pending',?)",
72
- ).run(generationId, projectId, graphHash(graph), options.readiness, now);
73
- for (const node of graph.nodes) {
74
- const context = contextIdFor(graph, node.key);
75
- const directory = realized.realizationDirByKey.get(node.key)!;
76
- const instance = `inst1_${sha512Hex(directory).slice(0, 32)}`;
77
- contexts.push(context);
78
- instances.push(instance);
79
- db.prepare(
80
- "INSERT INTO realizations(context_id,descriptor_hash,source_id,readiness,store_format,created_at) VALUES(?,?,?,'ready',?,?) ON CONFLICT(context_id) DO NOTHING",
81
- ).run(context, context, node.sourceId, STORE_FORMAT_VERSION, now);
82
- db.prepare(
83
- "INSERT INTO realization_instances(instance_id,context_id,path,verification_state,created_at) VALUES(?,?,?,'verified',?) ON CONFLICT(instance_id) DO NOTHING",
84
- ).run(instance, context, directory, now);
85
- db.prepare(
86
- "INSERT INTO generation_instances(generation_id,context_id,instance_id,direct_link) VALUES(?,?,?,?) ON CONFLICT(generation_id,context_id) DO NOTHING",
87
- ).run(
88
- generationId,
89
- context,
90
- instance,
91
- options.roots.includes(node.key) ? 1 : 0,
92
- );
93
- }
94
- db.prepare(
95
- "INSERT INTO roots(root_id,project_id,generation_id,kind,state,created_at) VALUES(?,?,?,'pending','active',?)",
96
- ).run(`root1_${generationId}`, projectId, generationId, now);
97
- });
98
- return {
99
- contexts,
100
- instances,
101
- activate() {
102
- withTransaction(db, () => {
103
- db.prepare(
104
- "UPDATE generations SET state='rollback' WHERE project_id=? AND state='active' AND generation_id<>?",
105
- ).run(projectId, generationId);
106
- db.prepare(
107
- "UPDATE generations SET state='active',activated_at=? WHERE generation_id=?",
108
- ).run(new Date().toISOString(), generationId);
109
- db.prepare(
110
- "UPDATE roots SET kind='generation' WHERE generation_id=?",
111
- ).run(generationId);
112
- });
113
- },
114
- close() {
115
- db.close();
116
- },
117
- };
118
- } catch (cause) {
119
- db.close();
120
- throw cause;
121
- }
122
- }
@@ -1,88 +0,0 @@
1
- /** Fail closed on registry settings the current single-registry adapter cannot honor. */
2
- import { readFile } from "node:fs/promises";
3
- import * as path from "node:path";
4
- import * as os from "node:os";
5
- import { ZyrkError } from "../errors.ts";
6
- import { RegistryClient, DEFAULT_REGISTRY } from "../fetch/registry.ts";
7
- import { isErrno } from "../util/fsx.ts";
8
- import { cleanUrl } from "./lock.ts";
9
-
10
- export async function installRegistry(options: {
11
- cwd: string;
12
- env: NodeJS.ProcessEnv;
13
- version: string;
14
- registry?: string;
15
- }): Promise<RegistryClient> {
16
- let registry = DEFAULT_REGISTRY;
17
- const home = options.env.HOME ?? os.homedir();
18
- const files = [
19
- options.env.npm_config_userconfig ?? path.join(home, ".npmrc"),
20
- path.join(options.cwd, ".npmrc"),
21
- ];
22
- for (const file of files) {
23
- let text: string;
24
- try {
25
- text = await readFile(file, "utf8");
26
- } catch (cause) {
27
- if (isErrno(cause, "ENOENT")) continue;
28
- throw new ZyrkError(
29
- "ZYRK_POLICY_DENIED",
30
- "Cannot read npm registry configuration.",
31
- {
32
- remedy: "Make the user and project .npmrc readable before retrying.",
33
- },
34
- );
35
- }
36
- for (const line of text.split(/\r?\n/)) {
37
- const trimmed = line.trim();
38
- if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith(";"))
39
- continue;
40
- const index = trimmed.indexOf("=");
41
- const key = trimmed.slice(0, index).trim();
42
- const value = trimmed.slice(index + 1).trim();
43
- if (key === "registry") registry = value;
44
- if (/^@.+:registry$/.test(key))
45
- throw new ZyrkError(
46
- "ZYRK_POLICY_DENIED",
47
- "Scoped registry routing is not supported by project install yet.",
48
- {
49
- remedy:
50
- "Use npm for mixed-registry projects; zyrk will not silently fetch a private scope from a public registry.",
51
- },
52
- );
53
- if (key === "strict-ssl" && value === "false")
54
- throw new ZyrkError(
55
- "ZYRK_POLICY_DENIED",
56
- "Disabling registry TLS verification is not supported.",
57
- {
58
- remedy:
59
- "Configure a trusted HTTPS registry with valid TLS certificates.",
60
- },
61
- );
62
- }
63
- }
64
- registry = options.registry ?? options.env.npm_config_registry ?? registry;
65
- if (!cleanUrl(registry))
66
- throw new ZyrkError(
67
- "ZYRK_POLICY_DENIED",
68
- "Registry URL must be HTTP(S) without credentials, query parameters, or fragments.",
69
- {
70
- remedy:
71
- "Use a credential-free registry URL. Authenticated private registries are not supported by project install yet.",
72
- },
73
- );
74
- const url = new URL(registry);
75
- if (
76
- url.protocol !== "https:" &&
77
- !["127.0.0.1", "localhost", "[::1]"].includes(url.hostname)
78
- )
79
- throw new ZyrkError(
80
- "ZYRK_POLICY_DENIED",
81
- "Remote registries require HTTPS.",
82
- {
83
- remedy:
84
- "Select an HTTPS registry; HTTP is limited to loopback development registries.",
85
- },
86
- );
87
- return new RegistryClient({ registry, userAgent: `zyrk/${options.version}` });
88
- }