@xemahq/biome-database-nest 0.9.0 → 0.10.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/dist/index.d.ts +3 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -15
- package/dist/index.js.map +1 -1
- package/dist/lib/bootstrap.d.ts +3 -16
- package/dist/lib/bootstrap.d.ts.map +1 -1
- package/dist/lib/bootstrap.js +12 -71
- package/dist/lib/bootstrap.js.map +1 -1
- package/dist/lib/config.d.ts +0 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +7 -10
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/control-plane-client.d.ts +0 -1
- package/dist/lib/control-plane-client.d.ts.map +1 -1
- package/dist/lib/control-plane-client.js +3 -13
- package/dist/lib/control-plane-client.js.map +1 -1
- package/dist/lib/migration-mode.d.ts +1 -117
- package/dist/lib/migration-mode.d.ts.map +1 -1
- package/dist/lib/migration-mode.js +1 -48
- package/dist/lib/migration-mode.js.map +1 -1
- package/dist/lib/nest/biome-database.module.d.ts +3 -8
- package/dist/lib/nest/biome-database.module.d.ts.map +1 -1
- package/dist/lib/nest/biome-database.module.js +1 -2
- package/dist/lib/nest/biome-database.module.js.map +1 -1
- package/package.json +4 -3
- package/src/index.ts +112 -0
- package/src/lib/adapter.ts +114 -0
- package/src/lib/bootstrap.ts +433 -0
- package/src/lib/config.ts +183 -0
- package/src/lib/control-plane-client.ts +121 -0
- package/src/lib/control-plane-discovery.ts +34 -0
- package/src/lib/identifier.ts +177 -0
- package/src/lib/migration-mode.ts +25 -0
- package/src/lib/nest/biome-database.module.ts +175 -0
- package/src/lib/nest/org-erasure.module.ts +124 -0
- package/src/lib/nest/prisma-service-factory.ts +376 -0
- package/src/lib/role-names.ts +77 -0
- package/src/lib/schema-name.ts +62 -0
- package/src/lib/tenant-isolation/org-erasure.ts +158 -0
- package/src/lib/tenant-isolation/org-scope.ts +305 -0
- package/src/lib/tenant-isolation/tenant-isolation-error.ts +79 -0
- package/src/lib/tenant-isolation/tenant-isolation-mode.ts +55 -0
- package/src/lib/tenant-isolation/tenant-isolation.extension.ts +203 -0
- package/src/lib/tenant-isolation/unscoped-models.ts +269 -0
- package/dist/lib/credential-generation.d.ts +0 -4
- package/dist/lib/credential-generation.d.ts.map +0 -1
- package/dist/lib/credential-generation.js +0 -24
- package/dist/lib/credential-generation.js.map +0 -1
- package/dist/lib/external-runtime-verifier.d.ts +0 -3
- package/dist/lib/external-runtime-verifier.d.ts.map +0 -1
- package/dist/lib/external-runtime-verifier.js +0 -860
- package/dist/lib/external-runtime-verifier.js.map +0 -1
- package/dist/lib/response-envelope.d.ts +0 -2
- package/dist/lib/response-envelope.d.ts.map +0 -1
- package/dist/lib/response-envelope.js +0 -6
- package/dist/lib/response-envelope.js.map +0 -1
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
3
|
+
* The blind spot this module closes.
|
|
4
|
+
*
|
|
5
|
+
* {@link collectOrgScopedModels} treats a model as org-scoped ONLY when it
|
|
6
|
+
* DECLARES the org column. A model with no org column is therefore invisible to
|
|
7
|
+
* the isolation extension: every query on it passes through UNSCOPED, silently,
|
|
8
|
+
* even in {@link TenantIsolationMode.Enforce}. That silence is the whole
|
|
9
|
+
* problem — `Enforce` reads as "this service is isolated", but it only ever
|
|
10
|
+
* covered the models that happened to carry an `orgId`.
|
|
11
|
+
*
|
|
12
|
+
* That is not a hypothetical. `ProjectRepositoryBinding` (scm-connector-api)
|
|
13
|
+
* has no `orgId` — it is owned transitively via `orgRepositoryId ->
|
|
14
|
+
* OrgRepository.orgId` — so enforcement never applied to it, and eight
|
|
15
|
+
* cross-org queries lived there unnoticed, including a destructive
|
|
16
|
+
* CloudEvent-driven `deleteByProjectId` and, on the sibling connector edge, a
|
|
17
|
+
* cross-tenant PLAINTEXT-credential read.
|
|
18
|
+
*
|
|
19
|
+
* The fix is not to guess. A model with no org column can be either:
|
|
20
|
+
*
|
|
21
|
+
* - GENUINELY GLOBAL — a platform catalog, a kernel-shipped registry, a
|
|
22
|
+
* bookkeeping table. Correctly unscoped.
|
|
23
|
+
* - TENANT-SCOPED-INVISIBLE — the rows DO belong to a tenant, reached through
|
|
24
|
+
* a foreign key to something that carries the org. These MUST be fenced by
|
|
25
|
+
* hand at every query (`owner: { orgId }`), and nothing in the runtime can
|
|
26
|
+
* infer that for them.
|
|
27
|
+
*
|
|
28
|
+
* Only the schema's author can tell those apart, so the runtime demands the
|
|
29
|
+
* answer instead of assuming one: every model with no org column must be
|
|
30
|
+
* DECLARED, with a written justification, via
|
|
31
|
+
* {@link TenantIsolationServiceOptions.unscopedModels}. An undeclared one is a
|
|
32
|
+
* boot-time error in `Enforce` and a loud warning in `Observe` — never a silent
|
|
33
|
+
* pass-through.
|
|
34
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
35
|
+
*/
|
|
36
|
+
import { TenantIsolationMode } from './tenant-isolation-mode';
|
|
37
|
+
import type { TenantIsolationLogger } from './tenant-isolation.extension';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Why a model carries no org column, and — when it is tenant-scoped in reality
|
|
41
|
+
* — how its queries are fenced instead.
|
|
42
|
+
*
|
|
43
|
+
* A bare string is accepted as shorthand for `{ reason }`.
|
|
44
|
+
*/
|
|
45
|
+
export interface UnscopedModelDeclaration {
|
|
46
|
+
/**
|
|
47
|
+
* Why this model has no org column. Must be a real sentence, not a
|
|
48
|
+
* placeholder: this text is the record of a security decision and is what a
|
|
49
|
+
* future reader (or auditor) sees. Blank/whitespace is rejected.
|
|
50
|
+
*/
|
|
51
|
+
readonly reason: string;
|
|
52
|
+
/**
|
|
53
|
+
* REQUIRED when the model is tenant-scoped in reality: the fence its queries
|
|
54
|
+
* carry instead of the auto-scope, e.g.
|
|
55
|
+
* `"orgRepository: { orgId } relation filter on every query"`.
|
|
56
|
+
* Omit ONLY for genuinely global models.
|
|
57
|
+
*/
|
|
58
|
+
readonly fencedBy?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Declaration map: Prisma model name → justification. */
|
|
62
|
+
export type UnscopedModelDeclarations = Readonly<
|
|
63
|
+
Record<string, string | UnscopedModelDeclaration>
|
|
64
|
+
>;
|
|
65
|
+
|
|
66
|
+
/** Normalized form of one declaration. */
|
|
67
|
+
export interface NormalizedUnscopedModelDeclaration {
|
|
68
|
+
readonly model: string;
|
|
69
|
+
readonly reason: string;
|
|
70
|
+
readonly fencedBy?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Thrown when the set of models carrying no org column does not match what the
|
|
75
|
+
* service declared. Fail-fast: in `Enforce` this aborts boot.
|
|
76
|
+
*/
|
|
77
|
+
export class UndeclaredUnscopedModelsError extends Error {
|
|
78
|
+
/** Models with no org column that were never declared. */
|
|
79
|
+
readonly undeclared: readonly string[];
|
|
80
|
+
/** Declared names that no longer match a model with no org column. */
|
|
81
|
+
readonly staleDeclarations: readonly string[];
|
|
82
|
+
|
|
83
|
+
constructor(
|
|
84
|
+
undeclared: readonly string[],
|
|
85
|
+
staleDeclarations: readonly string[],
|
|
86
|
+
orgField: string,
|
|
87
|
+
) {
|
|
88
|
+
super(
|
|
89
|
+
formatUnscopedModelReport(undeclared, staleDeclarations, orgField, true),
|
|
90
|
+
);
|
|
91
|
+
this.name = 'UndeclaredUnscopedModelsError';
|
|
92
|
+
this.undeclared = undeclared;
|
|
93
|
+
this.staleDeclarations = staleDeclarations;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Every model in the client's runtime data model that does NOT declare
|
|
99
|
+
* `orgField` — the set the isolation extension can never auto-scope.
|
|
100
|
+
*/
|
|
101
|
+
export function collectUnscopableModels(
|
|
102
|
+
models: Readonly<Record<string, { readonly fields: readonly { readonly name: string }[] }>>,
|
|
103
|
+
orgField: string,
|
|
104
|
+
): readonly string[] {
|
|
105
|
+
return Object.entries(models)
|
|
106
|
+
.filter(([, model]) => !model.fields.some((f) => f.name === orgField))
|
|
107
|
+
.map(([name]) => name)
|
|
108
|
+
.sort();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Normalize + validate the declaration map on its own terms (before it is
|
|
113
|
+
* compared against the schema). Fail-fast on a blank reason: an empty
|
|
114
|
+
* justification is a rubber stamp, and a rubber stamp is exactly the silent
|
|
115
|
+
* pass-through this mechanism exists to remove.
|
|
116
|
+
*/
|
|
117
|
+
export function normalizeUnscopedModelDeclarations(
|
|
118
|
+
declarations: UnscopedModelDeclarations,
|
|
119
|
+
): readonly NormalizedUnscopedModelDeclaration[] {
|
|
120
|
+
return Object.entries(declarations).map(([model, value]) => {
|
|
121
|
+
const declaration: UnscopedModelDeclaration =
|
|
122
|
+
typeof value === 'string' ? { reason: value } : value;
|
|
123
|
+
if (declaration.reason.trim().length === 0) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
`[tenant-isolation] unscopedModels["${model}"] has a blank reason. ` +
|
|
126
|
+
'Every model with no org column must carry a written justification — ' +
|
|
127
|
+
'say whether it is genuinely global, or tenant-scoped-in-reality and ' +
|
|
128
|
+
'fenced by hand (then also set `fencedBy`).',
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (
|
|
132
|
+
declaration.fencedBy !== undefined &&
|
|
133
|
+
declaration.fencedBy.trim().length === 0
|
|
134
|
+
) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`[tenant-isolation] unscopedModels["${model}"].fencedBy is blank. ` +
|
|
137
|
+
'Either describe the manual fence or omit the field entirely.',
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
model,
|
|
142
|
+
reason: declaration.reason,
|
|
143
|
+
...(declaration.fencedBy !== undefined
|
|
144
|
+
? { fencedBy: declaration.fencedBy }
|
|
145
|
+
: {}),
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Render the actionable boot message for a declaration mismatch. */
|
|
151
|
+
export function formatUnscopedModelReport(
|
|
152
|
+
undeclared: readonly string[],
|
|
153
|
+
staleDeclarations: readonly string[],
|
|
154
|
+
orgField: string,
|
|
155
|
+
fatal: boolean,
|
|
156
|
+
): string {
|
|
157
|
+
const lines: string[] = [
|
|
158
|
+
`[tenant-isolation] ${fatal ? 'REFUSING TO START' : 'UNDECLARED MODELS'} — ` +
|
|
159
|
+
`tenant isolation cannot scope every model in this schema.`,
|
|
160
|
+
];
|
|
161
|
+
if (undeclared.length > 0) {
|
|
162
|
+
lines.push(
|
|
163
|
+
` ${undeclared.length} model(s) declare no "${orgField}" column and were ` +
|
|
164
|
+
`not declared in tenantIsolation.unscopedModels, so every query on them ` +
|
|
165
|
+
`runs UNSCOPED and enforcement silently does not apply:`,
|
|
166
|
+
` ${undeclared.join(', ')}`,
|
|
167
|
+
' For EACH one, decide which it is and record the decision:',
|
|
168
|
+
' - GENUINELY GLOBAL (platform catalog, kernel registry, bookkeeping) →',
|
|
169
|
+
' unscopedModels: { Foo: "global catalog; rows belong to no tenant" }',
|
|
170
|
+
' - TENANT-SCOPED via a foreign key (the dangerous case) → fence EVERY',
|
|
171
|
+
' query by hand through the owning relation, then record how:',
|
|
172
|
+
' unscopedModels: { Foo: { reason: "owned via barId -> Bar.orgId",',
|
|
173
|
+
' fencedBy: "bar: { orgId } on every query" } }',
|
|
174
|
+
' A model that carries the org column but must NOT be scoped belongs in',
|
|
175
|
+
' `exemptModels` instead — that is a different decision and stays separate.',
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
if (staleDeclarations.length > 0) {
|
|
179
|
+
lines.push(
|
|
180
|
+
` ${staleDeclarations.length} declaration(s) no longer match a model ` +
|
|
181
|
+
`without "${orgField}" — the schema moved on and the justification is ` +
|
|
182
|
+
'now misleading. Remove them (or move them to `exemptModels` if the ' +
|
|
183
|
+
'model gained an org column but must stay unscoped):',
|
|
184
|
+
` ${staleDeclarations.join(', ')}`,
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
return lines.join('\n');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export interface AssertUnscopedModelsOptions {
|
|
191
|
+
/** Runtime data model of the generated client. */
|
|
192
|
+
readonly models: Readonly<
|
|
193
|
+
Record<string, { readonly fields: readonly { readonly name: string }[] }>
|
|
194
|
+
>;
|
|
195
|
+
readonly orgField: string;
|
|
196
|
+
readonly mode: TenantIsolationMode;
|
|
197
|
+
/** Declarations for models with NO org column. */
|
|
198
|
+
readonly unscopedModels: UnscopedModelDeclarations;
|
|
199
|
+
/** Models that DO carry the org column but are deliberately not scoped. */
|
|
200
|
+
readonly exemptModels: readonly string[];
|
|
201
|
+
readonly logger: TenantIsolationLogger;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Compare the schema against the declarations and act per mode.
|
|
206
|
+
*
|
|
207
|
+
* - `Enforce` → THROW {@link UndeclaredUnscopedModelsError} (boot aborts).
|
|
208
|
+
* - `Observe` → one loud `warn` carrying the same report (rollout mode keeps
|
|
209
|
+
* its promise of zero behaviour change).
|
|
210
|
+
* - `Off` → nothing; the kill switch must never be able to fail a boot.
|
|
211
|
+
*
|
|
212
|
+
* This is a STARTUP check rather than a per-query one on purpose. Startup is
|
|
213
|
+
* strictly stronger here: it sees 100% of the schema deterministically, while a
|
|
214
|
+
* query-time check only fires on code paths that actually execute (and would
|
|
215
|
+
* require routing every model delegate through the extension, which changes the
|
|
216
|
+
* proxy surface and adds cost on models the extension has nothing to do). It
|
|
217
|
+
* also fails at the earliest possible moment — a deploy, not a request.
|
|
218
|
+
*/
|
|
219
|
+
export function assertUnscopedModelsDeclared(
|
|
220
|
+
options: AssertUnscopedModelsOptions,
|
|
221
|
+
): void {
|
|
222
|
+
const { models, orgField, mode, unscopedModels, exemptModels, logger } =
|
|
223
|
+
options;
|
|
224
|
+
if (mode === TenantIsolationMode.Off) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const normalized = normalizeUnscopedModelDeclarations(unscopedModels);
|
|
229
|
+
const unscopable = new Set(collectUnscopableModels(models, orgField));
|
|
230
|
+
|
|
231
|
+
for (const { model } of normalized) {
|
|
232
|
+
if (!(model in models)) {
|
|
233
|
+
throw new Error(
|
|
234
|
+
`[tenant-isolation] unscopedModels names unknown model "${model}" — ` +
|
|
235
|
+
`known models: ${Object.keys(models).join(', ')}.`,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// A model listed in BOTH lists is a contradiction: `exemptModels` means "has
|
|
241
|
+
// the org column, deliberately not scoped"; `unscopedModels` means "has no
|
|
242
|
+
// org column at all". Never let one silently shadow the other.
|
|
243
|
+
const declaredUnscoped = new Set(normalized.map((d) => d.model));
|
|
244
|
+
const inBoth = exemptModels.filter((m) => declaredUnscoped.has(m));
|
|
245
|
+
if (inBoth.length > 0) {
|
|
246
|
+
throw new Error(
|
|
247
|
+
`[tenant-isolation] ${inBoth.join(', ')} appear in BOTH exemptModels and ` +
|
|
248
|
+
'unscopedModels. They answer different questions — exemptModels means ' +
|
|
249
|
+
`"declares ${orgField} but must not be auto-scoped"; unscopedModels ` +
|
|
250
|
+
`means "declares no ${orgField} at all". Pick the one that is true.`,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const undeclared = [...unscopable].filter((m) => !declaredUnscoped.has(m));
|
|
255
|
+
const stale = [...declaredUnscoped].filter((m) => !unscopable.has(m)).sort();
|
|
256
|
+
|
|
257
|
+
if (undeclared.length === 0 && stale.length === 0) {
|
|
258
|
+
logger.debug(
|
|
259
|
+
`[tenant-isolation] ${unscopable.size} model(s) carry no "${orgField}" ` +
|
|
260
|
+
'column; all are declared in unscopedModels.',
|
|
261
|
+
);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (mode === TenantIsolationMode.Enforce) {
|
|
266
|
+
throw new UndeclaredUnscopedModelsError(undeclared, stale, orgField);
|
|
267
|
+
}
|
|
268
|
+
logger.warn(formatUnscopedModelReport(undeclared, stale, orgField, false));
|
|
269
|
+
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export declare const MAX_DATABASE_CREDENTIAL_GENERATION = 2147483647;
|
|
2
|
-
export declare function assertDatabaseCredentialGeneration(value: number, field: string): void;
|
|
3
|
-
export declare function parseDatabaseCredentialGeneration(value: string, field: string): number;
|
|
4
|
-
//# sourceMappingURL=credential-generation.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"credential-generation.d.ts","sourceRoot":"","sources":["../../src/lib/credential-generation.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kCAAkC,aAAgB,CAAC;AAIhE,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,IAAI,CAWN;AAED,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,MAAM,CASR"}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MAX_DATABASE_CREDENTIAL_GENERATION = void 0;
|
|
4
|
-
exports.assertDatabaseCredentialGeneration = assertDatabaseCredentialGeneration;
|
|
5
|
-
exports.parseDatabaseCredentialGeneration = parseDatabaseCredentialGeneration;
|
|
6
|
-
exports.MAX_DATABASE_CREDENTIAL_GENERATION = 2_147_483_647;
|
|
7
|
-
const CANONICAL_POSITIVE_DECIMAL = /^[1-9][0-9]*$/;
|
|
8
|
-
function assertDatabaseCredentialGeneration(value, field) {
|
|
9
|
-
if (!Number.isSafeInteger(value) ||
|
|
10
|
-
value <= 0 ||
|
|
11
|
-
value > exports.MAX_DATABASE_CREDENTIAL_GENERATION) {
|
|
12
|
-
throw new Error(`${field} must be a safe positive integer no greater than ` +
|
|
13
|
-
`${exports.MAX_DATABASE_CREDENTIAL_GENERATION}.`);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function parseDatabaseCredentialGeneration(value, field) {
|
|
17
|
-
if (!CANONICAL_POSITIVE_DECIMAL.test(value)) {
|
|
18
|
-
throw new Error(`${field} value "${value}" must be a canonical positive decimal integer.`);
|
|
19
|
-
}
|
|
20
|
-
const generation = Number(value);
|
|
21
|
-
assertDatabaseCredentialGeneration(generation, field);
|
|
22
|
-
return generation;
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=credential-generation.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"credential-generation.js","sourceRoot":"","sources":["../../src/lib/credential-generation.ts"],"names":[],"mappings":";;;AAIA,gFAcC;AAED,8EAYC;AAhCY,QAAA,kCAAkC,GAAG,aAAa,CAAC;AAEhE,MAAM,0BAA0B,GAAG,eAAe,CAAC;AAEnD,SAAgB,kCAAkC,CAChD,KAAa,EACb,KAAa;IAEb,IACE,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;QAC5B,KAAK,IAAI,CAAC;QACV,KAAK,GAAG,0CAAkC,EAC1C,CAAC;QACD,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,mDAAmD;YACzD,GAAG,0CAAkC,GAAG,CAC3C,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAgB,iCAAiC,CAC/C,KAAa,EACb,KAAa;IAEb,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,WAAW,KAAK,iDAAiD,CAC1E,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACjC,kCAAkC,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACtD,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { MigrationCompatibilityContext, MigrationCompatibilityExpectation, RuntimeDatabaseAccessExpectation, RuntimeDatabaseTarget } from './migration-mode';
|
|
2
|
-
export declare function verifyExternallyManagedRuntime(runtimeUrl: string, target: RuntimeDatabaseTarget, access: RuntimeDatabaseAccessExpectation, compatibility: MigrationCompatibilityExpectation): Promise<MigrationCompatibilityContext>;
|
|
3
|
-
//# sourceMappingURL=external-runtime-verifier.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"external-runtime-verifier.d.ts","sourceRoot":"","sources":["../../src/lib/external-runtime-verifier.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,6BAA6B,EAC7B,iCAAiC,EACjC,gCAAgC,EAEhC,qBAAqB,EAEtB,MAAM,kBAAkB,CAAC;AAugC1B,wBAAsB,8BAA8B,CAClD,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,qBAAqB,EAC7B,MAAM,EAAE,gCAAgC,EACxC,aAAa,EAAE,iCAAiC,GAC/C,OAAO,CAAC,6BAA6B,CAAC,CAwfxC"}
|