pyfig 0.3.0 → 0.4.0
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 +112 -121
- package/SECURITY.md +1 -1
- package/dist/cjs/index.js +469 -871
- package/dist/cjs/index.js.map +14 -15
- package/dist/cjs/sync-resolver.js +426 -657
- package/dist/cjs/sync-resolver.js.map +12 -12
- package/dist/cli.js +5 -8
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +3 -8
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +13 -11
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +4 -13
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -51
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +5 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/package-target.d.ts +7 -11
- package/dist/package-target.d.ts.map +1 -1
- package/dist/package-target.js +41 -57
- package/dist/package-target.js.map +1 -1
- package/dist/probes.d.ts +0 -18
- package/dist/probes.d.ts.map +1 -1
- package/dist/probes.js +0 -70
- package/dist/probes.js.map +1 -1
- package/dist/process.d.ts +1 -1
- package/dist/process.d.ts.map +1 -1
- package/dist/process.js +2 -1
- package/dist/process.js.map +1 -1
- package/dist/project-root.d.ts +1 -1
- package/dist/project-root.d.ts.map +1 -1
- package/dist/project-root.js +3 -64
- package/dist/project-root.js.map +1 -1
- package/dist/provision-lock.d.ts +10 -0
- package/dist/provision-lock.d.ts.map +1 -0
- package/dist/provision-lock.js +24 -0
- package/dist/provision-lock.js.map +1 -0
- package/dist/provision.d.ts +18 -6
- package/dist/provision.d.ts.map +1 -1
- package/dist/provision.js +273 -228
- package/dist/provision.js.map +1 -1
- package/dist/runners.d.ts +3 -7
- package/dist/runners.d.ts.map +1 -1
- package/dist/runners.js +35 -115
- package/dist/runners.js.map +1 -1
- package/dist/sync-resolver.js +4 -13
- package/dist/sync-resolver.js.map +1 -1
- package/dist/virtual-environment.d.ts +3 -1
- package/dist/virtual-environment.d.ts.map +1 -1
- package/dist/virtual-environment.js +8 -1
- package/dist/virtual-environment.js.map +1 -1
- package/package.json +6 -8
- package/dist/coordination.d.ts +0 -25
- package/dist/coordination.d.ts.map +0 -1
- package/dist/coordination.js +0 -187
- package/dist/coordination.js.map +0 -1
- package/dist/state.d.ts +0 -10
- package/dist/state.d.ts.map +0 -1
- package/dist/state.js +0 -62
- package/dist/state.js.map +0 -1
package/dist/probes.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import semver from 'semver';
|
|
3
2
|
import { resolveExecutable, run } from './process.js';
|
|
4
|
-
import { activateVirtualEnvironment } from './virtual-environment.js';
|
|
5
3
|
const PYTHON_PROBE = `
|
|
6
4
|
import json
|
|
7
5
|
import os
|
|
@@ -70,24 +68,6 @@ print(json.dumps({
|
|
|
70
68
|
"embedding": embedding,
|
|
71
69
|
}))
|
|
72
70
|
`;
|
|
73
|
-
export async function findPython(options) {
|
|
74
|
-
const candidates = [];
|
|
75
|
-
if (options.python)
|
|
76
|
-
candidates.push({ executable: options.python, args: [] });
|
|
77
|
-
if (process.platform === 'win32') {
|
|
78
|
-
candidates.push({ executable: 'python', args: [] }, { executable: 'python3', args: [] }, { executable: 'py', args: ['-3'] });
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
candidates.push(...['python3.15', 'python3.14', 'python3.13', 'python3.12', 'python3.11', 'python3.10']
|
|
82
|
-
.map((executable) => ({ executable, args: [] })), { executable: 'python3', args: [] }, { executable: 'python', args: [] });
|
|
83
|
-
}
|
|
84
|
-
for (const candidate of candidates) {
|
|
85
|
-
const info = await probePython(candidate, options);
|
|
86
|
-
if (info && pythonSatisfiesRequirements(info, options))
|
|
87
|
-
return info;
|
|
88
|
-
}
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
71
|
export function pythonSatisfiesRequirements(python, options) {
|
|
92
72
|
return semver.satisfies(python.version, options.pythonRange) &&
|
|
93
73
|
(!options.requireEmbedding || (python.implementation === 'cpython' &&
|
|
@@ -108,53 +88,6 @@ export async function probePython(candidate, options) {
|
|
|
108
88
|
return null;
|
|
109
89
|
}
|
|
110
90
|
}
|
|
111
|
-
export async function findPip(python, options) {
|
|
112
|
-
if (!python.virtualEnvironment) {
|
|
113
|
-
throw new Error('pip discovery requires a virtual-environment Python interpreter.');
|
|
114
|
-
}
|
|
115
|
-
const activeEnv = activateVirtualEnvironment(options.env, python.virtualEnvironment, python.executable);
|
|
116
|
-
try {
|
|
117
|
-
const { stdout } = run(python.executable, ['-m', 'pip', '--version'], activeEnv, options.probeTimeoutMs);
|
|
118
|
-
const details = parsePipVersionOutput(stdout);
|
|
119
|
-
const version = normalizeVersion(details?.version);
|
|
120
|
-
if (!version || !semver.satisfies(version, options.pipRange))
|
|
121
|
-
return null;
|
|
122
|
-
if (!details || !pipBelongsToPython(details, python))
|
|
123
|
-
return null;
|
|
124
|
-
return {
|
|
125
|
-
kind: 'pip',
|
|
126
|
-
executable: python.executable,
|
|
127
|
-
prefixArgs: ['-m', 'pip'],
|
|
128
|
-
version,
|
|
129
|
-
pythonExecutable: python.executable,
|
|
130
|
-
virtualEnvironment: python.virtualEnvironment,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
catch {
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
export function parsePipVersionOutput(output) {
|
|
138
|
-
const match = output.trim().match(/^pip\s+(\S+)\s+from\s+(.+?)\s+\(python\s+(\d+)\.(\d+)(?:\.\d+)?\)$/iu);
|
|
139
|
-
if (!match?.[1] || !match[2] || !match[3] || !match[4])
|
|
140
|
-
return null;
|
|
141
|
-
return {
|
|
142
|
-
version: match[1],
|
|
143
|
-
location: match[2],
|
|
144
|
-
pythonMajor: Number.parseInt(match[3], 10),
|
|
145
|
-
pythonMinor: Number.parseInt(match[4], 10),
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
export function pipBelongsToPython(pip, python) {
|
|
149
|
-
if (pip.pythonMajor !== python.major || pip.pythonMinor !== python.minor)
|
|
150
|
-
return false;
|
|
151
|
-
const prefix = normalizePathForComparison(path.resolve(python.prefix));
|
|
152
|
-
const location = normalizePathForComparison(path.resolve(pip.location));
|
|
153
|
-
const relative = path.relative(prefix, location);
|
|
154
|
-
return relative === '' || (relative !== '..' &&
|
|
155
|
-
!relative.startsWith(`..${path.sep}`) &&
|
|
156
|
-
!path.isAbsolute(relative));
|
|
157
|
-
}
|
|
158
91
|
export async function findUv(options) {
|
|
159
92
|
const configured = options.env['PYFIG_UV'] ?? 'uv';
|
|
160
93
|
const executable = await resolveExecutable(configured, options.env);
|
|
@@ -176,9 +109,6 @@ function normalizeVersion(value) {
|
|
|
176
109
|
return null;
|
|
177
110
|
return semver.valid(value) ?? semver.coerce(value)?.version ?? null;
|
|
178
111
|
}
|
|
179
|
-
function normalizePathForComparison(value) {
|
|
180
|
-
return process.platform === 'win32' ? value.toLowerCase() : value;
|
|
181
|
-
}
|
|
182
112
|
function pythonArchitectureMatchesRuntime(python) {
|
|
183
113
|
const architecture = python.architecture.toLowerCase();
|
|
184
114
|
if (python.pointerBits !== (process.arch === 'ia32' ? 32 : 64))
|
package/dist/probes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probes.js","sourceRoot":"","sources":["../src/probes.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"probes.js","sourceRoot":"","sources":["../src/probes.ts"],"names":[],"mappings":"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"}
|
package/dist/process.d.ts
CHANGED
|
@@ -9,5 +9,5 @@ export interface RunResult {
|
|
|
9
9
|
export declare function resolveExecutable(value: string, env: NodeJS.ProcessEnv): Promise<string | null>;
|
|
10
10
|
export declare function run(executable: string, args: string[], env: NodeJS.ProcessEnv, timeoutMs: number): RunResult;
|
|
11
11
|
/** Run a child without blocking lock heartbeats or other coordination timers. */
|
|
12
|
-
export declare function runAsync(executable: string, args: string[], env: NodeJS.ProcessEnv, timeoutMs: number, signal?: AbortSignal): Promise<RunResult>;
|
|
12
|
+
export declare function runAsync(executable: string, args: string[], env: NodeJS.ProcessEnv, timeoutMs: number, signal?: AbortSignal, cwd?: string): Promise<RunResult>;
|
|
13
13
|
//# sourceMappingURL=process.d.ts.map
|
package/dist/process.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOxB;AAED,wBAAgB,GAAG,CACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,SAAS,EAAE,MAAM,GAChB,SAAS,CAaX;AAED,iFAAiF;AACjF,wBAAsB,QAAQ,CAC5B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOxB;AAED,wBAAgB,GAAG,CACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,SAAS,EAAE,MAAM,GAChB,SAAS,CAaX;AAED,iFAAiF;AACjF,wBAAsB,QAAQ,CAC5B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,WAAW,EACpB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,CAAC,CA0DpB"}
|
package/dist/process.js
CHANGED
|
@@ -26,10 +26,11 @@ export function run(executable, args, env, timeoutMs) {
|
|
|
26
26
|
return { stdout: result.stdout, stderr: result.stderr };
|
|
27
27
|
}
|
|
28
28
|
/** Run a child without blocking lock heartbeats or other coordination timers. */
|
|
29
|
-
export async function runAsync(executable, args, env, timeoutMs, signal) {
|
|
29
|
+
export async function runAsync(executable, args, env, timeoutMs, signal, cwd) {
|
|
30
30
|
return new Promise((resolve, reject) => {
|
|
31
31
|
const child = spawn(executable, args, {
|
|
32
32
|
env,
|
|
33
|
+
cwd,
|
|
33
34
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
34
35
|
windowsHide: true,
|
|
35
36
|
});
|
package/dist/process.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.js","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAa,EACb,GAAsB;IAEtB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,OAAO,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,GAAG,CACjB,UAAkB,EAClB,IAAc,EACd,GAAsB,EACtB,SAAiB;IAEjB,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE;QACzC,QAAQ,EAAE,MAAM;QAChB,GAAG;QACH,OAAO,EAAE,SAAS;QAClB,SAAS,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;QAC1B,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC,KAAK,EAAE,OAAO,IAAI,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACzF,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,MAAM,EAAE,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AAC1D,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,UAAkB,EAClB,IAAc,EACd,GAAsB,EACtB,SAAiB,EACjB,MAAoB;
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"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"}
|
package/dist/project-root.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/** Resolve the
|
|
1
|
+
/** Resolve the nearest Git worktree without interpreting project manifests. */
|
|
2
2
|
export declare function resolveProjectRoot(startDirectory?: string): string;
|
|
3
3
|
//# sourceMappingURL=project-root.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-root.d.ts","sourceRoot":"","sources":["../src/project-root.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"project-root.d.ts","sourceRoot":"","sources":["../src/project-root.ts"],"names":[],"mappings":"AAGA,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,cAAc,GAAE,MAAsB,GAAG,MAAM,CAMjF"}
|
package/dist/project-root.js
CHANGED
|
@@ -1,74 +1,13 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
|
|
4
|
-
const PACKAGE_MANAGER_LOCKFILES = [
|
|
5
|
-
'bun.lock',
|
|
6
|
-
'bun.lockb',
|
|
7
|
-
'npm-shrinkwrap.json',
|
|
8
|
-
'package-lock.json',
|
|
9
|
-
'pnpm-lock.yaml',
|
|
10
|
-
'yarn.lock',
|
|
11
|
-
];
|
|
12
|
-
const PYTHON_PROJECT_MARKERS = [
|
|
13
|
-
'pyproject.toml',
|
|
14
|
-
'uv.lock',
|
|
15
|
-
];
|
|
16
|
-
/** Resolve the repository root from a working directory without requiring Git. */
|
|
3
|
+
/** Resolve the nearest Git worktree without interpreting project manifests. */
|
|
17
4
|
export function resolveProjectRoot(startDirectory = process.cwd()) {
|
|
18
5
|
const start = path.resolve(startDirectory);
|
|
19
|
-
const
|
|
20
|
-
if (workspaceRoot) {
|
|
21
|
-
try {
|
|
22
|
-
return path.resolve(createFileSystemProject({
|
|
23
|
-
rootDirectory: start,
|
|
24
|
-
disableExecutableConfigs: true,
|
|
25
|
-
}).rootDirectory);
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
// Pacwich can reject an otherwise recognizable root when workspace metadata is incomplete.
|
|
29
|
-
return workspaceRoot;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return findConventionalProjectRoot(start);
|
|
33
|
-
}
|
|
34
|
-
function findWorkspaceProjectRoot(startDirectory) {
|
|
35
|
-
for (const directory of ancestors(startDirectory)) {
|
|
36
|
-
const packageJson = path.join(directory, 'package.json');
|
|
37
|
-
if (!fs.existsSync(packageJson))
|
|
38
|
-
continue;
|
|
39
|
-
if (fs.existsSync(path.join(directory, 'pnpm-workspace.yaml')))
|
|
40
|
-
return directory;
|
|
41
|
-
try {
|
|
42
|
-
const manifest = JSON.parse(fs.readFileSync(packageJson, 'utf8'));
|
|
43
|
-
if (hasWorkspaceDeclaration(manifest.workspaces))
|
|
44
|
-
return directory;
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
// Keep walking so malformed nested package metadata cannot hide a valid ancestor.
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
function findConventionalProjectRoot(startDirectory) {
|
|
53
|
-
let nearestPackageDirectory = null;
|
|
54
|
-
let nearestPythonDirectory = null;
|
|
55
|
-
for (const directory of ancestors(startDirectory)) {
|
|
56
|
-
const hasPackage = fs.existsSync(path.join(directory, 'package.json'));
|
|
57
|
-
if (hasPackage && !nearestPackageDirectory)
|
|
58
|
-
nearestPackageDirectory = directory;
|
|
59
|
-
if (!nearestPythonDirectory && PYTHON_PROJECT_MARKERS.some((file) => fs.existsSync(path.join(directory, file)))) {
|
|
60
|
-
nearestPythonDirectory = directory;
|
|
61
|
-
}
|
|
62
|
-
if (hasPackage && PACKAGE_MANAGER_LOCKFILES.some((file) => fs.existsSync(path.join(directory, file)))) {
|
|
63
|
-
return directory;
|
|
64
|
-
}
|
|
6
|
+
for (const directory of ancestors(start)) {
|
|
65
7
|
if (fs.existsSync(path.join(directory, '.git')))
|
|
66
8
|
return directory;
|
|
67
9
|
}
|
|
68
|
-
return
|
|
69
|
-
}
|
|
70
|
-
function hasWorkspaceDeclaration(value) {
|
|
71
|
-
return Array.isArray(value) || (value !== null && typeof value === 'object');
|
|
10
|
+
return start;
|
|
72
11
|
}
|
|
73
12
|
function* ancestors(startDirectory) {
|
|
74
13
|
let directory = startDirectory;
|
package/dist/project-root.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-root.js","sourceRoot":"","sources":["../src/project-root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"project-root.js","sourceRoot":"","sources":["../src/project-root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB,CAAC,cAAc,GAAW,OAAO,CAAC,GAAG,EAAE;IACvE,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3C,KAAK,MAAM,SAAS,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;IACpE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,QAAQ,CAAC,CAAC,SAAS,CAAC,cAAsB;IACxC,IAAI,SAAS,GAAG,cAAc,CAAC;IAC/B,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,SAAS,CAAC;QAChB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO;QACjC,SAAS,GAAG,MAAM,CAAC;IACrB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ProvisioningLockOptions<T> {
|
|
2
|
+
/** Stable logical identity shared by every caller of the protected resource. */
|
|
3
|
+
key: string;
|
|
4
|
+
timeoutMs: number;
|
|
5
|
+
check: () => Promise<T | null>;
|
|
6
|
+
mutate: () => Promise<T>;
|
|
7
|
+
}
|
|
8
|
+
/** Use Loqkit's layered lock and predicate checks for one idempotent mutation. */
|
|
9
|
+
export declare function withProvisioningLock<T>(options: ProvisioningLockOptions<T>): Promise<T>;
|
|
10
|
+
//# sourceMappingURL=provision-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision-lock.d.ts","sourceRoot":"","sources":["../src/provision-lock.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,uBAAuB,CAAC,CAAC;IACxC,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;CAC1B;AAED,kFAAkF;AAClF,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,OAAO,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAClC,OAAO,CAAC,CAAC,CAAC,CAsBZ"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { withLock } from 'loqkit';
|
|
2
|
+
/** Use Loqkit's layered lock and predicate checks for one idempotent mutation. */
|
|
3
|
+
export async function withProvisioningLock(options) {
|
|
4
|
+
let existing;
|
|
5
|
+
const result = await withLock({ resource: options.key }, options.mutate, {
|
|
6
|
+
key: options.key,
|
|
7
|
+
name: 'Pyfig provisioning',
|
|
8
|
+
namespace: 'pyfig',
|
|
9
|
+
timeout: options.timeoutMs,
|
|
10
|
+
predicate: async () => {
|
|
11
|
+
const value = await options.check();
|
|
12
|
+
if (value === null)
|
|
13
|
+
return true;
|
|
14
|
+
existing = { value };
|
|
15
|
+
return false;
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
if (result.context.state === 'executed')
|
|
19
|
+
return result.value;
|
|
20
|
+
if (existing)
|
|
21
|
+
return existing.value;
|
|
22
|
+
throw new Error(`Provisioning check for ${options.key} did not produce a resource.`);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=provision-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision-lock.js","sourceRoot":"","sources":["../src/provision-lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAUlC,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAmC;IAEnC,IAAI,QAAkC,CAAC;IACvC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAC3B,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,EACzB,OAAO,CAAC,MAAM,EACd;QACE,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,IAAI,EAAE,oBAAoB;QAC1B,SAAS,EAAE,OAAO;QAClB,OAAO,EAAE,OAAO,CAAC,SAAS;QAC1B,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACpC,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YAChC,QAAQ,GAAG,EAAE,KAAK,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CACF,CAAC;IAEF,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC,KAAU,CAAC;IAClE,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC;IACpC,MAAM,IAAI,KAAK,CAAC,0BAA0B,OAAO,CAAC,GAAG,8BAA8B,CAAC,CAAC;AACvF,CAAC"}
|
package/dist/provision.d.ts
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import { type PyfigOptions } from './config.js';
|
|
2
|
-
import { type
|
|
2
|
+
import { type PythonInfo, type UvInfo } from './probes.js';
|
|
3
3
|
export interface PythonEnvironment {
|
|
4
4
|
python: PythonInfo;
|
|
5
|
-
|
|
5
|
+
uv: UvInfo;
|
|
6
|
+
/** True when the environment lives in node_modules/.pyfig/venv. */
|
|
7
|
+
managed: boolean;
|
|
6
8
|
}
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
export interface RuntimeDependencyOptions {
|
|
10
|
+
/** Optional-dependency extras read from an existing pyproject.toml. */
|
|
11
|
+
extras?: readonly string[];
|
|
12
|
+
/** Include every optional-dependency extra from an existing pyproject.toml. */
|
|
13
|
+
allExtras?: boolean;
|
|
14
|
+
/** Dependency groups read from an existing pyproject.toml. */
|
|
15
|
+
groups?: readonly string[];
|
|
16
|
+
}
|
|
17
|
+
/** Ensure a compatible uv executable, preferring an existing installation. */
|
|
10
18
|
export declare function ensureUv(options?: PyfigOptions): Promise<UvInfo>;
|
|
11
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Select a compatible environment and optionally add runtime requirements.
|
|
21
|
+
* Project dependency files are inputs only and are never changed.
|
|
22
|
+
*/
|
|
23
|
+
export declare function ensureEnvironment(options?: PyfigOptions, requirements?: readonly string[], dependencyOptions?: RuntimeDependencyOptions): Promise<PythonEnvironment>;
|
|
12
24
|
//# sourceMappingURL=provision.d.ts.map
|
package/dist/provision.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AAoBA,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,MAAM,EACZ,MAAM,aAAa,CAAC;AAUrB,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,UAAU,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED,8EAA8E;AAC9E,wBAAsB,QAAQ,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1E;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,GAAE,YAAiB,EAC1B,YAAY,GAAE,SAAS,MAAM,EAAO,EACpC,iBAAiB,GAAE,wBAA6B,GAC/C,OAAO,CAAC,iBAAiB,CAAC,CAe5B"}
|