@prisma/compute-sdk 0.21.0 → 0.23.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 +3 -1
- package/dist/api-client.d.ts +105 -0
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +39 -0
- package/dist/api-client.js.map +1 -1
- package/dist/compute-client.d.ts.map +1 -1
- package/dist/compute-client.js +69 -12
- package/dist/compute-client.js.map +1 -1
- package/dist/config/frameworks.d.ts +46 -0
- package/dist/config/frameworks.d.ts.map +1 -0
- package/dist/config/frameworks.js +129 -0
- package/dist/config/frameworks.js.map +1 -0
- package/dist/config/index.d.ts +15 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +15 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/load.d.ts +48 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +141 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/normalize.d.ts +77 -0
- package/dist/config/normalize.d.ts.map +1 -0
- package/dist/config/normalize.js +366 -0
- package/dist/config/normalize.js.map +1 -0
- package/dist/config/serialize.d.ts +11 -0
- package/dist/config/serialize.d.ts.map +1 -0
- package/dist/config/serialize.js +55 -0
- package/dist/config/serialize.js.map +1 -0
- package/dist/config/source-root.d.ts +10 -0
- package/dist/config/source-root.d.ts.map +1 -0
- package/dist/config/source-root.js +72 -0
- package/dist/config/source-root.js.map +1 -0
- package/dist/config/types.d.ts +67 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +30 -0
- package/dist/config/types.js.map +1 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/package.json +11 -3
- package/src/api-client.ts +89 -0
- package/src/compute-client.ts +138 -13
- package/src/config/frameworks.ts +187 -0
- package/src/config/index.ts +59 -0
- package/src/config/load.ts +201 -0
- package/src/config/normalize.ts +569 -0
- package/src/config/serialize.ts +76 -0
- package/src/config/source-root.ts +91 -0
- package/src/config/types.ts +78 -0
- package/src/errors.ts +1 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { access } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
|
|
6
|
+
import { Result, TaggedError } from "better-result";
|
|
7
|
+
import { createJiti } from "jiti";
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
type ComputeConfigInvalidError,
|
|
11
|
+
type LoadedComputeConfig,
|
|
12
|
+
normalizeComputeConfig,
|
|
13
|
+
} from "./normalize.ts";
|
|
14
|
+
import { sourceRootLineage } from "./source-root.ts";
|
|
15
|
+
|
|
16
|
+
export const COMPUTE_CONFIG_FILENAME = "prisma.compute.ts";
|
|
17
|
+
|
|
18
|
+
// Highest priority first. TypeScript is the canonical format; the rest exist
|
|
19
|
+
// so plain JavaScript projects are not forced into TypeScript.
|
|
20
|
+
export const COMPUTE_CONFIG_FILENAMES = [
|
|
21
|
+
"prisma.compute.ts",
|
|
22
|
+
"prisma.compute.mts",
|
|
23
|
+
"prisma.compute.js",
|
|
24
|
+
"prisma.compute.mjs",
|
|
25
|
+
"prisma.compute.cjs",
|
|
26
|
+
] as const;
|
|
27
|
+
|
|
28
|
+
// Config files may import the typed helper through either package; both
|
|
29
|
+
// resolve to this module so configs load without a local install.
|
|
30
|
+
const CONFIG_MODULE_SPECIFIERS = [
|
|
31
|
+
"@prisma/compute-sdk/config",
|
|
32
|
+
"@prisma/cli/config",
|
|
33
|
+
] as const;
|
|
34
|
+
|
|
35
|
+
export class ComputeConfigAmbiguousError extends TaggedError(
|
|
36
|
+
"ComputeConfigAmbiguousError",
|
|
37
|
+
)<{
|
|
38
|
+
message: string;
|
|
39
|
+
configPaths: string[];
|
|
40
|
+
}>() {
|
|
41
|
+
constructor(configPaths: string[]) {
|
|
42
|
+
super({
|
|
43
|
+
message: `Multiple compute config files exist: ${configPaths.map((configPath) => path.basename(configPath)).join(", ")}. Keep exactly one.`,
|
|
44
|
+
configPaths,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class ComputeConfigLoadError extends TaggedError(
|
|
50
|
+
"ComputeConfigLoadError",
|
|
51
|
+
)<{
|
|
52
|
+
message: string;
|
|
53
|
+
cause: unknown;
|
|
54
|
+
configPath: string;
|
|
55
|
+
}>() {
|
|
56
|
+
constructor(configPath: string, cause: unknown) {
|
|
57
|
+
super({
|
|
58
|
+
message: `Could not load ${path.basename(configPath)}: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
59
|
+
cause,
|
|
60
|
+
configPath,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type ComputeConfigError =
|
|
66
|
+
| ComputeConfigAmbiguousError
|
|
67
|
+
| ComputeConfigLoadError
|
|
68
|
+
| ComputeConfigInvalidError;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Compute config files present in one directory, in filename priority order.
|
|
72
|
+
*/
|
|
73
|
+
export async function findComputeConfigCandidates(
|
|
74
|
+
directory: string,
|
|
75
|
+
signal?: AbortSignal,
|
|
76
|
+
): Promise<string[]> {
|
|
77
|
+
const candidates: string[] = [];
|
|
78
|
+
for (const filename of COMPUTE_CONFIG_FILENAMES) {
|
|
79
|
+
const configPath = path.join(directory, filename);
|
|
80
|
+
signal?.throwIfAborted();
|
|
81
|
+
try {
|
|
82
|
+
await access(configPath);
|
|
83
|
+
candidates.push(configPath);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
if (signal?.aborted) throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
signal?.throwIfAborted();
|
|
89
|
+
|
|
90
|
+
return candidates;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Locates the nearest directory holding a compute config file, searching from
|
|
95
|
+
* `cwd` up to the source root. This is location-only discovery — the config
|
|
96
|
+
* is not loaded or validated — so it is safe to run in hot paths.
|
|
97
|
+
* Returns null when no config exists inside the repository boundary.
|
|
98
|
+
*/
|
|
99
|
+
export async function findComputeConfigDir(
|
|
100
|
+
cwd: string,
|
|
101
|
+
signal?: AbortSignal,
|
|
102
|
+
): Promise<string | null> {
|
|
103
|
+
for (const directory of await sourceRootLineage(cwd, signal)) {
|
|
104
|
+
const candidates = await findComputeConfigCandidates(directory, signal);
|
|
105
|
+
if (candidates.length > 0) {
|
|
106
|
+
return directory;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Loads the nearest compute config, searching from `cwd` up to the source
|
|
115
|
+
* root (repository or workspace boundary). Without such a boundary only
|
|
116
|
+
* `cwd` itself is checked, so discovery never escapes into unrelated
|
|
117
|
+
* directories.
|
|
118
|
+
*/
|
|
119
|
+
export async function loadComputeConfig(
|
|
120
|
+
cwd: string,
|
|
121
|
+
options?: {
|
|
122
|
+
signal?: AbortSignal;
|
|
123
|
+
/**
|
|
124
|
+
* Module path the config-helper import specifiers alias to. Defaults to
|
|
125
|
+
* this SDK's own config module; pass a path when the consumer ships its
|
|
126
|
+
* own copy of the contract (e.g. a bundled CLI).
|
|
127
|
+
*/
|
|
128
|
+
configModuleAlias?: string;
|
|
129
|
+
},
|
|
130
|
+
): Promise<Result<LoadedComputeConfig | null, ComputeConfigError>> {
|
|
131
|
+
const signal = options?.signal;
|
|
132
|
+
for (const directory of await sourceRootLineage(cwd, signal)) {
|
|
133
|
+
const candidates = await findComputeConfigCandidates(directory, signal);
|
|
134
|
+
if (candidates.length === 0) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (candidates.length > 1) {
|
|
138
|
+
return Result.err(new ComputeConfigAmbiguousError(candidates));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const configPath = candidates[0] as string;
|
|
142
|
+
signal?.throwIfAborted();
|
|
143
|
+
const imported = await importComputeConfigModule(
|
|
144
|
+
configPath,
|
|
145
|
+
options?.configModuleAlias,
|
|
146
|
+
);
|
|
147
|
+
if (imported.isErr()) {
|
|
148
|
+
return Result.err(imported.error);
|
|
149
|
+
}
|
|
150
|
+
return normalizeComputeConfig(imported.value, configPath);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return Result.ok(null);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async function importComputeConfigModule(
|
|
157
|
+
configPath: string,
|
|
158
|
+
configModuleAlias: string | undefined,
|
|
159
|
+
): Promise<Result<unknown, ComputeConfigLoadError>> {
|
|
160
|
+
return Result.tryPromise({
|
|
161
|
+
try: async () => {
|
|
162
|
+
const aliasTarget = configModuleAlias ?? resolveOwnConfigModulePath();
|
|
163
|
+
const jiti = createJiti(import.meta.url, {
|
|
164
|
+
// Keep Node's standard interop so `.default` exists only for a real
|
|
165
|
+
// default export (ESM) or module.exports (CJS).
|
|
166
|
+
interopDefault: false,
|
|
167
|
+
// Re-import fresh so repeated loads in one process observe file edits.
|
|
168
|
+
moduleCache: false,
|
|
169
|
+
...(aliasTarget
|
|
170
|
+
? {
|
|
171
|
+
alias: Object.fromEntries(
|
|
172
|
+
CONFIG_MODULE_SPECIFIERS.map((specifier) => [
|
|
173
|
+
specifier,
|
|
174
|
+
aliasTarget,
|
|
175
|
+
]),
|
|
176
|
+
),
|
|
177
|
+
}
|
|
178
|
+
: {}),
|
|
179
|
+
});
|
|
180
|
+
const moduleNamespace =
|
|
181
|
+
await jiti.import<Record<string, unknown>>(configPath);
|
|
182
|
+
// Require an explicit default export instead of jiti's namespace
|
|
183
|
+
// interop so named-export configs fail with a clear message.
|
|
184
|
+
return moduleNamespace?.default;
|
|
185
|
+
},
|
|
186
|
+
catch: (cause) => new ComputeConfigLoadError(configPath, cause),
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function resolveOwnConfigModulePath(): string | null {
|
|
191
|
+
// dist layout: dist/config/load.js -> dist/config/index.js
|
|
192
|
+
// src layout (bun/tests): src/config/load.ts -> src/config/index.ts
|
|
193
|
+
for (const candidate of ["./index.js", "./index.ts"]) {
|
|
194
|
+
const candidatePath = fileURLToPath(new URL(candidate, import.meta.url));
|
|
195
|
+
if (existsSync(candidatePath)) {
|
|
196
|
+
return candidatePath;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return null;
|
|
201
|
+
}
|