@dbx-tools/projen 0.9.21 → 0.9.29
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/README.md +77 -207
- package/index.ts +10 -14
- package/package.json +4 -4
- package/src/barrels.ts +1 -74
- package/src/module-exports.ts +175 -1
- package/src/openapi.ts +5 -72
- package/src/packages.ts +45 -0
- package/src/project-js.ts +3 -6
- package/src/project-predicate.ts +1 -2
- package/src/project-py.ts +82 -103
- package/src/project.ts +2 -2
- package/src/python-node-bindings.ts +138 -0
- package/src/python-node-bundle.ts +92 -0
- package/src/release-catalog.ts +3 -5
- package/src/{release-dispatch.ts → release-context.ts} +0 -11
- package/src/release.ts +70 -152
- package/tasks/bump.ts +12 -21
- package/tasks/databricks-cli-assets.ts +129 -0
- package/tasks/local-publish.ts +23 -107
- package/tasks/publish-npm.ts +10 -1
- package/tasks/publish-python.ts +26 -11
- package/tasks/publish.ts +12 -48
- package/tasks/python-node-bindings-watch.ts +47 -0
- package/tasks/python-node-bindings.ts +1017 -0
- package/tasks/python-release.ts +74 -0
- package/tasks/release.ts +99 -0
- package/tasks/sync.ts +13 -18
- package/tasks/version-check.ts +1 -28
- package/._LICENSE +0 -0
- package/._README.md +0 -0
- package/._index.ts +0 -0
- package/._package.json +0 -0
- package/src/.__lazy-require.ts +0 -0
- package/src/.__release-platform.ts +0 -0
- package/src/.__rust-project.ts +0 -0
- package/src/.__rust-release-workflow.ts +0 -0
- package/src/.__task-command.ts +0 -0
- package/src/._barrels.ts +0 -0
- package/src/._bun-app.ts +0 -0
- package/src/._bun-workflow.ts +0 -0
- package/src/._clean.ts +0 -0
- package/src/._codegen.ts +0 -0
- package/src/._dbx-tools-config.ts +0 -0
- package/src/._engine-root.ts +0 -0
- package/src/._generated.ts +0 -0
- package/src/._mixin.ts +0 -0
- package/src/._module-exports.ts +0 -0
- package/src/._openapi.ts +0 -0
- package/src/._packages.ts +0 -0
- package/src/._pnpm-workspace.ts +0 -0
- package/src/._project-js.ts +0 -0
- package/src/._project-predicate.ts +0 -0
- package/src/._project-py.ts +0 -0
- package/src/._project-rs.ts +0 -0
- package/src/._project.ts +0 -0
- package/src/._projen-version.ts +0 -0
- package/src/._publish.ts +0 -0
- package/src/._release-catalog.ts +0 -0
- package/src/._release-dispatch.ts +0 -0
- package/src/._release-github.ts +0 -0
- package/src/._release.ts +0 -0
- package/src/._scaffold.ts +0 -0
- package/src/._tags.ts +0 -0
- package/src/._tsconfig.ts +0 -0
- package/src/._uniffi.ts +0 -0
- package/src/._vscode.ts +0 -0
- package/src/._watch.ts +0 -0
- package/src/._workspace-lock.ts +0 -0
- package/src/._workspace-version.ts +0 -0
- package/src/_release-platform.ts +0 -78
- package/src/_rust-project.ts +0 -429
- package/src/_rust-release-workflow.ts +0 -311
- package/src/project-rs.ts +0 -1054
- package/src/release-github.ts +0 -109
- package/src/uniffi.ts +0 -65
- package/tasks/._barrels.ts +0 -0
- package/tasks/._bump.ts +0 -0
- package/tasks/._clean.ts +0 -0
- package/tasks/._compile-workspace.ts +0 -0
- package/tasks/._local-publish.ts +0 -0
- package/tasks/._openapi.ts +0 -0
- package/tasks/._projenrc.ts +0 -0
- package/tasks/._publish-npm.ts +0 -0
- package/tasks/._publish-python.ts +0 -0
- package/tasks/._publish-uniffi-local.ts +0 -0
- package/tasks/._publish.ts +0 -0
- package/tasks/._python-registry.ts +0 -0
- package/tasks/._release-assets.ts +0 -0
- package/tasks/._release-candidate.ts +0 -0
- package/tasks/._release-manifest.ts +0 -0
- package/tasks/._release-pr.ts +0 -0
- package/tasks/._release-summary.ts +0 -0
- package/tasks/._release-version.ts +0 -0
- package/tasks/._rust.ts +0 -0
- package/tasks/._sync.ts +0 -0
- package/tasks/._uniffi-python.d.ts +0 -0
- package/tasks/._uniffi-python.js +0 -0
- package/tasks/._uniffi-release.mjs +0 -0
- package/tasks/._uniffi.ts +0 -0
- package/tasks/._version-check.ts +0 -0
- package/tasks/publish-uniffi-local.ts +0 -359
- package/tasks/release-assets.ts +0 -467
- package/tasks/release-candidate.ts +0 -416
- package/tasks/release-manifest.ts +0 -273
- package/tasks/release-pr.ts +0 -589
- package/tasks/release-summary.ts +0 -379
- package/tasks/rust.ts +0 -173
- package/tasks/uniffi-python.d.ts +0 -60
- package/tasks/uniffi-python.js +0 -178
- package/tasks/uniffi-release.mjs +0 -579
- package/tasks/uniffi.ts +0 -262
package/tasks/uniffi-release.mjs
DELETED
|
@@ -1,579 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
chmodSync,
|
|
4
|
-
cpSync,
|
|
5
|
-
existsSync,
|
|
6
|
-
mkdirSync,
|
|
7
|
-
mkdtempSync,
|
|
8
|
-
readFileSync,
|
|
9
|
-
readdirSync,
|
|
10
|
-
rmSync,
|
|
11
|
-
statSync,
|
|
12
|
-
writeFileSync,
|
|
13
|
-
} from "node:fs";
|
|
14
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
15
|
-
import { tmpdir } from "node:os";
|
|
16
|
-
import { fileURLToPath } from "node:url";
|
|
17
|
-
import { createRequire } from "node:module";
|
|
18
|
-
import { parseArgs } from "node:util";
|
|
19
|
-
import { spawnSync } from "node:child_process";
|
|
20
|
-
import {
|
|
21
|
-
installPythonBindings,
|
|
22
|
-
preparePythonProjectForPublication,
|
|
23
|
-
pythonBindingGeneratorArgs,
|
|
24
|
-
pythonBindingGeneratorName,
|
|
25
|
-
} from "./uniffi-python.js";
|
|
26
|
-
|
|
27
|
-
const require = createRequire(import.meta.url);
|
|
28
|
-
const bundledToml = fileURLToPath(new URL("./smol-toml.cjs", import.meta.url));
|
|
29
|
-
const toml = require(existsSync(bundledToml) ? bundledToml : "smol-toml");
|
|
30
|
-
|
|
31
|
-
const parsed = parseArgs({
|
|
32
|
-
allowPositionals: true,
|
|
33
|
-
options: {
|
|
34
|
-
root: { type: "string" },
|
|
35
|
-
crate: { type: "string" },
|
|
36
|
-
node: { type: "string" },
|
|
37
|
-
python: { type: "string" },
|
|
38
|
-
"node-package": { type: "string" },
|
|
39
|
-
"native-package": { type: "string" },
|
|
40
|
-
"python-package": { type: "string" },
|
|
41
|
-
"python-module": { type: "string" },
|
|
42
|
-
"python-bindings": { type: "string" },
|
|
43
|
-
"cargo-target": { type: "string" },
|
|
44
|
-
"generator-target": { type: "string" },
|
|
45
|
-
"node-triple": { type: "string" },
|
|
46
|
-
"python-tag": { type: "string" },
|
|
47
|
-
os: { type: "string" },
|
|
48
|
-
cpu: { type: "string" },
|
|
49
|
-
libc: { type: "string" },
|
|
50
|
-
facade: { type: "string" },
|
|
51
|
-
version: { type: "string" },
|
|
52
|
-
output: { type: "string" },
|
|
53
|
-
"skip-build": { type: "boolean" },
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const required = (name) => {
|
|
58
|
-
const value = parsed.values[name];
|
|
59
|
-
if (!value) throw new Error(`Missing --${name}`);
|
|
60
|
-
return value;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const root = resolve(parsed.values.root ?? process.cwd());
|
|
64
|
-
const commandInvocation = (command, args) => {
|
|
65
|
-
if (process.platform !== "win32" || command !== "npm") return { command, args };
|
|
66
|
-
const npmCli = resolve(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
|
|
67
|
-
if (!existsSync(npmCli)) throw new Error(`Missing npm CLI ${npmCli}`);
|
|
68
|
-
return { command: process.execPath, args: [npmCli, ...args] };
|
|
69
|
-
};
|
|
70
|
-
const run = (command, args, cwd = root) => {
|
|
71
|
-
const invocation = commandInvocation(command, args);
|
|
72
|
-
const result = spawnSync(invocation.command, invocation.args, { cwd, stdio: "inherit" });
|
|
73
|
-
if (result.error) {
|
|
74
|
-
throw new Error(`${invocation.command} failed: ${result.error.message}`, {
|
|
75
|
-
cause: result.error,
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
if (result.status !== 0) throw new Error(`${invocation.command} exited with ${result.status}`);
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const runWithRetry = (command, args, cwd = root, attempts = 6) => {
|
|
82
|
-
const signal = new Int32Array(new SharedArrayBuffer(4));
|
|
83
|
-
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
84
|
-
const invocation = commandInvocation(command, args);
|
|
85
|
-
const result = spawnSync(invocation.command, invocation.args, { cwd, stdio: "inherit" });
|
|
86
|
-
if (result.error) {
|
|
87
|
-
throw new Error(`${invocation.command} failed: ${result.error.message}`, {
|
|
88
|
-
cause: result.error,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
if (result.status === 0) return;
|
|
92
|
-
if (attempt === attempts) {
|
|
93
|
-
throw new Error(
|
|
94
|
-
`${invocation.command} exited with ${result.status} after ${attempts} attempts`,
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
Atomics.wait(signal, 0, 0, 10_000);
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const singlePackage = (directory) => {
|
|
102
|
-
const packages = readdirSync(directory)
|
|
103
|
-
.filter((file) => file.endsWith(".tgz"))
|
|
104
|
-
.map((file) => resolve(directory, file));
|
|
105
|
-
if (packages.length !== 1) {
|
|
106
|
-
throw new Error(`Expected one npm package in ${directory}, found ${packages.length}`);
|
|
107
|
-
}
|
|
108
|
-
return packages[0];
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const localWorkspacePackages = () => {
|
|
112
|
-
const manifest = JSON.parse(readFileSync(resolve(root, "package.json"), "utf8"));
|
|
113
|
-
const workspaces = Array.isArray(manifest.workspaces) ? manifest.workspaces : [];
|
|
114
|
-
return new Map(
|
|
115
|
-
workspaces.flatMap((directory) => {
|
|
116
|
-
const manifestPath = resolve(root, directory, "package.json");
|
|
117
|
-
if (!existsSync(manifestPath)) return [];
|
|
118
|
-
const workspaceManifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
119
|
-
return workspaceManifest.name ? [[workspaceManifest.name, workspaceManifest.version]] : [];
|
|
120
|
-
}),
|
|
121
|
-
);
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Read one bundled facade's static imports so local workspace dependency stubs
|
|
126
|
-
* expose every requested ESM name. Callable proxy values support module helpers
|
|
127
|
-
* and base classes that execute while the facade is imported.
|
|
128
|
-
*/
|
|
129
|
-
const importedNames = (source, packageName) => {
|
|
130
|
-
const escaped = packageName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
131
|
-
const pattern = new RegExp(`(?:^|\\n)import\\s+([^;]+?)\\s+from\\s+["']${escaped}["'];`, "g");
|
|
132
|
-
const names = new Set();
|
|
133
|
-
let hasDefault = false;
|
|
134
|
-
for (const match of source.matchAll(pattern)) {
|
|
135
|
-
const clause = match[1].trim();
|
|
136
|
-
const named = /\{([\s\S]*?)\}/.exec(clause)?.[1];
|
|
137
|
-
if (named) {
|
|
138
|
-
for (const specifier of named.split(",")) {
|
|
139
|
-
const name = specifier.trim().split(/\s+as\s+/)[0];
|
|
140
|
-
if (name) names.add(name);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
const beforeNamed = clause.split(/[,{\s]/, 1)[0];
|
|
144
|
-
if (beforeNamed && beforeNamed !== "*" && !clause.startsWith("{")) hasDefault = true;
|
|
145
|
-
}
|
|
146
|
-
return { names: [...names].sort(), hasDefault };
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const testNodeFacade = ({
|
|
150
|
-
facadeDirectory,
|
|
151
|
-
facadePackage,
|
|
152
|
-
manifest,
|
|
153
|
-
nativePackage,
|
|
154
|
-
nodePackage,
|
|
155
|
-
}) => {
|
|
156
|
-
const installDirectory = mkdtempSync(join(tmpdir(), "uniffi-facade-install-"));
|
|
157
|
-
try {
|
|
158
|
-
const workspacePackages = localWorkspacePackages();
|
|
159
|
-
const facadeSource = readFileSync(join(facadeDirectory, "lib", "index.js"), "utf8");
|
|
160
|
-
const bindings =
|
|
161
|
-
JSON.parse(readFileSync(join(root, "package.json"), "utf8")).dbxToolsConfig?.rust?.bindings ??
|
|
162
|
-
[];
|
|
163
|
-
const localDependencies = Object.keys(manifest.dependencies ?? {}).flatMap((name, index) => {
|
|
164
|
-
const workspaceVersion = workspacePackages.get(name);
|
|
165
|
-
if (!workspaceVersion) return [];
|
|
166
|
-
const binding = bindings.find((binding) => binding.nodePackage === name);
|
|
167
|
-
if (binding) {
|
|
168
|
-
const stagedFacade = resolve(root, "dist/uniffi/facades", binding.crate, "npm-facade");
|
|
169
|
-
const stagedNative = resolve(root, "dist/uniffi/native");
|
|
170
|
-
const nativeName = existsSync(stagedNative)
|
|
171
|
-
? readdirSync(stagedNative).find((file) =>
|
|
172
|
-
file.startsWith(`${binding.crate}-${required("node-triple")}-`),
|
|
173
|
-
)
|
|
174
|
-
: undefined;
|
|
175
|
-
if (existsSync(stagedFacade) && nativeName) {
|
|
176
|
-
return [singlePackage(stagedFacade), join(stagedNative, nativeName)];
|
|
177
|
-
}
|
|
178
|
-
const output = resolve(root, "dist/release", binding.crate, required("node-triple"));
|
|
179
|
-
if (existsSync(join(output, "npm-facade")) && existsSync(join(output, "npm"))) {
|
|
180
|
-
return [singlePackage(join(output, "npm-facade")), singlePackage(join(output, "npm"))];
|
|
181
|
-
}
|
|
182
|
-
return [];
|
|
183
|
-
}
|
|
184
|
-
const directory = join(installDirectory, "local-dependencies", String(index));
|
|
185
|
-
mkdirSync(directory, { recursive: true });
|
|
186
|
-
writeFileSync(
|
|
187
|
-
join(directory, "package.json"),
|
|
188
|
-
`${JSON.stringify({
|
|
189
|
-
name,
|
|
190
|
-
version: workspaceVersion,
|
|
191
|
-
type: "module",
|
|
192
|
-
exports: "./index.js",
|
|
193
|
-
})}\n`,
|
|
194
|
-
);
|
|
195
|
-
const imports = importedNames(facadeSource, name);
|
|
196
|
-
writeFileSync(
|
|
197
|
-
join(directory, "index.js"),
|
|
198
|
-
[
|
|
199
|
-
"const stub = new Proxy(function () {}, { get: () => stub, apply: () => stub });",
|
|
200
|
-
...imports.names.map((name) => `export const ${name} = stub;`),
|
|
201
|
-
...(imports.hasDefault ? ["export default stub;"] : []),
|
|
202
|
-
"",
|
|
203
|
-
].join("\n"),
|
|
204
|
-
);
|
|
205
|
-
return [directory];
|
|
206
|
-
});
|
|
207
|
-
writeFileSync(
|
|
208
|
-
join(installDirectory, "package.json"),
|
|
209
|
-
`${JSON.stringify({ private: true, type: "module" })}\n`,
|
|
210
|
-
);
|
|
211
|
-
runWithRetry(
|
|
212
|
-
"npm",
|
|
213
|
-
[
|
|
214
|
-
"install",
|
|
215
|
-
"--ignore-scripts",
|
|
216
|
-
"--no-audit",
|
|
217
|
-
"--no-fund",
|
|
218
|
-
"--package-lock=false",
|
|
219
|
-
facadePackage,
|
|
220
|
-
nativePackage,
|
|
221
|
-
...localDependencies,
|
|
222
|
-
],
|
|
223
|
-
installDirectory,
|
|
224
|
-
);
|
|
225
|
-
run("node", ["-e", `import(${JSON.stringify(nodePackage)})`], installDirectory);
|
|
226
|
-
} finally {
|
|
227
|
-
rmSync(installDirectory, { recursive: true, force: true });
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
/** Resolve workspace and generated catalog protocols for a publishable facade. */
|
|
232
|
-
const facadeDependency = (name, dependency, catalog, workspaceVersions) => {
|
|
233
|
-
if (typeof dependency !== "string") return dependency;
|
|
234
|
-
if (dependency.startsWith("workspace:")) {
|
|
235
|
-
const version = workspaceVersions.get(name);
|
|
236
|
-
if (!version) throw new Error(`Missing workspace version for ${name}`);
|
|
237
|
-
return dependency === "workspace:*"
|
|
238
|
-
? version
|
|
239
|
-
: `${dependency.slice("workspace:".length)}${version}`;
|
|
240
|
-
}
|
|
241
|
-
if (!dependency.startsWith("catalog:")) return dependency;
|
|
242
|
-
const resolved = catalog[name];
|
|
243
|
-
if (!resolved) throw new Error(`Missing root catalog entry for ${name}`);
|
|
244
|
-
return resolved;
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
const writable = (path) => {
|
|
248
|
-
if (existsSync(path)) chmodSync(path, statSync(path).mode | 0o200);
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
const cargoMetadata = spawnSync("cargo", ["metadata", "--format-version", "1", "--no-deps"], {
|
|
252
|
-
cwd: root,
|
|
253
|
-
encoding: "utf8",
|
|
254
|
-
});
|
|
255
|
-
if (cargoMetadata.error) {
|
|
256
|
-
throw new Error(`cargo metadata failed: ${cargoMetadata.error.message}`, {
|
|
257
|
-
cause: cargoMetadata.error,
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
if (cargoMetadata.status !== 0) {
|
|
261
|
-
throw new Error(`cargo metadata exited with ${cargoMetadata.status}`);
|
|
262
|
-
}
|
|
263
|
-
const cargoTargetRoot = JSON.parse(cargoMetadata.stdout).target_directory;
|
|
264
|
-
if (typeof cargoTargetRoot !== "string" || !cargoTargetRoot) {
|
|
265
|
-
throw new Error("cargo metadata returned no target_directory");
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const libraryPath = (crate, cargoTarget, os) => {
|
|
269
|
-
const name = crate.replaceAll("-", "_");
|
|
270
|
-
const extension = os === "darwin" ? "dylib" : os === "win32" ? "dll" : "so";
|
|
271
|
-
const prefix = os === "win32" ? "" : "lib";
|
|
272
|
-
return resolve(cargoTargetRoot, cargoTarget, "release", `${prefix}${name}.${extension}`);
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
const packageNode = ({
|
|
276
|
-
library,
|
|
277
|
-
output,
|
|
278
|
-
nodeDirectory,
|
|
279
|
-
nodePackage,
|
|
280
|
-
nodeTriple,
|
|
281
|
-
os,
|
|
282
|
-
cpu,
|
|
283
|
-
version,
|
|
284
|
-
facade,
|
|
285
|
-
}) => {
|
|
286
|
-
const libraryFile = basename(library);
|
|
287
|
-
const sourceManifest = JSON.parse(
|
|
288
|
-
readFileSync(resolve(root, nodeDirectory, "package.json"), "utf8"),
|
|
289
|
-
);
|
|
290
|
-
const nativePackage = resolve(output, "native-node");
|
|
291
|
-
mkdirSync(nativePackage, { recursive: true });
|
|
292
|
-
cpSync(library, join(nativePackage, libraryFile));
|
|
293
|
-
writeFileSync(
|
|
294
|
-
join(nativePackage, "package.json"),
|
|
295
|
-
`${JSON.stringify(
|
|
296
|
-
{
|
|
297
|
-
name: `${nodePackage}-${nodeTriple}`,
|
|
298
|
-
version,
|
|
299
|
-
description: `Native ${nodeTriple} library for ${nodePackage}`,
|
|
300
|
-
repository: sourceManifest.repository,
|
|
301
|
-
license: "Apache-2.0",
|
|
302
|
-
os: [os],
|
|
303
|
-
cpu: [cpu],
|
|
304
|
-
...(parsed.values.libc ? { libc: [parsed.values.libc] } : {}),
|
|
305
|
-
files: [libraryFile],
|
|
306
|
-
},
|
|
307
|
-
null,
|
|
308
|
-
2,
|
|
309
|
-
)}\n`,
|
|
310
|
-
);
|
|
311
|
-
mkdirSync(resolve(output, "npm"), { recursive: true });
|
|
312
|
-
run("npm", ["pack", "--pack-destination", resolve(output, "npm")], nativePackage);
|
|
313
|
-
|
|
314
|
-
if (!facade) return;
|
|
315
|
-
packageNodeFacade({
|
|
316
|
-
output,
|
|
317
|
-
nodeDirectory,
|
|
318
|
-
nodePackage,
|
|
319
|
-
version,
|
|
320
|
-
nativePackage: singlePackage(resolve(output, "npm")),
|
|
321
|
-
});
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
const packageNodeFacade = ({ output, nodeDirectory, nodePackage, version, nativePackage }) => {
|
|
325
|
-
const facadeDirectory = resolve(output, "facade-node");
|
|
326
|
-
rmSync(facadeDirectory, { recursive: true, force: true });
|
|
327
|
-
rmSync(resolve(output, "npm-facade"), { recursive: true, force: true });
|
|
328
|
-
mkdirSync(output, { recursive: true });
|
|
329
|
-
cpSync(resolve(root, nodeDirectory), facadeDirectory, { recursive: true });
|
|
330
|
-
rmSync(join(facadeDirectory, "dist"), { recursive: true, force: true });
|
|
331
|
-
const barrel = join(facadeDirectory, "index.ts");
|
|
332
|
-
const barrelVersion = /^export const PACKAGE_VERSION = "([^"]+)";$/m.exec(
|
|
333
|
-
readFileSync(barrel, "utf8"),
|
|
334
|
-
)?.[1];
|
|
335
|
-
if (barrelVersion !== version) {
|
|
336
|
-
throw new Error(`Facade PACKAGE_VERSION ${String(barrelVersion)} does not match ${version}`);
|
|
337
|
-
}
|
|
338
|
-
for (const file of readdirSync(join(facadeDirectory, "src"))) {
|
|
339
|
-
if (/\.(dll|dylib|so)$/.test(file)) {
|
|
340
|
-
rmSync(join(facadeDirectory, "src", file), { force: true });
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
const ffiBindings = join(facadeDirectory, "src", "_bindings-ffi.ts");
|
|
344
|
-
writable(ffiBindings);
|
|
345
|
-
const ffiSource = readFileSync(ffiBindings, "utf8");
|
|
346
|
-
const packageSource = ffiSource.replace(
|
|
347
|
-
/(\s+callerUrl: import\.meta\.url,\n)(\s+\}\);)/,
|
|
348
|
-
`$1 npmPackageBase: ${JSON.stringify(`${nodePackage}-`)},\n tripleStyle: "node",\n$2`,
|
|
349
|
-
);
|
|
350
|
-
if (packageSource === ffiSource) {
|
|
351
|
-
throw new Error(`Could not configure native package lookup in ${ffiBindings}`);
|
|
352
|
-
}
|
|
353
|
-
writeFileSync(ffiBindings, packageSource);
|
|
354
|
-
const manifestPath = join(facadeDirectory, "package.json");
|
|
355
|
-
writable(manifestPath);
|
|
356
|
-
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
357
|
-
const workspaceManifest = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
358
|
-
const catalog = workspaceManifest.catalog ?? {};
|
|
359
|
-
const workspaceVersions = localWorkspacePackages();
|
|
360
|
-
if (manifest.version !== version) {
|
|
361
|
-
throw new Error(`Facade package version ${String(manifest.version)} does not match ${version}`);
|
|
362
|
-
}
|
|
363
|
-
if (manifest.private === true) throw new Error(`${manifest.name} is private`);
|
|
364
|
-
manifest.license = manifest.license === "UNLICENSED" ? "Apache-2.0" : manifest.license;
|
|
365
|
-
manifest.optionalDependencies = Object.fromEntries(
|
|
366
|
-
Object.entries(manifest.optionalDependencies ?? {}).map(([name, dependency]) => {
|
|
367
|
-
if (dependency !== version) {
|
|
368
|
-
throw new Error(`${manifest.name} optional dependency ${name} does not match ${version}`);
|
|
369
|
-
}
|
|
370
|
-
return [name, dependency];
|
|
371
|
-
}),
|
|
372
|
-
);
|
|
373
|
-
manifest.dependencies = Object.fromEntries(
|
|
374
|
-
Object.entries(manifest.dependencies ?? {}).map(([name, dependency]) => [
|
|
375
|
-
name,
|
|
376
|
-
facadeDependency(name, dependency, catalog, workspaceVersions),
|
|
377
|
-
]),
|
|
378
|
-
);
|
|
379
|
-
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
380
|
-
// Node loads the facade from node_modules, so every TypeScript entry point
|
|
381
|
-
// must be emitted and advertised as JavaScript.
|
|
382
|
-
rmSync(join(facadeDirectory, "lib"), { recursive: true, force: true });
|
|
383
|
-
run(
|
|
384
|
-
"bun",
|
|
385
|
-
[
|
|
386
|
-
"build",
|
|
387
|
-
"index.ts",
|
|
388
|
-
"--outdir",
|
|
389
|
-
"lib",
|
|
390
|
-
"--target",
|
|
391
|
-
"node",
|
|
392
|
-
"--format",
|
|
393
|
-
"esm",
|
|
394
|
-
"--packages",
|
|
395
|
-
"external",
|
|
396
|
-
],
|
|
397
|
-
facadeDirectory,
|
|
398
|
-
);
|
|
399
|
-
const compiledPublish = { ...(manifest.publishConfig ?? {}) };
|
|
400
|
-
delete compiledPublish.access;
|
|
401
|
-
Object.assign(manifest, compiledPublish);
|
|
402
|
-
manifest.types = "./index.ts";
|
|
403
|
-
manifest.exports["."].types = "./index.ts";
|
|
404
|
-
delete manifest.publishConfig;
|
|
405
|
-
delete manifest.scripts;
|
|
406
|
-
delete manifest.devDependencies;
|
|
407
|
-
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
408
|
-
const facadeOutput = resolve(output, "npm-facade");
|
|
409
|
-
mkdirSync(facadeOutput, { recursive: true });
|
|
410
|
-
run("npm", ["pack", "--pack-destination", facadeOutput], facadeDirectory);
|
|
411
|
-
if (nativePackage) {
|
|
412
|
-
testNodeFacade({
|
|
413
|
-
facadeDirectory,
|
|
414
|
-
facadePackage: singlePackage(facadeOutput),
|
|
415
|
-
manifest,
|
|
416
|
-
nativePackage,
|
|
417
|
-
nodePackage,
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
|
-
|
|
422
|
-
const packagePython = ({
|
|
423
|
-
crate,
|
|
424
|
-
library,
|
|
425
|
-
output,
|
|
426
|
-
pythonDirectory,
|
|
427
|
-
pythonTag,
|
|
428
|
-
version,
|
|
429
|
-
cargoTarget,
|
|
430
|
-
generatorTarget,
|
|
431
|
-
os,
|
|
432
|
-
pythonModule,
|
|
433
|
-
pythonBindings,
|
|
434
|
-
}) => {
|
|
435
|
-
const pythonRoot = resolve(output, "python-root");
|
|
436
|
-
cpSync(resolve(root, pythonDirectory), pythonRoot, { recursive: true });
|
|
437
|
-
const pyproject = join(pythonRoot, "pyproject.toml");
|
|
438
|
-
writable(pyproject);
|
|
439
|
-
const workspaceBindings =
|
|
440
|
-
JSON.parse(readFileSync(join(root, "package.json"), "utf8")).dbxToolsConfig?.rust?.bindings ??
|
|
441
|
-
[];
|
|
442
|
-
writeFileSync(
|
|
443
|
-
pyproject,
|
|
444
|
-
preparePythonProjectForPublication(readFileSync(pyproject, "utf8"), {
|
|
445
|
-
packages: workspaceBindings.flatMap((binding) =>
|
|
446
|
-
binding.pythonPackage && binding.python
|
|
447
|
-
? [{ name: binding.pythonPackage, directory: binding.python }]
|
|
448
|
-
: [],
|
|
449
|
-
),
|
|
450
|
-
toml,
|
|
451
|
-
version,
|
|
452
|
-
}),
|
|
453
|
-
);
|
|
454
|
-
installPythonBindings({
|
|
455
|
-
crate,
|
|
456
|
-
library,
|
|
457
|
-
module: pythonModule,
|
|
458
|
-
packageRoot: pythonRoot,
|
|
459
|
-
platform: os,
|
|
460
|
-
generatedSource: pythonBindings,
|
|
461
|
-
run,
|
|
462
|
-
targetDirectory: resolve(cargoTargetRoot, generatorTarget ?? cargoTarget, "release"),
|
|
463
|
-
});
|
|
464
|
-
|
|
465
|
-
const wheelDirectory = resolve(output, "python");
|
|
466
|
-
mkdirSync(wheelDirectory, { recursive: true });
|
|
467
|
-
run("uv", ["build", "--wheel", "--out-dir", wheelDirectory], pythonRoot);
|
|
468
|
-
const wheels = readdirSync(wheelDirectory).filter((file) => file.endsWith(".whl"));
|
|
469
|
-
if (wheels.length !== 1) throw new Error(`Expected one Python wheel, found ${wheels.length}`);
|
|
470
|
-
run("uvx", [
|
|
471
|
-
"--from",
|
|
472
|
-
"wheel",
|
|
473
|
-
"wheel",
|
|
474
|
-
"tags",
|
|
475
|
-
"--remove",
|
|
476
|
-
"--platform-tag",
|
|
477
|
-
pythonTag,
|
|
478
|
-
join(wheelDirectory, wheels[0]),
|
|
479
|
-
]);
|
|
480
|
-
};
|
|
481
|
-
|
|
482
|
-
const generatePython = () => {
|
|
483
|
-
const crate = required("crate");
|
|
484
|
-
const cargoTarget = required("cargo-target");
|
|
485
|
-
const os = required("os");
|
|
486
|
-
const output = resolve(root, required("output"));
|
|
487
|
-
const generator = resolve(
|
|
488
|
-
cargoTargetRoot,
|
|
489
|
-
cargoTarget,
|
|
490
|
-
"release",
|
|
491
|
-
pythonBindingGeneratorName(crate, os),
|
|
492
|
-
);
|
|
493
|
-
const library = libraryPath(crate, cargoTarget, os);
|
|
494
|
-
if (!existsSync(generator)) throw new Error(`Missing UniFFI generator ${generator}`);
|
|
495
|
-
if (!existsSync(library)) throw new Error(`Missing native library ${library}`);
|
|
496
|
-
rmSync(output, { recursive: true, force: true });
|
|
497
|
-
mkdirSync(output, { recursive: true });
|
|
498
|
-
run(generator, pythonBindingGeneratorArgs({ crate, library, output }));
|
|
499
|
-
};
|
|
500
|
-
|
|
501
|
-
const build = () => {
|
|
502
|
-
const crate = required("crate");
|
|
503
|
-
const cargoTarget = required("cargo-target");
|
|
504
|
-
const nodeTriple = required("node-triple");
|
|
505
|
-
const pythonTag = required("python-tag");
|
|
506
|
-
const version = required("version");
|
|
507
|
-
const os = required("os");
|
|
508
|
-
const cpu = required("cpu");
|
|
509
|
-
const output = resolve(root, required("output"));
|
|
510
|
-
const library = libraryPath(crate, cargoTarget, os);
|
|
511
|
-
|
|
512
|
-
rmSync(output, { recursive: true, force: true });
|
|
513
|
-
mkdirSync(output, { recursive: true });
|
|
514
|
-
if (!parsed.values["skip-build"]) {
|
|
515
|
-
run("cargo", [
|
|
516
|
-
"build",
|
|
517
|
-
"--release",
|
|
518
|
-
...(existsSync(resolve(root, "Cargo.lock")) ? ["--locked"] : []),
|
|
519
|
-
"--package",
|
|
520
|
-
crate,
|
|
521
|
-
"--features",
|
|
522
|
-
"uniffi-bindgen",
|
|
523
|
-
"--target",
|
|
524
|
-
cargoTarget,
|
|
525
|
-
]);
|
|
526
|
-
}
|
|
527
|
-
if (!existsSync(library)) throw new Error(`Missing native library ${library}`);
|
|
528
|
-
|
|
529
|
-
const nodeDirectory = parsed.values.node;
|
|
530
|
-
const nodePackage = parsed.values["node-package"];
|
|
531
|
-
if (nodeDirectory && nodePackage) {
|
|
532
|
-
packageNode({
|
|
533
|
-
library,
|
|
534
|
-
output,
|
|
535
|
-
nodeDirectory,
|
|
536
|
-
nodePackage,
|
|
537
|
-
nodeTriple,
|
|
538
|
-
os,
|
|
539
|
-
cpu,
|
|
540
|
-
version,
|
|
541
|
-
facade: parsed.values.facade === "true",
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
const pythonDirectory = parsed.values.python;
|
|
546
|
-
if (pythonDirectory) {
|
|
547
|
-
packagePython({
|
|
548
|
-
crate,
|
|
549
|
-
library,
|
|
550
|
-
output,
|
|
551
|
-
pythonDirectory,
|
|
552
|
-
pythonTag,
|
|
553
|
-
version,
|
|
554
|
-
cargoTarget,
|
|
555
|
-
generatorTarget: parsed.values["generator-target"],
|
|
556
|
-
os,
|
|
557
|
-
pythonModule: required("python-module"),
|
|
558
|
-
pythonBindings: parsed.values["python-bindings"],
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
};
|
|
562
|
-
|
|
563
|
-
if (parsed.positionals[0] === "build") {
|
|
564
|
-
build();
|
|
565
|
-
} else if (parsed.positionals[0] === "generate-python") {
|
|
566
|
-
generatePython();
|
|
567
|
-
} else if (parsed.positionals[0] === "facade") {
|
|
568
|
-
packageNodeFacade({
|
|
569
|
-
output: resolve(root, required("output")),
|
|
570
|
-
nodeDirectory: required("node"),
|
|
571
|
-
nodePackage: required("node-package"),
|
|
572
|
-
version: required("version"),
|
|
573
|
-
nativePackage: parsed.values["native-package"]
|
|
574
|
-
? resolve(root, parsed.values["native-package"])
|
|
575
|
-
: undefined,
|
|
576
|
-
});
|
|
577
|
-
} else {
|
|
578
|
-
throw new Error("Expected build or facade command");
|
|
579
|
-
}
|