@dbx-tools/projen 0.9.19 → 0.9.28
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 +83 -229
- package/index.ts +11 -18
- package/package.json +9 -5
- package/src/_task-command.ts +75 -0
- 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 +5 -48
- package/src/project-predicate.ts +1 -2
- package/src/project-py.ts +87 -199
- 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 +40 -208
- package/src/{release-dispatch.ts → release-context.ts} +0 -11
- package/src/release.ts +74 -778
- package/src/scaffold.ts +2 -6
- package/src/workspace-version.ts +9 -121
- package/tasks/bump.ts +17 -34
- package/tasks/databricks-cli-assets.ts +129 -0
- package/tasks/local-publish.ts +61 -138
- package/tasks/publish-npm.ts +71 -30
- package/tasks/publish-python.ts +61 -148
- package/tasks/publish.ts +32 -182
- package/tasks/python-node-bindings-watch.ts +47 -0
- package/tasks/python-node-bindings.ts +1017 -0
- package/tasks/python-registry.ts +2 -9
- package/tasks/python-release.ts +74 -0
- package/tasks/release-version.ts +23 -2
- package/tasks/release.ts +99 -0
- package/tasks/sync.ts +13 -18
- package/tasks/version-check.ts +13 -72
- package/src/_rust-project.ts +0 -429
- package/src/_rust-release-workflow.ts +0 -698
- package/src/project-rs.ts +0 -1127
- package/src/release-plan.ts +0 -269
- package/src/release-please.ts +0 -242
- package/src/uniffi.ts +0 -65
- package/tasks/publish-uniffi-local.ts +0 -314
- package/tasks/release-assets.ts +0 -476
- package/tasks/release-bootstrap.ts +0 -59
- package/tasks/release-candidate.ts +0 -383
- package/tasks/release-manifest.ts +0 -273
- package/tasks/release-plan.ts +0 -89
- package/tasks/release-please.ts +0 -162
- package/tasks/release-pr.ts +0 -563
- package/tasks/release-request.ts +0 -166
- package/tasks/release-summary-units.ts +0 -75
- package/tasks/release-summary.ts +0 -381
- package/tasks/rust.ts +0 -178
- package/tasks/stamp-python.ts +0 -13
- package/tasks/uniffi-python.d.ts +0 -61
- package/tasks/uniffi-python.js +0 -191
- package/tasks/uniffi-release.mjs +0 -573
- package/tasks/uniffi.ts +0 -271
package/tasks/rust.ts
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env -S bun
|
|
2
|
-
import { spawnSync } from "node:child_process";
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
4
|
-
import { dirname, isAbsolute, resolve, sep } from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { log, object } from "@dbx-tools/shared-core";
|
|
7
|
-
import { readDbxToolsConfig, repoRoot } from "../src/packages.ts";
|
|
8
|
-
import {
|
|
9
|
-
discoverRustCrates,
|
|
10
|
-
hasUniFFIBindings,
|
|
11
|
-
orderRustBindings,
|
|
12
|
-
type RustBindingMapping,
|
|
13
|
-
type RustWorkspaceMapping,
|
|
14
|
-
} from "../src/project-rs.ts";
|
|
15
|
-
import { runSynth } from "../src/scaffold.ts";
|
|
16
|
-
import { watchLoop } from "../src/watch.ts";
|
|
17
|
-
|
|
18
|
-
const logger = log.logger("projen:rust");
|
|
19
|
-
|
|
20
|
-
function rustConfig(): RustWorkspaceMapping | undefined {
|
|
21
|
-
const value = readDbxToolsConfig(repoRoot)?.rust;
|
|
22
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
|
|
23
|
-
const candidate = value as Partial<RustWorkspaceMapping>;
|
|
24
|
-
if (typeof candidate.root !== "string") return undefined;
|
|
25
|
-
if (!Array.isArray(candidate.crates) || !Array.isArray(candidate.bindings)) return undefined;
|
|
26
|
-
return candidate as RustWorkspaceMapping;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function cargoAvailable(): boolean {
|
|
30
|
-
return spawnSync("cargo", ["--version"], { stdio: "ignore" }).status === 0;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function currentStructure(config: RustWorkspaceMapping): RustWorkspaceMapping {
|
|
34
|
-
const root = resolve(repoRoot, config.root);
|
|
35
|
-
const directories = discoverRustCrates(root);
|
|
36
|
-
const crates = directories.map((directory) => `${config.root}/${directory}`);
|
|
37
|
-
const recorded = new Map(config.bindings.map((binding) => [binding.rust, binding]));
|
|
38
|
-
const bindings = crates.flatMap((rust) => {
|
|
39
|
-
if (!hasUniFFIBindings(resolve(repoRoot, rust))) return [];
|
|
40
|
-
const binding = recorded.get(rust);
|
|
41
|
-
return binding ? [binding] : [{ crate: "", rust }];
|
|
42
|
-
});
|
|
43
|
-
return { ...config, crates, bindings };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Whether discovered crate membership or UniFFI marker membership changed. */
|
|
47
|
-
export function rustStructureChanged(config: RustWorkspaceMapping): boolean {
|
|
48
|
-
return !sameStructure(config, currentStructure(config));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function sameStructure(left: RustWorkspaceMapping, right: RustWorkspaceMapping): boolean {
|
|
52
|
-
return (
|
|
53
|
-
JSON.stringify(left.crates) === JSON.stringify(right.crates) &&
|
|
54
|
-
JSON.stringify(left.bindings.map((binding) => binding.rust)) ===
|
|
55
|
-
JSON.stringify(right.bindings.map((binding) => binding.rust))
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function ownerBinding(
|
|
60
|
-
path: string,
|
|
61
|
-
bindings: readonly RustBindingMapping[],
|
|
62
|
-
): RustBindingMapping | undefined {
|
|
63
|
-
const absolute = isAbsolute(path) ? path : resolve(repoRoot, path);
|
|
64
|
-
return bindings.find((binding) => {
|
|
65
|
-
const directory = resolve(repoRoot, binding.rust);
|
|
66
|
-
return absolute === directory || absolute.startsWith(directory + sep);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function generate(binding: RustBindingMapping): void {
|
|
71
|
-
const targets = [
|
|
72
|
-
...(binding.node ? ["--node", binding.node] : []),
|
|
73
|
-
...(binding.python
|
|
74
|
-
? ["--python", binding.python, "--python-module", binding.pythonModule ?? ""]
|
|
75
|
-
: []),
|
|
76
|
-
];
|
|
77
|
-
const result = spawnSync(
|
|
78
|
-
process.execPath,
|
|
79
|
-
[
|
|
80
|
-
resolve(dirname(fileURLToPath(import.meta.url)), "uniffi.ts"),
|
|
81
|
-
"--crate",
|
|
82
|
-
binding.crate,
|
|
83
|
-
...targets,
|
|
84
|
-
],
|
|
85
|
-
{ cwd: repoRoot, stdio: "inherit" },
|
|
86
|
-
);
|
|
87
|
-
if (result.status !== 0) throw new Error(`binding generation exited with ${result.status}`);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function* iterateAffectedRustBindings(
|
|
91
|
-
bindings: readonly RustBindingMapping[],
|
|
92
|
-
changed: ReadonlySet<string>,
|
|
93
|
-
): Generator<RustBindingMapping> {
|
|
94
|
-
const affected = new Set(changed);
|
|
95
|
-
for (const binding of orderRustBindings(bindings)) {
|
|
96
|
-
if (binding.dependencies?.some((dependency) => affected.has(dependency))) {
|
|
97
|
-
affected.add(binding.crate);
|
|
98
|
-
}
|
|
99
|
-
if (affected.has(binding.crate)) yield binding;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export function affectedRustBindings(
|
|
104
|
-
bindings: readonly RustBindingMapping[],
|
|
105
|
-
changed: ReadonlySet<string>,
|
|
106
|
-
): RustBindingMapping[] {
|
|
107
|
-
return [...iterateAffectedRustBindings(bindings, changed)];
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Lazily resolve direct binding owners so lock checks stop at the first match.
|
|
112
|
-
*/
|
|
113
|
-
export function changedRustOwners(
|
|
114
|
-
config: RustWorkspaceMapping,
|
|
115
|
-
changed: readonly string[],
|
|
116
|
-
): object.Sequence<RustBindingMapping> {
|
|
117
|
-
return object
|
|
118
|
-
.sequence(changed)
|
|
119
|
-
.map((path) => ownerBinding(path, config.bindings))
|
|
120
|
-
.nonNull()
|
|
121
|
-
.distinct();
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** Collect direct owners, then lazily yield them and their dependents in order. */
|
|
125
|
-
export function changedRustBindings(
|
|
126
|
-
config: RustWorkspaceMapping,
|
|
127
|
-
changed: readonly string[],
|
|
128
|
-
): object.Sequence<RustBindingMapping> {
|
|
129
|
-
const targets = new Set(changedRustOwners(config, changed).map((binding) => binding.crate));
|
|
130
|
-
return object.sequence(iterateAffectedRustBindings(config.bindings, targets));
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const config = rustConfig();
|
|
134
|
-
|
|
135
|
-
async function main(): Promise<void> {
|
|
136
|
-
if (!config || config.crates.length === 0 || !existsSync(resolve(repoRoot, config.root))) return;
|
|
137
|
-
if (!cargoAvailable()) {
|
|
138
|
-
throw new Error("Cargo is required because Rust projects were detected");
|
|
139
|
-
}
|
|
140
|
-
if (!process.argv.includes("--watch")) {
|
|
141
|
-
for (const binding of orderRustBindings(config.bindings)) generate(binding);
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
watchLoop(
|
|
146
|
-
"rust",
|
|
147
|
-
[resolve(repoRoot, config.root)],
|
|
148
|
-
(changed) => {
|
|
149
|
-
const latest = rustConfig() ?? config;
|
|
150
|
-
if (rustStructureChanged(latest)) {
|
|
151
|
-
logger.start("Rust project structure changed - re-synthesizing (+install)");
|
|
152
|
-
runSynth({ post: true });
|
|
153
|
-
logger.success("Rust project structure synchronized");
|
|
154
|
-
const refreshed = rustConfig();
|
|
155
|
-
if (!refreshed) return;
|
|
156
|
-
for (const binding of changedRustBindings(refreshed, changed)) {
|
|
157
|
-
logger.start(`generating ${binding.crate} bindings`);
|
|
158
|
-
generate(binding);
|
|
159
|
-
logger.success(`generated ${binding.crate} bindings`);
|
|
160
|
-
}
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
for (const binding of changedRustBindings(latest, changed)) {
|
|
164
|
-
logger.start(`generating ${binding.crate} bindings`);
|
|
165
|
-
generate(binding);
|
|
166
|
-
logger.success(`generated ${binding.crate} bindings`);
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
check: (changed) => {
|
|
171
|
-
const latest = rustConfig() ?? config;
|
|
172
|
-
return changedRustOwners(latest, changed).some(() => true) || rustStructureChanged(latest);
|
|
173
|
-
},
|
|
174
|
-
},
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (import.meta.main) await main();
|
package/tasks/stamp-python.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env -S bun
|
|
2
|
-
import { Command } from "commander";
|
|
3
|
-
import { stampPythonProjects } from "./publish-python.ts";
|
|
4
|
-
|
|
5
|
-
const program = new Command();
|
|
6
|
-
program
|
|
7
|
-
.argument("<version>", "Python package version")
|
|
8
|
-
.option("--root <path>", "Python workspace package root", "packages/py")
|
|
9
|
-
.action((version: string, options: { root: string }) => {
|
|
10
|
-
stampPythonProjects(options.root, version);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
await program.parseAsync();
|
package/tasks/uniffi-python.d.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
export interface TomlCodec {
|
|
2
|
-
parse(source: string): unknown;
|
|
3
|
-
stringify(document: unknown): string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export interface PythonPackageMapping {
|
|
7
|
-
readonly directory: string;
|
|
8
|
-
readonly name: string;
|
|
9
|
-
readonly version: string;
|
|
10
|
-
readonly uniffi: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface PythonProjectInfo {
|
|
14
|
-
readonly name: string;
|
|
15
|
-
readonly version: string;
|
|
16
|
-
readonly private: boolean;
|
|
17
|
-
readonly uniffi: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Read the project identity and publication flag from parsed TOML metadata. */
|
|
21
|
-
export function pythonProjectInfo(source: string, toml: TomlCodec): PythonProjectInfo;
|
|
22
|
-
|
|
23
|
-
/** Stamp a temporary publication version and exact sibling dependencies. */
|
|
24
|
-
export function stampPythonProject(
|
|
25
|
-
source: string,
|
|
26
|
-
options: {
|
|
27
|
-
readonly packages: readonly PythonPackageMapping[];
|
|
28
|
-
readonly rewriteDependencies?: boolean;
|
|
29
|
-
readonly usePackageVersions?: boolean;
|
|
30
|
-
readonly toml: TomlCodec;
|
|
31
|
-
readonly version: string;
|
|
32
|
-
},
|
|
33
|
-
): string;
|
|
34
|
-
|
|
35
|
-
/** Return the target-specific UniFFI generator executable name. */
|
|
36
|
-
export function pythonBindingGeneratorName(crate: string, platform: string): string;
|
|
37
|
-
|
|
38
|
-
/** Build the canonical UniFFI Python generator argument list. */
|
|
39
|
-
export function pythonBindingGeneratorArgs(options: {
|
|
40
|
-
readonly crate: string;
|
|
41
|
-
readonly library: string;
|
|
42
|
-
readonly output: string;
|
|
43
|
-
}): string[];
|
|
44
|
-
|
|
45
|
-
export interface InstalledPythonBindings {
|
|
46
|
-
readonly bindings: string;
|
|
47
|
-
readonly init: string;
|
|
48
|
-
readonly library: string;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** Generate and place one Python binding module and its native library. */
|
|
52
|
-
export function installPythonBindings(options: {
|
|
53
|
-
readonly crate: string;
|
|
54
|
-
readonly library: string;
|
|
55
|
-
readonly module: string;
|
|
56
|
-
readonly packageRoot: string;
|
|
57
|
-
readonly platform: string;
|
|
58
|
-
readonly readonly?: boolean;
|
|
59
|
-
readonly run: (command: string, args: string[]) => void;
|
|
60
|
-
readonly targetDirectory: string;
|
|
61
|
-
}): InstalledPythonBindings;
|
package/tasks/uniffi-python.js
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
chmodSync,
|
|
3
|
-
cpSync,
|
|
4
|
-
existsSync,
|
|
5
|
-
mkdirSync,
|
|
6
|
-
mkdtempSync,
|
|
7
|
-
readFileSync,
|
|
8
|
-
readdirSync,
|
|
9
|
-
rmSync,
|
|
10
|
-
writeFileSync,
|
|
11
|
-
} from "node:fs";
|
|
12
|
-
import { tmpdir } from "node:os";
|
|
13
|
-
import { basename, join, resolve } from "node:path";
|
|
14
|
-
|
|
15
|
-
const READONLY = 0o444;
|
|
16
|
-
const WRITABLE = 0o644;
|
|
17
|
-
|
|
18
|
-
const projectTable = (document) => {
|
|
19
|
-
const project = document?.project;
|
|
20
|
-
if (!project || typeof project !== "object" || Array.isArray(project)) {
|
|
21
|
-
throw new Error("Missing Python project metadata");
|
|
22
|
-
}
|
|
23
|
-
return project;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const directSibling = (dependency, sibling) => {
|
|
27
|
-
const prefix = `${sibling.name} @ git+`;
|
|
28
|
-
if (!dependency.startsWith(prefix)) return false;
|
|
29
|
-
const marker = "#subdirectory=";
|
|
30
|
-
const markerIndex = dependency.indexOf(marker, prefix.length);
|
|
31
|
-
if (markerIndex < 0) return false;
|
|
32
|
-
const directory = dependency.slice(markerIndex + marker.length);
|
|
33
|
-
return directory === sibling.directory || directory.endsWith(`/${sibling.directory}`);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const setWritable = (path) => {
|
|
37
|
-
if (existsSync(path)) chmodSync(path, WRITABLE);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const setReadonly = (path) => {
|
|
41
|
-
if (existsSync(path)) chmodSync(path, READONLY);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const generatedHeader = (crate) =>
|
|
45
|
-
[
|
|
46
|
-
"# GENERATED by UniFFI binding generation - DO NOT EDIT.",
|
|
47
|
-
`# Regenerated from the ${crate} Rust exports.`,
|
|
48
|
-
"# Hand edits are overwritten on the next watch; this file is read-only.",
|
|
49
|
-
"",
|
|
50
|
-
].join("\n");
|
|
51
|
-
|
|
52
|
-
export const pythonProjectInfo = (source, toml) => {
|
|
53
|
-
const document = toml.parse(source);
|
|
54
|
-
const project = projectTable(document);
|
|
55
|
-
if (typeof project.name !== "string" || !project.name) {
|
|
56
|
-
throw new Error("Missing Python project name");
|
|
57
|
-
}
|
|
58
|
-
if (typeof project.version !== "string" || !project.version) {
|
|
59
|
-
throw new Error("Missing Python project version");
|
|
60
|
-
}
|
|
61
|
-
const config = document?.tool?.["dbx-tools"];
|
|
62
|
-
return {
|
|
63
|
-
name: project.name,
|
|
64
|
-
version: project.version,
|
|
65
|
-
private: Boolean(config && typeof config === "object" && config.private === true),
|
|
66
|
-
uniffi: Boolean(config && typeof config === "object" && config.uniffi === true),
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const compatibleRequirement = (version) => {
|
|
71
|
-
const [major, minor] = version.split(".").map(Number);
|
|
72
|
-
const upper = major === 0 ? `0.${minor + 1}.0` : `${major + 1}.0.0`;
|
|
73
|
-
return `>=${version},<${upper}`;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export const stampPythonProject = (
|
|
77
|
-
source,
|
|
78
|
-
{ packages, rewriteDependencies = true, usePackageVersions = false, toml, version },
|
|
79
|
-
) => {
|
|
80
|
-
const marker = source.startsWith("# ") ? source.slice(0, source.indexOf("\n")) : undefined;
|
|
81
|
-
const document = toml.parse(source);
|
|
82
|
-
const project = projectTable(document);
|
|
83
|
-
if (typeof project.version !== "string") {
|
|
84
|
-
throw new Error("Missing Python project version");
|
|
85
|
-
}
|
|
86
|
-
project.version = version;
|
|
87
|
-
if (rewriteDependencies) {
|
|
88
|
-
const dependencies = project.dependencies;
|
|
89
|
-
if (dependencies !== undefined && !Array.isArray(dependencies)) {
|
|
90
|
-
throw new Error("Python project dependencies must be an array");
|
|
91
|
-
}
|
|
92
|
-
if (dependencies) {
|
|
93
|
-
project.dependencies = dependencies.map((dependency) => {
|
|
94
|
-
if (typeof dependency !== "string") {
|
|
95
|
-
throw new Error("Python project dependencies must be strings");
|
|
96
|
-
}
|
|
97
|
-
const sibling = packages.find((candidate) => directSibling(dependency, candidate));
|
|
98
|
-
return sibling
|
|
99
|
-
? `${sibling.name}${
|
|
100
|
-
usePackageVersions
|
|
101
|
-
? sibling.uniffi
|
|
102
|
-
? `==${sibling.version}`
|
|
103
|
-
: compatibleRequirement(sibling.version)
|
|
104
|
-
: `==${version}`
|
|
105
|
-
}`
|
|
106
|
-
: dependency;
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
const body = toml.stringify(document).trimEnd();
|
|
111
|
-
return `${marker ? `${marker}\n\n` : ""}${body}\n`;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
export const pythonBindingGeneratorName = (crate, platform) =>
|
|
115
|
-
`${crate}-uniffi-bindgen${platform === "win32" ? ".exe" : ""}`;
|
|
116
|
-
|
|
117
|
-
export const pythonBindingGeneratorArgs = ({ crate, library, output }) => [
|
|
118
|
-
"generate",
|
|
119
|
-
"--language",
|
|
120
|
-
"python",
|
|
121
|
-
"--crate",
|
|
122
|
-
crate.replaceAll("-", "_"),
|
|
123
|
-
"--out-dir",
|
|
124
|
-
output,
|
|
125
|
-
library,
|
|
126
|
-
];
|
|
127
|
-
|
|
128
|
-
export const installPythonBindings = ({
|
|
129
|
-
crate,
|
|
130
|
-
library,
|
|
131
|
-
module,
|
|
132
|
-
packageRoot,
|
|
133
|
-
platform,
|
|
134
|
-
generatedSource,
|
|
135
|
-
readonly = false,
|
|
136
|
-
run,
|
|
137
|
-
targetDirectory,
|
|
138
|
-
}) => {
|
|
139
|
-
const packageName = module.split(".").at(-1);
|
|
140
|
-
if (!packageName) throw new Error(`Invalid Python module ${module}`);
|
|
141
|
-
const packageDirectory = resolve(packageRoot, "src", ...module.split("."));
|
|
142
|
-
const generatedDirectory = generatedSource
|
|
143
|
-
? undefined
|
|
144
|
-
: mkdtempSync(join(tmpdir(), `${packageName}-python-`));
|
|
145
|
-
const generator = resolve(targetDirectory, pythonBindingGeneratorName(crate, platform));
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
if (!generatedSource) {
|
|
149
|
-
if (!existsSync(generator)) throw new Error(`Missing UniFFI generator ${generator}`);
|
|
150
|
-
run(
|
|
151
|
-
generator,
|
|
152
|
-
pythonBindingGeneratorArgs({
|
|
153
|
-
crate,
|
|
154
|
-
library,
|
|
155
|
-
output: generatedDirectory,
|
|
156
|
-
}),
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
const generated =
|
|
160
|
-
generatedSource ?? join(generatedDirectory, `${crate.replaceAll("-", "_")}.py`);
|
|
161
|
-
if (!existsSync(generated)) throw new Error(`Missing generated binding ${generated}`);
|
|
162
|
-
mkdirSync(packageDirectory, { recursive: true });
|
|
163
|
-
|
|
164
|
-
const bindings = join(packageDirectory, "bindings.py");
|
|
165
|
-
setWritable(bindings);
|
|
166
|
-
writeFileSync(bindings, `${generatedHeader(crate)}${readFileSync(generated, "utf8")}`);
|
|
167
|
-
|
|
168
|
-
const init = join(packageDirectory, "__init__.py");
|
|
169
|
-
setWritable(init);
|
|
170
|
-
writeFileSync(init, `${generatedHeader(crate)}from .bindings import *\n`);
|
|
171
|
-
|
|
172
|
-
for (const candidate of readdirSync(packageDirectory)) {
|
|
173
|
-
if (/\.(?:dll|dylib|so)$/.test(candidate)) {
|
|
174
|
-
rmSync(join(packageDirectory, candidate), { force: true });
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
const nativeLibrary = join(packageDirectory, basename(library));
|
|
178
|
-
setWritable(nativeLibrary);
|
|
179
|
-
cpSync(library, nativeLibrary);
|
|
180
|
-
|
|
181
|
-
if (readonly) {
|
|
182
|
-
setReadonly(bindings);
|
|
183
|
-
setReadonly(init);
|
|
184
|
-
setReadonly(nativeLibrary);
|
|
185
|
-
}
|
|
186
|
-
rmSync(join(packageDirectory, "_generated"), { recursive: true, force: true });
|
|
187
|
-
return { bindings, init, library: nativeLibrary };
|
|
188
|
-
} finally {
|
|
189
|
-
if (generatedDirectory) rmSync(generatedDirectory, { recursive: true, force: true });
|
|
190
|
-
}
|
|
191
|
-
};
|