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

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.
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env node
2
+ /**
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.
6
+ */
7
+ import { spawnSync } from "node:child_process";
8
+ import { readdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
9
+ import { dirname, join, relative, resolve } from "node:path";
10
+ import { fileURLToPath } from "node:url";
11
+
12
+ /**
13
+ * @typedef {{ name: string, dir: string }} WorkspacePackage
14
+ */
15
+
16
+ /**
17
+ * @param {string} rootDir
18
+ * @returns {WorkspacePackage[]}
19
+ */
20
+ export function collectWorkspacePackages(rootDir) {
21
+ /** @type {WorkspacePackage[]} */
22
+ const found = [];
23
+ const walk = (dir) => {
24
+ let entries;
25
+ try {
26
+ entries = readdirSync(dir, { withFileTypes: true });
27
+ } catch {
28
+ return;
29
+ }
30
+ for (const entry of entries) {
31
+ if (entry.name === "node_modules" || entry.name === ".git") continue;
32
+ const path = join(dir, entry.name);
33
+ if (entry.isDirectory()) {
34
+ walk(path);
35
+ continue;
36
+ }
37
+ if (entry.name !== "package.json") continue;
38
+ const pkg = JSON.parse(readFileSync(path, "utf8"));
39
+ if (typeof pkg.name === "string" && pkg.name.startsWith("@decohere/")) {
40
+ found.push({ name: pkg.name, dir });
41
+ }
42
+ }
43
+ };
44
+ walk(rootDir);
45
+ return found;
46
+ }
47
+
48
+ /**
49
+ * @param {string} fromDir
50
+ * @param {WorkspacePackage[]} packages
51
+ * @returns {Record<string, string>}
52
+ */
53
+ export function decohereFileOverrides(fromDir, packages) {
54
+ /** @type {Record<string, string>} */
55
+ const overrides = {};
56
+ 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;
65
+ }
66
+
67
+ /**
68
+ * @param {Record<string, unknown>} pkg
69
+ * @returns {string[]}
70
+ */
71
+ export function productionDepNames(pkg) {
72
+ const deps = pkg.dependencies;
73
+ if (deps == null || typeof deps !== "object") return [];
74
+ return Object.keys(deps);
75
+ }
76
+
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
+ /**
91
+ * @param {Record<string, unknown>} pkg
92
+ */
93
+ export function withBundleDependencies(pkg) {
94
+ const { overrides: _overrides, ...rest } = pkg;
95
+ return { ...rest, bundleDependencies: productionDepNames(pkg) };
96
+ }
97
+
98
+ function writeJson(path, value) {
99
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`);
100
+ }
101
+
102
+ function runNpm(cwd, args) {
103
+ const result = spawnSync("npm", args, { cwd, encoding: "utf8" });
104
+ if (result.status !== 0) {
105
+ throw new Error(
106
+ `npm ${args.join(" ")} failed (exit ${result.status}):\n${result.stderr}${result.stdout}`,
107
+ );
108
+ }
109
+ return result.stdout.trim();
110
+ }
111
+
112
+ export function packBuilderTgz(options) {
113
+ const outDir = resolve(options.outDir);
114
+ const workspaceOut = resolve(options.workspaceOut);
115
+ const dest = resolve(options.dest);
116
+ 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
+ }
127
+ renameSync(join(dirname(dest), tgzName), dest);
128
+ return dest;
129
+ }
130
+
131
+ function parseArgs(argv) {
132
+ /** @type {Record<string, string>} */
133
+ const parsed = {};
134
+ for (let i = 0; i < argv.length; i++) {
135
+ const arg = argv[i];
136
+ if (arg == null || !arg.startsWith("--")) continue;
137
+ const key = arg.slice(2);
138
+ const value = argv[i + 1];
139
+ if (value == null || value.startsWith("--")) {
140
+ throw new Error(`Missing value for --${key}`);
141
+ }
142
+ parsed[key] = value;
143
+ i++;
144
+ }
145
+ return parsed;
146
+ }
147
+
148
+ function main() {
149
+ const args = parseArgs(process.argv.slice(2));
150
+ const outDir = args["out-dir"];
151
+ const workspaceOut = args["workspace-out"];
152
+ const dest = args.dest;
153
+ if (outDir == null || workspaceOut == null || dest == null) {
154
+ throw new Error(
155
+ "Usage: pack-builder-tgz.mjs --out-dir <dir> --workspace-out <dir> --dest <create.tgz>",
156
+ );
157
+ }
158
+ packBuilderTgz({ outDir, workspaceOut, dest });
159
+ }
160
+
161
+ if (process.argv[1] != null && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
162
+ main();
163
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decohere/create",
3
- "version": "0.0.1-dev.44",
3
+ "version": "0.0.1-dev.46",
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.44",
24
+ "@decohere/nexus": "0.0.1-dev.46",
25
25
  "commander": "^13.1.0",
26
26
  "openapi-to-postmanv2": "^5.0.0"
27
27
  },