@decohere/create 0.0.1-dev.46 → 0.0.1-dev.47

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.
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * Pack `@decohere/create` for the builder image with production deps bundled
4
- * from dist/release (local `file:` for `@decohere/*`) so `npm install -g --offline`
5
- * does not hit the registry.
4
+ * from dist/release. Direct `@decohere/*` dependencies are rewritten to `file:`
5
+ * (not `overrides` — npm EOVERRIDE rejects overriding a direct dep). Nested
6
+ * workspace packages get the same rewrite so `npm install` never hits the
7
+ * private registry. The image then `npm install -g --offline`.
6
8
  */
7
9
  import { spawnSync } from "node:child_process";
8
10
  import { readdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
@@ -46,22 +48,43 @@ export function collectWorkspacePackages(rootDir) {
46
48
  }
47
49
 
48
50
  /**
51
+ * @param {string} fromDir
52
+ * @param {string} pkgDir
53
+ */
54
+ export function fileSpec(fromDir, pkgDir) {
55
+ let rel = relative(fromDir, pkgDir) || ".";
56
+ rel = rel.replaceAll("\\", "/");
57
+ if (!rel.startsWith(".")) rel = `./${rel}`;
58
+ return `file:${rel}`;
59
+ }
60
+
61
+ /**
62
+ * Rewrite `@decohere/*` dependency specs to local `file:` paths.
63
+ * Must mutate `dependencies` (not `overrides`) — npm throws EOVERRIDE when an
64
+ * override conflicts with a direct dependency.
65
+ *
66
+ * @param {Record<string, unknown>} pkg
49
67
  * @param {string} fromDir
50
68
  * @param {WorkspacePackage[]} packages
51
- * @returns {Record<string, string>}
52
69
  */
53
- export function decohereFileOverrides(fromDir, packages) {
54
- /** @type {Record<string, string>} */
55
- const overrides = {};
70
+ export function rewriteDecohereDepsToFile(pkg, fromDir, packages) {
71
+ const byName = new Map(packages.map((item) => [item.name, item.dir]));
56
72
  const from = resolve(fromDir);
57
- for (const pkg of packages) {
58
- if (resolve(pkg.dir) === from) continue;
59
- let rel = relative(fromDir, pkg.dir) || ".";
60
- rel = rel.replaceAll("\\", "/");
61
- if (!rel.startsWith(".")) rel = `./${rel}`;
62
- overrides[pkg.name] = `file:${rel}`;
63
- }
64
- return overrides;
73
+ const rewrite = (deps) => {
74
+ if (deps == null || typeof deps !== "object" || Array.isArray(deps)) return deps;
75
+ const next = { .../** @type {Record<string, unknown>} */ (deps) };
76
+ for (const name of Object.keys(next)) {
77
+ const dir = byName.get(name);
78
+ if (dir == null || resolve(dir) === from) continue;
79
+ next[name] = fileSpec(fromDir, dir);
80
+ }
81
+ return next;
82
+ };
83
+ return {
84
+ ...pkg,
85
+ dependencies: rewrite(pkg.dependencies),
86
+ optionalDependencies: rewrite(pkg.optionalDependencies),
87
+ };
65
88
  }
66
89
 
67
90
  /**
@@ -74,25 +97,11 @@ export function productionDepNames(pkg) {
74
97
  return Object.keys(deps);
75
98
  }
76
99
 
77
- /**
78
- * @param {Record<string, unknown>} pkg
79
- * @param {Record<string, string>} overrides
80
- */
81
- export function withInstallOverrides(pkg, overrides) {
82
- const existing = pkg.overrides;
83
- const previous =
84
- existing != null && typeof existing === "object" && !Array.isArray(existing)
85
- ? /** @type {Record<string, unknown>} */ (existing)
86
- : {};
87
- return { ...pkg, overrides: { ...previous, ...overrides } };
88
- }
89
-
90
100
  /**
91
101
  * @param {Record<string, unknown>} pkg
92
102
  */
93
103
  export function withBundleDependencies(pkg) {
94
- const { overrides: _overrides, ...rest } = pkg;
95
- return { ...rest, bundleDependencies: productionDepNames(pkg) };
104
+ return { ...pkg, bundleDependencies: productionDepNames(pkg) };
96
105
  }
97
106
 
98
107
  function writeJson(path, value) {
@@ -114,17 +123,38 @@ export function packBuilderTgz(options) {
114
123
  const workspaceOut = resolve(options.workspaceOut);
115
124
  const dest = resolve(options.dest);
116
125
  const packageJsonPath = join(outDir, "package.json");
117
- const original = JSON.parse(readFileSync(packageJsonPath, "utf8"));
118
- const overrides = decohereFileOverrides(outDir, collectWorkspacePackages(workspaceOut));
119
- writeJson(packageJsonPath, withInstallOverrides(original, overrides));
120
- runNpm(outDir, ["install", "--omit=dev", "--ignore-scripts"]);
121
- writeJson(packageJsonPath, withBundleDependencies(original));
122
- const packed = runNpm(outDir, ["pack", "--pack-destination", dirname(dest)]);
123
- const tgzName = packed.split(/\r?\n/).at(-1)?.replace(/^.*\//, "");
124
- if (tgzName == null || tgzName === "") {
125
- throw new Error(`npm pack did not print a tarball name:\n${packed}`);
126
+ const packages = collectWorkspacePackages(workspaceOut);
127
+ const originals = packages.map((pkg) => {
128
+ const path = join(pkg.dir, "package.json");
129
+ return { path, original: JSON.parse(readFileSync(path, "utf8")) };
130
+ });
131
+ const createOriginal = originals.find((entry) => entry.path === packageJsonPath)?.original;
132
+ if (createOriginal == null) {
133
+ throw new Error(`No @decohere package.json at ${packageJsonPath}`);
134
+ }
135
+
136
+ try {
137
+ for (const { path, original } of originals) {
138
+ writeJson(path, rewriteDecohereDepsToFile(original, dirname(path), packages));
139
+ }
140
+ runNpm(outDir, ["install", "--omit=dev", "--ignore-scripts"]);
141
+ } finally {
142
+ for (const { path, original } of originals) {
143
+ writeJson(path, original);
144
+ }
145
+ }
146
+
147
+ writeJson(packageJsonPath, withBundleDependencies(createOriginal));
148
+ try {
149
+ const packed = runNpm(outDir, ["pack", "--pack-destination", dirname(dest)]);
150
+ const tgzName = packed.split(/\r?\n/).at(-1)?.replace(/^.*\//, "");
151
+ if (tgzName == null || tgzName === "") {
152
+ throw new Error(`npm pack did not print a tarball name:\n${packed}`);
153
+ }
154
+ renameSync(join(dirname(dest), tgzName), dest);
155
+ } finally {
156
+ writeJson(packageJsonPath, createOriginal);
126
157
  }
127
- renameSync(join(dirname(dest), tgzName), dest);
128
158
  return dest;
129
159
  }
130
160
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decohere/create",
3
- "version": "0.0.1-dev.46",
3
+ "version": "0.0.1-dev.47",
4
4
  "description": "Scaffold a new Decohere project — build with Forge, serve with Flux",
5
5
  "keywords": [
6
6
  "decohere",
@@ -21,7 +21,7 @@
21
21
  "test": "echo \"Error: no test specified\" && exit 1"
22
22
  },
23
23
  "dependencies": {
24
- "@decohere/nexus": "0.0.1-dev.46",
24
+ "@decohere/nexus": "0.0.1-dev.47",
25
25
  "commander": "^13.1.0",
26
26
  "openapi-to-postmanv2": "^5.0.0"
27
27
  },