@tailor-platform/sdk 1.49.0 → 1.50.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/CHANGELOG.md +28 -0
- package/README.md +1 -1
- package/dist/cli/index.mjs +92 -4
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.d.mts +1409 -1373
- package/dist/cli/lib.mjs +1 -1
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/{runtime-oZgK353r.mjs → runtime-B2K6JW7V.mjs} +454 -156
- package/dist/runtime-B2K6JW7V.mjs.map +1 -0
- package/docs/cli/tailordb.md +50 -0
- package/docs/cli-reference.md +1 -0
- package/docs/services/tailordb-migration.md +49 -31
- package/package.json +3 -3
- package/dist/runtime-oZgK353r.mjs.map +0 -1
- /package/{skills → agent-skills}/tailor-sdk/SKILL.md +0 -0
|
@@ -5796,6 +5796,20 @@ function formatBreakingChanges(breakingChanges) {
|
|
|
5796
5796
|
}
|
|
5797
5797
|
return lines.join("\n");
|
|
5798
5798
|
}
|
|
5799
|
+
/**
|
|
5800
|
+
* Format warning changes for display
|
|
5801
|
+
* @param {WarningChangeInfo[]} warnings - Warning changes to format
|
|
5802
|
+
* @returns {string} Formatted warning changes string
|
|
5803
|
+
*/
|
|
5804
|
+
function formatWarnings(warnings) {
|
|
5805
|
+
if (warnings.length === 0) return "";
|
|
5806
|
+
const lines = ["Warning: data loss possible:", ""];
|
|
5807
|
+
for (const w of warnings) {
|
|
5808
|
+
const location = w.fieldName ? `${w.typeName}.${w.fieldName}` : w.typeName;
|
|
5809
|
+
lines.push(` - ${location}: ${w.reason}`);
|
|
5810
|
+
}
|
|
5811
|
+
return lines.join("\n");
|
|
5812
|
+
}
|
|
5799
5813
|
const DIFF_CHANGE_LABELS = {
|
|
5800
5814
|
type_added: "type(s) added",
|
|
5801
5815
|
type_removed: "type(s) removed",
|
|
@@ -5856,15 +5870,37 @@ const MIGRATION_NUMBER_PATTERN = /^\d{4}$/;
|
|
|
5856
5870
|
*/
|
|
5857
5871
|
const DEFAULT_DECIMAL_SCALE = 6;
|
|
5858
5872
|
/**
|
|
5859
|
-
*
|
|
5860
|
-
*
|
|
5861
|
-
*
|
|
5862
|
-
*
|
|
5863
|
-
* @
|
|
5873
|
+
* Normalize a snapshot field in place so the snapshot becomes the canonical
|
|
5874
|
+
* form for comparison. Currently fills in the platform default decimal scale
|
|
5875
|
+
* when omitted, which avoids false drift between local schemas (where scale
|
|
5876
|
+
* may be omitted) and the platform (which always materializes a scale).
|
|
5877
|
+
* @param {SnapshotFieldConfig} field - Field configuration to normalize
|
|
5878
|
+
*/
|
|
5879
|
+
function normalizeSnapshotField(field) {
|
|
5880
|
+
if (field.type === "decimal" && field.scale === void 0) field.scale = 6;
|
|
5881
|
+
if (field.fields) for (const nested of Object.values(field.fields)) normalizeSnapshotField(nested);
|
|
5882
|
+
}
|
|
5883
|
+
/**
|
|
5884
|
+
* Normalize a snapshot type in place to the canonical comparison shape.
|
|
5885
|
+
* Currently fills:
|
|
5886
|
+
* - `pluralForm` via inflection when missing (legacy snapshots written
|
|
5887
|
+
* before `pluralForm` became required may omit it)
|
|
5888
|
+
* - per-field `scale` defaults via {@link normalizeSnapshotField}
|
|
5889
|
+
*
|
|
5890
|
+
* Idempotent — safe to call multiple times on the same input.
|
|
5891
|
+
* @param {TailorDBSnapshotType} type - Snapshot type to normalize
|
|
5892
|
+
*/
|
|
5893
|
+
function normalizeSnapshotType(type) {
|
|
5894
|
+
if (!type.pluralForm) type.pluralForm = inflection.pluralize(type.name);
|
|
5895
|
+
for (const field of Object.values(type.fields)) normalizeSnapshotField(field);
|
|
5896
|
+
}
|
|
5897
|
+
/**
|
|
5898
|
+
* Type guard: is the operand a field-reference (object) operand?
|
|
5899
|
+
* @param {SnapshotPermissionOperand} operand - Operand to test
|
|
5900
|
+
* @returns {boolean} True if operand is a field-ref (not a value operand)
|
|
5864
5901
|
*/
|
|
5865
|
-
function
|
|
5866
|
-
|
|
5867
|
-
if (field.type === "decimal") return 6;
|
|
5902
|
+
function isSnapshotFieldRefOperand(operand) {
|
|
5903
|
+
return typeof operand === "object" && operand !== null && !Array.isArray(operand);
|
|
5868
5904
|
}
|
|
5869
5905
|
/**
|
|
5870
5906
|
* Validate that a migration number follows the expected format (4-digit number)
|
|
@@ -5955,6 +5991,7 @@ function createSnapshotFieldConfig(field) {
|
|
|
5955
5991
|
config.fields = {};
|
|
5956
5992
|
for (const [nestedName, nestedConfig] of Object.entries(field.config.fields)) config.fields[nestedName] = createSnapshotFieldConfigFromOperatorConfig(nestedConfig);
|
|
5957
5993
|
}
|
|
5994
|
+
normalizeSnapshotField(config);
|
|
5958
5995
|
return config;
|
|
5959
5996
|
}
|
|
5960
5997
|
/**
|
|
@@ -6000,21 +6037,22 @@ function createSnapshotFieldConfigFromOperatorConfig(fieldConfig) {
|
|
|
6000
6037
|
config.fields = {};
|
|
6001
6038
|
for (const [nestedName, nestedConfig] of Object.entries(fieldConfig.fields)) config.fields[nestedName] = createSnapshotFieldConfigFromOperatorConfig(nestedConfig);
|
|
6002
6039
|
}
|
|
6040
|
+
normalizeSnapshotField(config);
|
|
6003
6041
|
return config;
|
|
6004
6042
|
}
|
|
6005
6043
|
/**
|
|
6006
6044
|
* Create a snapshot type from a parsed type
|
|
6007
6045
|
* @param {TailorDBType} type - Parsed TailorDB type definition
|
|
6008
|
-
* @returns {
|
|
6046
|
+
* @returns {TailorDBSnapshotType} Snapshot type configuration
|
|
6009
6047
|
*/
|
|
6010
6048
|
function createSnapshotType(type) {
|
|
6011
6049
|
const fields = {};
|
|
6012
6050
|
for (const [fieldName, field] of Object.entries(type.fields)) fields[fieldName] = createSnapshotFieldConfig(field);
|
|
6013
6051
|
const snapshotType = {
|
|
6014
6052
|
name: type.name,
|
|
6053
|
+
pluralForm: type.pluralForm || inflection.pluralize(type.name),
|
|
6015
6054
|
fields
|
|
6016
6055
|
};
|
|
6017
|
-
if (type.pluralForm) snapshotType.pluralForm = type.pluralForm;
|
|
6018
6056
|
if (type.description) snapshotType.description = type.description;
|
|
6019
6057
|
if (type.settings) {
|
|
6020
6058
|
snapshotType.settings = {};
|
|
@@ -6111,7 +6149,9 @@ function createSnapshotFromLocalTypes(types, namespace) {
|
|
|
6111
6149
|
*/
|
|
6112
6150
|
function loadSnapshot(filePath) {
|
|
6113
6151
|
const content = fs$1.readFileSync(filePath, "utf-8");
|
|
6114
|
-
|
|
6152
|
+
const snapshot = JSON.parse(content);
|
|
6153
|
+
for (const type of Object.values(snapshot.types)) normalizeSnapshotType(type);
|
|
6154
|
+
return snapshot;
|
|
6115
6155
|
}
|
|
6116
6156
|
/**
|
|
6117
6157
|
* Load a migration diff from a file
|
|
@@ -6120,7 +6160,13 @@ function loadSnapshot(filePath) {
|
|
|
6120
6160
|
*/
|
|
6121
6161
|
function loadDiff(filePath) {
|
|
6122
6162
|
const content = fs$1.readFileSync(filePath, "utf-8");
|
|
6123
|
-
|
|
6163
|
+
const parsed = JSON.parse(content);
|
|
6164
|
+
const warnings = parsed.warnings ?? [];
|
|
6165
|
+
return {
|
|
6166
|
+
...parsed,
|
|
6167
|
+
warnings,
|
|
6168
|
+
hasWarnings: warnings.length > 0
|
|
6169
|
+
};
|
|
6124
6170
|
}
|
|
6125
6171
|
/**
|
|
6126
6172
|
* Get all migration directories and their files, sorted by number
|
|
@@ -6383,7 +6429,7 @@ function areFieldsDifferent(oldField, newField) {
|
|
|
6383
6429
|
if (oldSerial.maxValue !== newSerial.maxValue) return true;
|
|
6384
6430
|
if ((oldSerial.format ?? "") !== (newSerial.format ?? "")) return true;
|
|
6385
6431
|
}
|
|
6386
|
-
if (
|
|
6432
|
+
if (oldField.scale !== newField.scale) return true;
|
|
6387
6433
|
const oldFields = oldField.fields ?? {};
|
|
6388
6434
|
const newFields = newField.fields ?? {};
|
|
6389
6435
|
const oldFieldNames = Object.keys(oldFields);
|
|
@@ -6461,10 +6507,17 @@ function isBreakingFieldChange(typeName, fieldName, oldField, newField) {
|
|
|
6461
6507
|
}
|
|
6462
6508
|
function addChange(ctx, change, oldField, newField) {
|
|
6463
6509
|
ctx.changes.push(change);
|
|
6464
|
-
if (change.fieldName)
|
|
6465
|
-
|
|
6466
|
-
|
|
6510
|
+
if (!change.fieldName) return;
|
|
6511
|
+
const breaking = isBreakingFieldChange(change.typeName, change.fieldName, oldField, newField);
|
|
6512
|
+
if (breaking) {
|
|
6513
|
+
ctx.breakingChanges.push(breaking);
|
|
6514
|
+
return;
|
|
6467
6515
|
}
|
|
6516
|
+
if (change.kind === "field_removed") ctx.warnings.push({
|
|
6517
|
+
typeName: change.typeName,
|
|
6518
|
+
fieldName: change.fieldName,
|
|
6519
|
+
reason: "Field removed (existing data will be dropped in the post-migration phase)"
|
|
6520
|
+
});
|
|
6468
6521
|
}
|
|
6469
6522
|
function compareTypeFields(ctx, typeName, prevType, currType) {
|
|
6470
6523
|
const prevFieldNames = new Set(Object.keys(prevType.fields));
|
|
@@ -6655,9 +6708,12 @@ function comparePermissions(ctx, typeName, oldRecordPerm, newRecordPerm, oldGqlP
|
|
|
6655
6708
|
* @returns {MigrationDiff} Migration diff between snapshots
|
|
6656
6709
|
*/
|
|
6657
6710
|
function compareSnapshots(previous, current) {
|
|
6711
|
+
for (const type of Object.values(previous.types)) normalizeSnapshotType(type);
|
|
6712
|
+
for (const type of Object.values(current.types)) normalizeSnapshotType(type);
|
|
6658
6713
|
const ctx = {
|
|
6659
6714
|
changes: [],
|
|
6660
|
-
breakingChanges: []
|
|
6715
|
+
breakingChanges: [],
|
|
6716
|
+
warnings: []
|
|
6661
6717
|
};
|
|
6662
6718
|
const previousTypeNames = new Set(Object.keys(previous.types));
|
|
6663
6719
|
const currentTypeNames = new Set(Object.keys(current.types));
|
|
@@ -6666,11 +6722,17 @@ function compareSnapshots(previous, current) {
|
|
|
6666
6722
|
typeName,
|
|
6667
6723
|
after: current.types[typeName]
|
|
6668
6724
|
});
|
|
6669
|
-
for (const typeName of previousTypeNames) if (!currentTypeNames.has(typeName))
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6725
|
+
for (const typeName of previousTypeNames) if (!currentTypeNames.has(typeName)) {
|
|
6726
|
+
ctx.changes.push({
|
|
6727
|
+
kind: "type_removed",
|
|
6728
|
+
typeName,
|
|
6729
|
+
before: previous.types[typeName]
|
|
6730
|
+
});
|
|
6731
|
+
ctx.warnings.push({
|
|
6732
|
+
typeName,
|
|
6733
|
+
reason: "Type removed (all records of this type will be dropped in the post-migration phase)"
|
|
6734
|
+
});
|
|
6735
|
+
}
|
|
6674
6736
|
for (const typeName of currentTypeNames) {
|
|
6675
6737
|
if (!previousTypeNames.has(typeName)) continue;
|
|
6676
6738
|
const prevType = previous.types[typeName];
|
|
@@ -6689,18 +6751,29 @@ function compareSnapshots(previous, current) {
|
|
|
6689
6751
|
changes: ctx.changes,
|
|
6690
6752
|
hasBreakingChanges: ctx.breakingChanges.length > 0,
|
|
6691
6753
|
breakingChanges: ctx.breakingChanges,
|
|
6754
|
+
hasWarnings: ctx.warnings.length > 0,
|
|
6755
|
+
warnings: ctx.warnings,
|
|
6692
6756
|
requiresMigrationScript: ctx.breakingChanges.length > 0
|
|
6693
6757
|
};
|
|
6694
6758
|
}
|
|
6695
6759
|
/**
|
|
6696
|
-
* Compare
|
|
6760
|
+
* Compare a snapshot against canonical TailorDBSnapshotType-shaped local types.
|
|
6761
|
+
* Callers are expected to pre-convert TailorDBService.types to TailorDBSnapshotType via
|
|
6762
|
+
* `createSnapshotType`. As a safety net, `compareSnapshots` re-runs idempotent
|
|
6763
|
+
* normalization on both sides, so a caller that forgets will still get correct
|
|
6764
|
+
* comparisons (no silent false drift).
|
|
6697
6765
|
* @param {SchemaSnapshot} snapshot - Schema snapshot to compare against
|
|
6698
|
-
* @param {Record<string,
|
|
6766
|
+
* @param {Record<string, TailorDBSnapshotType>} localTypes - Local snapshot-shaped types
|
|
6699
6767
|
* @param {string} namespace - Namespace for comparison
|
|
6700
6768
|
* @returns {MigrationDiff} Migration diff
|
|
6701
6769
|
*/
|
|
6702
6770
|
function compareLocalTypesWithSnapshot(snapshot, localTypes, namespace) {
|
|
6703
|
-
return compareSnapshots(snapshot,
|
|
6771
|
+
return compareSnapshots(snapshot, {
|
|
6772
|
+
version: 1,
|
|
6773
|
+
namespace,
|
|
6774
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6775
|
+
types: localTypes
|
|
6776
|
+
});
|
|
6704
6777
|
}
|
|
6705
6778
|
/**
|
|
6706
6779
|
* Validate migration files in a directory
|
|
@@ -6807,6 +6880,7 @@ function convertRemoteFieldsToSnapshot(remoteType) {
|
|
|
6807
6880
|
...remoteField.serial.format && { format: remoteField.serial.format }
|
|
6808
6881
|
};
|
|
6809
6882
|
if (remoteField.scale !== void 0) config.scale = remoteField.scale;
|
|
6883
|
+
normalizeSnapshotField(config);
|
|
6810
6884
|
fields[fieldName] = config;
|
|
6811
6885
|
}
|
|
6812
6886
|
return fields;
|
|
@@ -6851,9 +6925,7 @@ function compareFields(typeName, fieldName, remoteField, snapshotField) {
|
|
|
6851
6925
|
const remoteVector = remoteField.vector ?? false;
|
|
6852
6926
|
const snapshotVector = snapshotField.vector ?? false;
|
|
6853
6927
|
if (remoteVector !== snapshotVector) differences.push(`vector: remote=${remoteVector}, expected=${snapshotVector}`);
|
|
6854
|
-
|
|
6855
|
-
const snapshotScale = getEffectiveScale(snapshotField);
|
|
6856
|
-
if (remoteScale !== snapshotScale) differences.push(`scale: remote=${remoteScale}, expected=${snapshotScale}`);
|
|
6928
|
+
if (remoteField.scale !== snapshotField.scale) differences.push(`scale: remote=${remoteField.scale}, expected=${snapshotField.scale}`);
|
|
6857
6929
|
if (differences.length > 0) return {
|
|
6858
6930
|
typeName,
|
|
6859
6931
|
kind: "field_mismatch",
|
|
@@ -6873,6 +6945,7 @@ const SYSTEM_FIELDS = new Set(["id"]);
|
|
|
6873
6945
|
* @returns {SchemaDrift[]} List of drifts detected
|
|
6874
6946
|
*/
|
|
6875
6947
|
function compareRemoteWithSnapshot(remoteTypes, snapshot) {
|
|
6948
|
+
for (const type of Object.values(snapshot.types)) normalizeSnapshotType(type);
|
|
6876
6949
|
const drifts = [];
|
|
6877
6950
|
const remoteTypeMap = /* @__PURE__ */ new Map();
|
|
6878
6951
|
for (const remoteType of remoteTypes) remoteTypeMap.set(remoteType.name, remoteType);
|
|
@@ -6938,6 +7011,189 @@ function formatSchemaDrifts(drifts) {
|
|
|
6938
7011
|
return lines.join("\n");
|
|
6939
7012
|
}
|
|
6940
7013
|
|
|
7014
|
+
//#endregion
|
|
7015
|
+
//#region src/cli/commands/tailordb/migrate/snapshot-manifest.ts
|
|
7016
|
+
/**
|
|
7017
|
+
* Convert a snapshot field config to proto format
|
|
7018
|
+
* @param {SnapshotFieldConfig} config - Snapshot field config
|
|
7019
|
+
* @returns {MessageInitShape<typeof TailorDBType_FieldConfigSchema>} Proto field config
|
|
7020
|
+
*/
|
|
7021
|
+
function convertFieldConfigToProto(config) {
|
|
7022
|
+
const fieldEntry = {
|
|
7023
|
+
type: config.type,
|
|
7024
|
+
allowedValues: config.type === "enum" ? config.allowedValues?.map((v) => ({ ...v })) ?? [] : [],
|
|
7025
|
+
description: config.description || "",
|
|
7026
|
+
validate: toProtoSnapshotFieldValidate(config),
|
|
7027
|
+
array: config.array ?? false,
|
|
7028
|
+
index: config.index ?? false,
|
|
7029
|
+
unique: config.unique ?? false,
|
|
7030
|
+
foreignKey: config.foreignKey ?? false,
|
|
7031
|
+
foreignKeyType: config.foreignKeyType,
|
|
7032
|
+
foreignKeyField: config.foreignKeyField,
|
|
7033
|
+
required: config.required ?? true,
|
|
7034
|
+
vector: config.vector ?? false,
|
|
7035
|
+
...toProtoSnapshotFieldHooks(config),
|
|
7036
|
+
...config.serial && { serial: {
|
|
7037
|
+
start: BigInt(config.serial.start),
|
|
7038
|
+
...config.serial.maxValue !== void 0 && { maxValue: BigInt(config.serial.maxValue) },
|
|
7039
|
+
...config.serial.format && { format: config.serial.format }
|
|
7040
|
+
} },
|
|
7041
|
+
...config.scale !== void 0 && { scale: config.scale }
|
|
7042
|
+
};
|
|
7043
|
+
if (config.type === "nested" && config.fields) fieldEntry.fields = processNestedFieldsFromSnapshot(config.fields);
|
|
7044
|
+
return fieldEntry;
|
|
7045
|
+
}
|
|
7046
|
+
function toProtoSnapshotFieldValidate(config) {
|
|
7047
|
+
return (config.validate ?? []).map((val) => ({
|
|
7048
|
+
action: TailorDBType_PermitAction.DENY,
|
|
7049
|
+
errorMessage: val.errorMessage || "",
|
|
7050
|
+
...val.script && { script: { expr: val.script.expr ? `!${val.script.expr}` : "" } }
|
|
7051
|
+
}));
|
|
7052
|
+
}
|
|
7053
|
+
function toProtoSnapshotFieldHooks(config) {
|
|
7054
|
+
if (!config.hooks) return {};
|
|
7055
|
+
return { hooks: {
|
|
7056
|
+
create: config.hooks.create ? { expr: config.hooks.create.expr || "" } : void 0,
|
|
7057
|
+
update: config.hooks.update ? { expr: config.hooks.update.expr || "" } : void 0
|
|
7058
|
+
} };
|
|
7059
|
+
}
|
|
7060
|
+
/**
|
|
7061
|
+
* Process nested fields from snapshot format to proto format
|
|
7062
|
+
* @param {Record<string, SnapshotFieldConfig>} fields - Nested fields
|
|
7063
|
+
* @returns {Record<string, MessageInitShape<typeof TailorDBType_FieldConfigSchema>>} Proto nested fields
|
|
7064
|
+
*/
|
|
7065
|
+
function processNestedFieldsFromSnapshot(fields) {
|
|
7066
|
+
const nestedFields = {};
|
|
7067
|
+
for (const [fieldName, fieldConfig] of Object.entries(fields)) if (fieldConfig.type === "nested" && fieldConfig.fields) {
|
|
7068
|
+
const deepNestedFields = processNestedFieldsFromSnapshot(fieldConfig.fields);
|
|
7069
|
+
nestedFields[fieldName] = {
|
|
7070
|
+
type: "nested",
|
|
7071
|
+
allowedValues: fieldConfig.allowedValues?.map((v) => ({ ...v })) ?? [],
|
|
7072
|
+
description: fieldConfig.description || "",
|
|
7073
|
+
validate: toProtoSnapshotFieldValidate(fieldConfig),
|
|
7074
|
+
required: fieldConfig.required ?? true,
|
|
7075
|
+
array: fieldConfig.array ?? false,
|
|
7076
|
+
index: false,
|
|
7077
|
+
unique: false,
|
|
7078
|
+
foreignKey: false,
|
|
7079
|
+
vector: false,
|
|
7080
|
+
...toProtoSnapshotFieldHooks(fieldConfig),
|
|
7081
|
+
fields: deepNestedFields,
|
|
7082
|
+
...fieldConfig.scale !== void 0 && { scale: fieldConfig.scale }
|
|
7083
|
+
};
|
|
7084
|
+
} else nestedFields[fieldName] = {
|
|
7085
|
+
type: fieldConfig.type,
|
|
7086
|
+
allowedValues: fieldConfig.type === "enum" ? fieldConfig.allowedValues?.map((v) => ({ ...v })) ?? [] : [],
|
|
7087
|
+
description: fieldConfig.description || "",
|
|
7088
|
+
validate: toProtoSnapshotFieldValidate(fieldConfig),
|
|
7089
|
+
required: fieldConfig.required ?? true,
|
|
7090
|
+
array: fieldConfig.array ?? false,
|
|
7091
|
+
index: false,
|
|
7092
|
+
unique: false,
|
|
7093
|
+
foreignKey: false,
|
|
7094
|
+
vector: false,
|
|
7095
|
+
...toProtoSnapshotFieldHooks(fieldConfig),
|
|
7096
|
+
...fieldConfig.serial && { serial: {
|
|
7097
|
+
start: BigInt(fieldConfig.serial.start),
|
|
7098
|
+
...fieldConfig.serial.maxValue !== void 0 && { maxValue: BigInt(fieldConfig.serial.maxValue) },
|
|
7099
|
+
...fieldConfig.serial.format && { format: fieldConfig.serial.format }
|
|
7100
|
+
} },
|
|
7101
|
+
...fieldConfig.scale !== void 0 && { scale: fieldConfig.scale }
|
|
7102
|
+
};
|
|
7103
|
+
return nestedFields;
|
|
7104
|
+
}
|
|
7105
|
+
|
|
7106
|
+
//#endregion
|
|
7107
|
+
//#region src/cli/commands/tailordb/migrate/pre-migration-schema.ts
|
|
7108
|
+
/**
|
|
7109
|
+
* Pre-migration field config adjustments
|
|
7110
|
+
*
|
|
7111
|
+
* The Pre-phase sends a "relaxed" version of the target schema so that
|
|
7112
|
+
* `migrate.ts` scripts can still operate on the previous shape of the data.
|
|
7113
|
+
* This module handles the field-level adjustments:
|
|
7114
|
+
*
|
|
7115
|
+
* - `field_removed`: re-insert the removed field so migrate.ts can read it
|
|
7116
|
+
* (the physical drop happens in Post-phase).
|
|
7117
|
+
* - `field_added` with `required: true`: relax to `required: false`.
|
|
7118
|
+
* - `field_modified` optional→required, unique constraint added, enum
|
|
7119
|
+
* value removed: keep the looser side until Post-phase.
|
|
7120
|
+
*
|
|
7121
|
+
* Type-level deletions (`type_removed`) are handled by the deploy flow,
|
|
7122
|
+
* which retains the type until Post-phase rather than via this module.
|
|
7123
|
+
*
|
|
7124
|
+
* Post-phase then sends the final schema, after migrate.ts has had a chance
|
|
7125
|
+
* to fix up data.
|
|
7126
|
+
*/
|
|
7127
|
+
/**
|
|
7128
|
+
* Diff change kinds that require pre-migration schema adjustments.
|
|
7129
|
+
*/
|
|
7130
|
+
const PRE_MIGRATION_FIELD_KINDS = new Set([
|
|
7131
|
+
"field_added",
|
|
7132
|
+
"field_modified",
|
|
7133
|
+
"field_removed"
|
|
7134
|
+
]);
|
|
7135
|
+
/**
|
|
7136
|
+
* Build a map of field changes that require pre-migration schema adjustment.
|
|
7137
|
+
* @param {PendingMigration[]} pendingMigrations - Pending migrations to scan
|
|
7138
|
+
* @returns {PreMigrationChangesMap} Map of changes keyed by typeName/fieldName
|
|
7139
|
+
*/
|
|
7140
|
+
function buildPreMigrationChangesMap(pendingMigrations) {
|
|
7141
|
+
const map = /* @__PURE__ */ new Map();
|
|
7142
|
+
for (const migration of pendingMigrations) for (const change of migration.diff.changes) {
|
|
7143
|
+
if (!PRE_MIGRATION_FIELD_KINDS.has(change.kind)) continue;
|
|
7144
|
+
if (!change.fieldName) continue;
|
|
7145
|
+
const perType = map.get(change.typeName) ?? /* @__PURE__ */ new Map();
|
|
7146
|
+
perType.set(change.fieldName, change);
|
|
7147
|
+
map.set(change.typeName, perType);
|
|
7148
|
+
}
|
|
7149
|
+
return map;
|
|
7150
|
+
}
|
|
7151
|
+
/**
|
|
7152
|
+
* Apply pre-migration schema adjustments to a single field map in place.
|
|
7153
|
+
*
|
|
7154
|
+
* The fields map is the proto-shape `TailorDBType.schema.fields` that will
|
|
7155
|
+
* be sent in the Pre-phase. We mutate it so that:
|
|
7156
|
+
*
|
|
7157
|
+
* - Removed fields are re-inserted using their pre-migration config.
|
|
7158
|
+
* - Newly added required fields are relaxed to optional.
|
|
7159
|
+
* - Modified fields keep the looser side of unique/required/enum.
|
|
7160
|
+
*
|
|
7161
|
+
* @param {Record<string, MessageInitShape<typeof TailorDBType_FieldConfigSchema>>} fields - Field map to adjust (mutated in place)
|
|
7162
|
+
* @param {Map<string, DiffChange>} typeChanges - Changes for this type, keyed by fieldName
|
|
7163
|
+
*/
|
|
7164
|
+
function applyPreMigrationFieldAdjustments(fields, typeChanges) {
|
|
7165
|
+
for (const [fieldName, change] of typeChanges) {
|
|
7166
|
+
if (change.kind === "field_removed") {
|
|
7167
|
+
const before = change.before;
|
|
7168
|
+
if (before) fields[fieldName] = convertFieldConfigToProto(before);
|
|
7169
|
+
continue;
|
|
7170
|
+
}
|
|
7171
|
+
const field = fields[fieldName];
|
|
7172
|
+
if (!field) continue;
|
|
7173
|
+
const before = change.before;
|
|
7174
|
+
const after = change.after;
|
|
7175
|
+
if (change.kind === "field_added" && after?.required) {
|
|
7176
|
+
field.required = false;
|
|
7177
|
+
continue;
|
|
7178
|
+
}
|
|
7179
|
+
if (change.kind !== "field_modified") continue;
|
|
7180
|
+
if (!before?.required && after?.required) field.required = false;
|
|
7181
|
+
if (!(before?.unique ?? false) && (after?.unique ?? false)) field.unique = false;
|
|
7182
|
+
if (before?.allowedValues && after?.allowedValues) {
|
|
7183
|
+
const afterValues = new Set(after.allowedValues.map((v) => v.value));
|
|
7184
|
+
if (before.allowedValues.filter((v) => !afterValues.has(v.value)).length > 0) {
|
|
7185
|
+
const valueMap = /* @__PURE__ */ new Map();
|
|
7186
|
+
for (const v of before.allowedValues) valueMap.set(v.value, v.description ?? "");
|
|
7187
|
+
for (const v of after.allowedValues) if (!valueMap.has(v.value)) valueMap.set(v.value, v.description ?? "");
|
|
7188
|
+
field.allowedValues = Array.from(valueMap.entries()).map(([value, description]) => ({
|
|
7189
|
+
value,
|
|
7190
|
+
description
|
|
7191
|
+
}));
|
|
7192
|
+
}
|
|
7193
|
+
}
|
|
7194
|
+
}
|
|
7195
|
+
}
|
|
7196
|
+
|
|
6941
7197
|
//#endregion
|
|
6942
7198
|
//#region src/cli/commands/tailordb/migrate/bundler.ts
|
|
6943
7199
|
/**
|
|
@@ -7316,13 +7572,15 @@ async function detectPendingMigrations(client, workspaceId, namespacesWithMigrat
|
|
|
7316
7572
|
if (!fs$1.existsSync(diffPath)) continue;
|
|
7317
7573
|
const diff = loadDiff(diffPath);
|
|
7318
7574
|
const scriptPath = getMigrationFilePath(migrationsDir, file.number, "migrate");
|
|
7319
|
-
|
|
7575
|
+
const hasScript = fs$1.existsSync(scriptPath);
|
|
7576
|
+
if (diff.requiresMigrationScript && !hasScript) {
|
|
7320
7577
|
logger.warn(`Migration ${namespace}/${file.number} requires a script but migrate.ts not found`);
|
|
7321
7578
|
continue;
|
|
7322
7579
|
}
|
|
7323
7580
|
pendingMigrations.push({
|
|
7324
7581
|
number: file.number,
|
|
7325
7582
|
scriptPath,
|
|
7583
|
+
hasScript,
|
|
7326
7584
|
diffPath,
|
|
7327
7585
|
namespace,
|
|
7328
7586
|
migrationsDir,
|
|
@@ -7387,7 +7645,7 @@ async function updateMigrationLabel(client, workspaceId, namespace, migrationNum
|
|
|
7387
7645
|
* @returns {Promise<void>}
|
|
7388
7646
|
*/
|
|
7389
7647
|
async function executeMigrations(context, migrations) {
|
|
7390
|
-
const migrationsWithScripts = migrations.filter((m) => m.
|
|
7648
|
+
const migrationsWithScripts = migrations.filter((m) => m.hasScript);
|
|
7391
7649
|
if (migrationsWithScripts.length === 0) return;
|
|
7392
7650
|
const migrationsByNamespace = groupMigrationsByNamespace(migrationsWithScripts);
|
|
7393
7651
|
for (const [namespace, namespaceMigrations] of migrationsByNamespace) {
|
|
@@ -7553,7 +7811,7 @@ function formatRemoteVerificationResults(results) {
|
|
|
7553
7811
|
* Validate migration files and detect pending migrations
|
|
7554
7812
|
* @param {OperatorClient} client - Operator client instance
|
|
7555
7813
|
* @param {string} workspaceId - Workspace ID
|
|
7556
|
-
* @param {ReadonlyMap<string, Record<string,
|
|
7814
|
+
* @param {ReadonlyMap<string, Record<string, TailorDBSnapshotType>>} typesByNamespace - Types by namespace
|
|
7557
7815
|
* @param {LoadedConfig} config - Loaded application config (includes path)
|
|
7558
7816
|
* @param {boolean} noSchemaCheck - Whether to skip schema diff check
|
|
7559
7817
|
* @returns {Promise<ValidateAndDetectResult>} Pending migrations and namespaces that have migration directories configured
|
|
@@ -7590,8 +7848,8 @@ async function validateAndDetectMigrations(client, workspaceId, typesByNamespace
|
|
|
7590
7848
|
pendingMigrations = await detectPendingMigrations(client, workspaceId, namespacesWithMigrations);
|
|
7591
7849
|
if (pendingMigrations.length > 0) {
|
|
7592
7850
|
logger.newline();
|
|
7593
|
-
const withScripts = pendingMigrations.filter((m) => m.
|
|
7594
|
-
const withoutScripts = pendingMigrations.filter((m) => !m.
|
|
7851
|
+
const withScripts = pendingMigrations.filter((m) => m.hasScript);
|
|
7852
|
+
const withoutScripts = pendingMigrations.filter((m) => !m.hasScript);
|
|
7595
7853
|
logger.info(`Applying ${pendingMigrations.length} migration(s):`);
|
|
7596
7854
|
if (withoutScripts.length > 0) logger.info(` • ${withoutScripts.length} schema change(s) (applied automatically with schema deployment)`, { mode: "plain" });
|
|
7597
7855
|
if (withScripts.length > 0) logger.info(` • ${withScripts.length} data migration(s) (requires migration script execution)`, { mode: "plain" });
|
|
@@ -7660,25 +7918,23 @@ async function applyTailorDB(client, result, phase = "create-update") {
|
|
|
7660
7918
|
const { changeSet, context: migrationContext } = result;
|
|
7661
7919
|
if (phase === "create-update") {
|
|
7662
7920
|
const typesByNamespace = /* @__PURE__ */ new Map();
|
|
7663
|
-
for (const tailordb of migrationContext.
|
|
7664
|
-
const types = tailordb.types;
|
|
7665
|
-
if (types) typesByNamespace.set(tailordb.namespace, types);
|
|
7666
|
-
}
|
|
7921
|
+
for (const tailordb of migrationContext.tailorDBInputs) typesByNamespace.set(tailordb.namespace, tailordb.types);
|
|
7667
7922
|
const { pendingMigrations, namespacesWithMigrations } = await validateAndDetectMigrations(client, migrationContext.workspaceId, typesByNamespace, migrationContext.config, migrationContext.noSchemaCheck);
|
|
7668
7923
|
if (pendingMigrations.length > 0) {
|
|
7669
7924
|
processedTypes.reset();
|
|
7670
7925
|
deletedResources.reset();
|
|
7926
|
+
migrationSnapshotCache.reset();
|
|
7671
7927
|
await executeServicesCreation(client, changeSet);
|
|
7672
|
-
const migrationsRequiringScripts = pendingMigrations.filter((m) => m.
|
|
7928
|
+
const migrationsRequiringScripts = pendingMigrations.filter((m) => m.hasScript);
|
|
7673
7929
|
const migrationCtx = migrationsRequiringScripts.length > 0 ? buildMigrationContextForScripts(client, migrationContext, migrationsRequiringScripts) : void 0;
|
|
7674
7930
|
if (migrationsRequiringScripts.length > 0) {
|
|
7675
7931
|
logger.info(`Executing ${migrationsRequiringScripts.length} data migration(s)...`);
|
|
7676
7932
|
logger.newline();
|
|
7677
7933
|
}
|
|
7678
7934
|
for (const migration of pendingMigrations) {
|
|
7679
|
-
await executeSingleMigrationPrePhase(client, changeSet, migration);
|
|
7680
|
-
if (migration.
|
|
7681
|
-
await executeSingleMigrationPostPhase(client, changeSet, migration);
|
|
7935
|
+
await executeSingleMigrationPrePhase(client, changeSet, migration, migrationContext.tailorDBInputs, migrationContext.executorUsedTypes);
|
|
7936
|
+
if (migration.hasScript && migrationCtx) await executeMigrations(migrationCtx, [migration]);
|
|
7937
|
+
await executeSingleMigrationPostPhase(client, changeSet, migration, migrationContext.tailorDBInputs, migrationContext.executorUsedTypes);
|
|
7682
7938
|
await updateMigrationLabel(client, migrationContext.workspaceId, migration.namespace, migration.number);
|
|
7683
7939
|
}
|
|
7684
7940
|
if (migrationsRequiringScripts.length > 0) {
|
|
@@ -7724,49 +7980,6 @@ function handleOptionalToRequiredError(error, messages) {
|
|
|
7724
7980
|
throw error;
|
|
7725
7981
|
}
|
|
7726
7982
|
/**
|
|
7727
|
-
* Build a map of breaking field changes from pending migrations
|
|
7728
|
-
* @param {PendingMigration[]} pendingMigrations - Pending migrations
|
|
7729
|
-
* @returns {BreakingChangesMap} Map of breaking changes
|
|
7730
|
-
*/
|
|
7731
|
-
function buildBreakingChangesMap(pendingMigrations) {
|
|
7732
|
-
const map = /* @__PURE__ */ new Map();
|
|
7733
|
-
for (const migration of pendingMigrations) for (const change of migration.diff.changes) if (change.kind === "field_added" || change.kind === "field_modified" || change.kind === "field_removed") {
|
|
7734
|
-
if (!change.fieldName) continue;
|
|
7735
|
-
if (!map.has(change.typeName)) map.set(change.typeName, /* @__PURE__ */ new Map());
|
|
7736
|
-
map.get(change.typeName).set(change.fieldName, change);
|
|
7737
|
-
}
|
|
7738
|
-
return map;
|
|
7739
|
-
}
|
|
7740
|
-
/**
|
|
7741
|
-
* Apply pre-migration schema adjustments to avoid breaking changes before scripts run.
|
|
7742
|
-
* @param fields - Field configs to adjust
|
|
7743
|
-
* @param typeChanges - Breaking changes for a type
|
|
7744
|
-
*/
|
|
7745
|
-
function applyPreMigrationFieldAdjustments(fields, typeChanges) {
|
|
7746
|
-
for (const [fieldName, change] of typeChanges) {
|
|
7747
|
-
const field = fields[fieldName];
|
|
7748
|
-
if (!field) continue;
|
|
7749
|
-
const before = change.before;
|
|
7750
|
-
const after = change.after;
|
|
7751
|
-
if (change.kind === "field_added" && after?.required) field.required = false;
|
|
7752
|
-
if (change.kind !== "field_modified") continue;
|
|
7753
|
-
if (!before?.required && after?.required) field.required = false;
|
|
7754
|
-
if (!(before?.unique ?? false) && (after?.unique ?? false)) field.unique = false;
|
|
7755
|
-
if (before?.allowedValues && after?.allowedValues) {
|
|
7756
|
-
const afterValues = new Set(after.allowedValues.map((v) => v.value));
|
|
7757
|
-
if (before.allowedValues.filter((v) => !afterValues.has(v.value)).length > 0) {
|
|
7758
|
-
const valueMap = /* @__PURE__ */ new Map();
|
|
7759
|
-
for (const v of before.allowedValues) valueMap.set(v.value, v.description ?? "");
|
|
7760
|
-
for (const v of after.allowedValues) if (!valueMap.has(v.value)) valueMap.set(v.value, v.description ?? "");
|
|
7761
|
-
field.allowedValues = Array.from(valueMap.entries()).map(([value, description]) => ({
|
|
7762
|
-
value,
|
|
7763
|
-
description
|
|
7764
|
-
}));
|
|
7765
|
-
}
|
|
7766
|
-
}
|
|
7767
|
-
}
|
|
7768
|
-
}
|
|
7769
|
-
/**
|
|
7770
7983
|
* Get the set of type names affected by a migration
|
|
7771
7984
|
* @param {PendingMigration} migration - Pending migration
|
|
7772
7985
|
* @returns {Set<string>} Set of affected type names
|
|
@@ -7812,14 +8025,54 @@ const processedTypes = {
|
|
|
7812
8025
|
}
|
|
7813
8026
|
};
|
|
7814
8027
|
/**
|
|
8028
|
+
* Snapshot cache for per-migration schema lookups during a single apply run.
|
|
8029
|
+
*
|
|
8030
|
+
* Only the initial baseline `0000/schema.json` is stored on disk; later migrations
|
|
8031
|
+
* ship `diff.json` only. To get the schema state AFTER migration N we replay the
|
|
8032
|
+
* initial snapshot through all diffs up to N via `reconstructSnapshotFromMigrations`.
|
|
8033
|
+
* Results are memoized per (namespace, migration number) for the apply run.
|
|
8034
|
+
*/
|
|
8035
|
+
const migrationSnapshotCache = {
|
|
8036
|
+
cache: /* @__PURE__ */ new Map(),
|
|
8037
|
+
reset() {
|
|
8038
|
+
this.cache.clear();
|
|
8039
|
+
},
|
|
8040
|
+
load(migration) {
|
|
8041
|
+
const key = `${migration.namespace}/${migration.number}`;
|
|
8042
|
+
let snapshot = this.cache.get(key);
|
|
8043
|
+
if (!snapshot) {
|
|
8044
|
+
const reconstructed = reconstructSnapshotFromMigrations(migration.migrationsDir, migration.number);
|
|
8045
|
+
if (!reconstructed) throw new Error(`Cannot reconstruct snapshot for ${migration.namespace} migration ${migration.number}: no migrations found in ${migration.migrationsDir}`);
|
|
8046
|
+
snapshot = reconstructed;
|
|
8047
|
+
this.cache.set(key, snapshot);
|
|
8048
|
+
}
|
|
8049
|
+
return snapshot;
|
|
8050
|
+
}
|
|
8051
|
+
};
|
|
8052
|
+
/**
|
|
8053
|
+
* Build the TailorDBType manifest for `typeName` from migration N's snapshot.
|
|
8054
|
+
* @param migration - The pending migration whose snapshot to consult
|
|
8055
|
+
* @param typeName - The type name to look up in the snapshot
|
|
8056
|
+
* @param tailorDBInputs - Deploy inputs, used to resolve namespace gqlOperations
|
|
8057
|
+
* @param executorUsedTypes - Types used by executors (drives publishRecordEvents default)
|
|
8058
|
+
* @returns The manifest, or undefined if `typeName` is not in that snapshot.
|
|
8059
|
+
*/
|
|
8060
|
+
function buildSnapshotTypeManifest(migration, typeName, tailorDBInputs, executorUsedTypes) {
|
|
8061
|
+
const snapshotType = migrationSnapshotCache.load(migration).types[typeName];
|
|
8062
|
+
if (!snapshotType) return void 0;
|
|
8063
|
+
return generateTailorDBTypeManifest(snapshotType, executorUsedTypes, tailorDBInputs.find((i) => i.namespace === migration.namespace)?.config.gqlOperations);
|
|
8064
|
+
}
|
|
8065
|
+
/**
|
|
7815
8066
|
* Execute pre-migration phase for a single migration
|
|
7816
8067
|
* @param {OperatorClient} client - Operator client instance
|
|
7817
8068
|
* @param {TailorDBChangeSet} changeSet - TailorDB change set
|
|
7818
8069
|
* @param {PendingMigration} migration - Single pending migration
|
|
8070
|
+
* @param tailorDBInputs - Deploy inputs, used to resolve namespace gqlOperations for the snapshot
|
|
8071
|
+
* @param executorUsedTypes - Types used by executors (drives publishRecordEvents default)
|
|
7819
8072
|
* @returns {Promise<void>} Promise that resolves when pre-migration phase completes
|
|
7820
8073
|
*/
|
|
7821
|
-
async function executeSingleMigrationPrePhase(client, changeSet, migration) {
|
|
7822
|
-
const
|
|
8074
|
+
async function executeSingleMigrationPrePhase(client, changeSet, migration, tailorDBInputs, executorUsedTypes) {
|
|
8075
|
+
const preMigrationChanges = buildPreMigrationChangesMap([migration]);
|
|
7823
8076
|
const affectedTypes = getAffectedTypeNames(migration);
|
|
7824
8077
|
const createdBeforeMigration = new Set(processedTypes.created);
|
|
7825
8078
|
await Promise.all([
|
|
@@ -7828,11 +8081,13 @@ async function executeSingleMigrationPrePhase(client, changeSet, migration) {
|
|
|
7828
8081
|
return typeName && affectedTypes.has(typeName) && !createdBeforeMigration.has(typeName);
|
|
7829
8082
|
}).map((create) => {
|
|
7830
8083
|
const typeName = create.request.tailordbType?.name;
|
|
8084
|
+
const snapshotType = typeName ? buildSnapshotTypeManifest(migration, typeName, tailorDBInputs, executorUsedTypes) : void 0;
|
|
8085
|
+
if (!snapshotType) return void 0;
|
|
7831
8086
|
if (typeName) processedTypes.created.add(typeName);
|
|
7832
|
-
const typeChanges = typeName ? breakingChanges.get(typeName) : void 0;
|
|
7833
|
-
if (!typeChanges || typeChanges.size === 0) return client.createTailorDBType(create.request);
|
|
7834
8087
|
const clonedRequest = structuredClone(create.request);
|
|
7835
|
-
|
|
8088
|
+
clonedRequest.tailordbType = snapshotType;
|
|
8089
|
+
const typeChanges = typeName ? preMigrationChanges.get(typeName) : void 0;
|
|
8090
|
+
if (typeChanges && typeChanges.size > 0 && clonedRequest.tailordbType?.schema?.fields) applyPreMigrationFieldAdjustments(clonedRequest.tailordbType.schema.fields, typeChanges);
|
|
7836
8091
|
return client.createTailorDBType(clonedRequest);
|
|
7837
8092
|
}),
|
|
7838
8093
|
...changeSet.type.creates.filter((create) => {
|
|
@@ -7840,19 +8095,16 @@ async function executeSingleMigrationPrePhase(client, changeSet, migration) {
|
|
|
7840
8095
|
return typeName && affectedTypes.has(typeName) && createdBeforeMigration.has(typeName);
|
|
7841
8096
|
}).map((create) => {
|
|
7842
8097
|
const typeName = create.request.tailordbType?.name;
|
|
8098
|
+
const snapshotType = typeName ? buildSnapshotTypeManifest(migration, typeName, tailorDBInputs, executorUsedTypes) : void 0;
|
|
8099
|
+
if (!snapshotType) return void 0;
|
|
7843
8100
|
if (typeName) processedTypes.updated.add(typeName);
|
|
7844
|
-
const
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
namespaceName: create.request.namespaceName,
|
|
7848
|
-
tailordbType: create.request.tailordbType
|
|
7849
|
-
});
|
|
7850
|
-
const clonedRequest = structuredClone(create.request);
|
|
7851
|
-
if (clonedRequest.tailordbType?.schema?.fields) applyPreMigrationFieldAdjustments(clonedRequest.tailordbType.schema.fields, typeChanges);
|
|
8101
|
+
const clonedTypeRequest = structuredClone(snapshotType);
|
|
8102
|
+
const typeChanges = typeName ? preMigrationChanges.get(typeName) : void 0;
|
|
8103
|
+
if (typeChanges && typeChanges.size > 0 && clonedTypeRequest.schema?.fields) applyPreMigrationFieldAdjustments(clonedTypeRequest.schema.fields, typeChanges);
|
|
7852
8104
|
return client.updateTailorDBType({
|
|
7853
8105
|
workspaceId: create.request.workspaceId,
|
|
7854
8106
|
namespaceName: create.request.namespaceName,
|
|
7855
|
-
tailordbType:
|
|
8107
|
+
tailordbType: clonedTypeRequest
|
|
7856
8108
|
});
|
|
7857
8109
|
}),
|
|
7858
8110
|
...changeSet.type.updates.filter((update) => {
|
|
@@ -7860,11 +8112,13 @@ async function executeSingleMigrationPrePhase(client, changeSet, migration) {
|
|
|
7860
8112
|
return typeName && affectedTypes.has(typeName);
|
|
7861
8113
|
}).map((update) => {
|
|
7862
8114
|
const typeName = update.request.tailordbType?.name;
|
|
8115
|
+
const snapshotType = typeName ? buildSnapshotTypeManifest(migration, typeName, tailorDBInputs, executorUsedTypes) : void 0;
|
|
8116
|
+
if (!snapshotType) return void 0;
|
|
7863
8117
|
if (typeName) processedTypes.updated.add(typeName);
|
|
7864
|
-
const typeChanges = typeName ? breakingChanges.get(typeName) : void 0;
|
|
7865
|
-
if (!typeChanges || typeChanges.size === 0) return client.updateTailorDBType(update.request);
|
|
7866
8118
|
const clonedRequest = structuredClone(update.request);
|
|
7867
|
-
|
|
8119
|
+
clonedRequest.tailordbType = snapshotType;
|
|
8120
|
+
const typeChanges = typeName ? preMigrationChanges.get(typeName) : void 0;
|
|
8121
|
+
if (typeChanges && typeChanges.size > 0 && clonedRequest.tailordbType?.schema?.fields) applyPreMigrationFieldAdjustments(clonedRequest.tailordbType.schema.fields, typeChanges);
|
|
7868
8122
|
return client.updateTailorDBType(clonedRequest);
|
|
7869
8123
|
})
|
|
7870
8124
|
]);
|
|
@@ -7901,24 +8155,40 @@ const deletedResources = {
|
|
|
7901
8155
|
* @param {OperatorClient} client - Operator client instance
|
|
7902
8156
|
* @param {TailorDBChangeSet} changeSet - TailorDB change set
|
|
7903
8157
|
* @param {PendingMigration} migration - Single pending migration
|
|
8158
|
+
* @param tailorDBInputs - Deploy inputs, used to resolve namespace gqlOperations for the snapshot
|
|
8159
|
+
* @param executorUsedTypes - Types used by executors (drives publishRecordEvents default)
|
|
7904
8160
|
* @returns {Promise<void>} Promise that resolves when post-migration phase completes
|
|
7905
8161
|
*/
|
|
7906
|
-
async function executeSingleMigrationPostPhase(client, changeSet, migration) {
|
|
7907
|
-
const
|
|
8162
|
+
async function executeSingleMigrationPostPhase(client, changeSet, migration, tailorDBInputs, executorUsedTypes) {
|
|
8163
|
+
const preMigrationChanges = buildPreMigrationChangesMap([migration]);
|
|
7908
8164
|
const affectedTypes = getAffectedTypeNames(migration);
|
|
7909
8165
|
const deletedTypeNames = getDeletedTypeNames(migration);
|
|
7910
8166
|
try {
|
|
7911
8167
|
await Promise.all([...changeSet.type.creates.filter((create) => {
|
|
7912
8168
|
const typeName = create.request.tailordbType?.name;
|
|
7913
|
-
return typeName && affectedTypes.has(typeName) &&
|
|
7914
|
-
}).map((create) =>
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
8169
|
+
return typeName && affectedTypes.has(typeName) && preMigrationChanges.has(typeName);
|
|
8170
|
+
}).map((create) => {
|
|
8171
|
+
const typeName = create.request.tailordbType?.name;
|
|
8172
|
+
const snapshotType = typeName ? buildSnapshotTypeManifest(migration, typeName, tailorDBInputs, executorUsedTypes) : void 0;
|
|
8173
|
+
if (!snapshotType) return void 0;
|
|
8174
|
+
return client.updateTailorDBType({
|
|
8175
|
+
workspaceId: create.request.workspaceId,
|
|
8176
|
+
namespaceName: create.request.namespaceName,
|
|
8177
|
+
tailordbType: snapshotType
|
|
8178
|
+
});
|
|
8179
|
+
}), ...changeSet.type.updates.filter((update) => {
|
|
8180
|
+
const typeName = update.request.tailordbType?.name;
|
|
8181
|
+
return typeName && affectedTypes.has(typeName) && preMigrationChanges.has(typeName);
|
|
8182
|
+
}).map((update) => {
|
|
7919
8183
|
const typeName = update.request.tailordbType?.name;
|
|
7920
|
-
|
|
7921
|
-
|
|
8184
|
+
const snapshotType = typeName ? buildSnapshotTypeManifest(migration, typeName, tailorDBInputs, executorUsedTypes) : void 0;
|
|
8185
|
+
if (!snapshotType) return void 0;
|
|
8186
|
+
return client.updateTailorDBType({
|
|
8187
|
+
workspaceId: update.request.workspaceId,
|
|
8188
|
+
namespaceName: update.request.namespaceName,
|
|
8189
|
+
tailordbType: snapshotType
|
|
8190
|
+
});
|
|
8191
|
+
})]);
|
|
7922
8192
|
} catch (error) {
|
|
7923
8193
|
handleOptionalToRequiredError(error, ["This error occurred during post-migration phase. Please check your migration script.", "Ensure all existing records have values for fields being changed to required."]);
|
|
7924
8194
|
}
|
|
@@ -7947,21 +8217,32 @@ async function executeSingleMigrationPostPhase(client, changeSet, migration) {
|
|
|
7947
8217
|
}
|
|
7948
8218
|
}
|
|
7949
8219
|
/**
|
|
7950
|
-
*
|
|
7951
|
-
* @param
|
|
7952
|
-
* @returns
|
|
8220
|
+
* Convert a runtime TailorDBService to the snapshot-shaped deploy input.
|
|
8221
|
+
* @param service - Loaded TailorDB service (after `loadTypes()`)
|
|
8222
|
+
* @returns The canonical snapshot-shaped deploy input for downstream plan/apply phases.
|
|
7953
8223
|
*/
|
|
8224
|
+
function toTailorDBDeployInput(service) {
|
|
8225
|
+
const types = {};
|
|
8226
|
+
for (const [typeName, type] of Object.entries(service.types)) types[typeName] = createSnapshotType(type);
|
|
8227
|
+
return {
|
|
8228
|
+
namespace: service.namespace,
|
|
8229
|
+
config: service.config,
|
|
8230
|
+
types
|
|
8231
|
+
};
|
|
8232
|
+
}
|
|
7954
8233
|
async function planTailorDB(context) {
|
|
7955
8234
|
const { client, workspaceId, application, forRemoval, config, noSchemaCheck, forceApplyAll = false } = context;
|
|
7956
8235
|
const tailordbs = [];
|
|
7957
8236
|
if (!forRemoval) for (const tailordb of application.tailorDBServices) {
|
|
7958
8237
|
await tailordb.loadTypes();
|
|
7959
|
-
tailordbs.push(tailordb);
|
|
8238
|
+
tailordbs.push(toTailorDBDeployInput(tailordb));
|
|
7960
8239
|
}
|
|
7961
8240
|
const executors = forRemoval ? [] : Object.values(await application.executorService?.loadExecutors() ?? {});
|
|
8241
|
+
const executorUsedTypes = /* @__PURE__ */ new Set();
|
|
8242
|
+
for (const executor of executors) if (executor.trigger.kind === "tailordb") executorUsedTypes.add(executor.trigger.typeName);
|
|
7962
8243
|
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices(client, workspaceId, application.name, application.id, tailordbs);
|
|
7963
8244
|
const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
|
|
7964
|
-
const [typeChangeSet, gqlPermissionChangeSet] = await Promise.all([planTypes(client, workspaceId, tailordbs,
|
|
8245
|
+
const [typeChangeSet, gqlPermissionChangeSet] = await Promise.all([planTypes(client, workspaceId, tailordbs, executorUsedTypes, deletedServices, void 0, forceApplyAll), planGqlPermissions(client, workspaceId, tailordbs, deletedServices, forceApplyAll)]);
|
|
7965
8246
|
return {
|
|
7966
8247
|
changeSet: {
|
|
7967
8248
|
service: serviceChangeSet,
|
|
@@ -7974,6 +8255,8 @@ async function planTailorDB(context) {
|
|
|
7974
8255
|
context: {
|
|
7975
8256
|
workspaceId,
|
|
7976
8257
|
application,
|
|
8258
|
+
tailorDBInputs: tailordbs,
|
|
8259
|
+
executorUsedTypes,
|
|
7977
8260
|
config,
|
|
7978
8261
|
noSchemaCheck: noSchemaCheck ?? false
|
|
7979
8262
|
}
|
|
@@ -8116,7 +8399,7 @@ async function planServices(client, workspaceId, appName, appId, tailordbs) {
|
|
|
8116
8399
|
resourceOwners
|
|
8117
8400
|
};
|
|
8118
8401
|
}
|
|
8119
|
-
async function planTypes(client, workspaceId, tailordbs,
|
|
8402
|
+
async function planTypes(client, workspaceId, tailordbs, executorUsedTypes, deletedServices, filteredTypesByNamespace, forceApplyAll = false) {
|
|
8120
8403
|
const changeSet = createChangeSet("TailorDB types");
|
|
8121
8404
|
const fetchTypes = (namespaceName) => {
|
|
8122
8405
|
return fetchAll(async (pageToken, maxPageSize) => {
|
|
@@ -8134,8 +8417,6 @@ async function planTypes(client, workspaceId, tailordbs, executors, deletedServi
|
|
|
8134
8417
|
}
|
|
8135
8418
|
});
|
|
8136
8419
|
};
|
|
8137
|
-
const executorUsedTypes = /* @__PURE__ */ new Set();
|
|
8138
|
-
for (const executor of executors) if (executor.trigger.kind === "tailordb") executorUsedTypes.add(executor.trigger.typeName);
|
|
8139
8420
|
for (const tailordb of tailordbs) {
|
|
8140
8421
|
const types = filteredTypesByNamespace?.get(tailordb.namespace) ?? tailordb.types;
|
|
8141
8422
|
for (const typeName of Object.keys(types)) {
|
|
@@ -8266,8 +8547,8 @@ function isNumericLikeValue(value) {
|
|
|
8266
8547
|
return typeof value === "number" || typeof value === "bigint" || /^-?\d+$/.test(value);
|
|
8267
8548
|
}
|
|
8268
8549
|
/**
|
|
8269
|
-
* Generate a TailorDB type manifest from
|
|
8270
|
-
* @param {
|
|
8550
|
+
* Generate a TailorDB type manifest from snapshot-shaped type
|
|
8551
|
+
* @param {TailorDBSnapshotType} type - Snapshot-shaped TailorDB type
|
|
8271
8552
|
* @param {ReadonlySet<string>} executorUsedTypes - Set of types used by executors
|
|
8272
8553
|
* @param {GqlOperations} [namespaceGqlOperations] - Default gqlOperations for the namespace (already normalized)
|
|
8273
8554
|
* @returns {MessageInitShape<typeof TailorDBTypeSchema>} Type manifest
|
|
@@ -8294,7 +8575,7 @@ function generateTailorDBTypeManifest(type, executorUsedTypes, namespaceGqlOpera
|
|
|
8294
8575
|
};
|
|
8295
8576
|
const fields = {};
|
|
8296
8577
|
Object.keys(type.fields).filter((fieldName) => fieldName !== "id").forEach((fieldName) => {
|
|
8297
|
-
const fieldConfig = type.fields[fieldName]
|
|
8578
|
+
const fieldConfig = type.fields[fieldName];
|
|
8298
8579
|
const fieldType = fieldConfig.type;
|
|
8299
8580
|
const fieldEntry = {
|
|
8300
8581
|
type: fieldType,
|
|
@@ -8307,7 +8588,7 @@ function generateTailorDBTypeManifest(type, executorUsedTypes, namespaceGqlOpera
|
|
|
8307
8588
|
foreignKey: fieldConfig.foreignKey || false,
|
|
8308
8589
|
foreignKeyType: fieldConfig.foreignKeyType,
|
|
8309
8590
|
foreignKeyField: fieldConfig.foreignKeyField,
|
|
8310
|
-
required: fieldConfig.required
|
|
8591
|
+
required: fieldConfig.required,
|
|
8311
8592
|
vector: fieldConfig.vector || false,
|
|
8312
8593
|
...toProtoFieldHooks(fieldConfig),
|
|
8313
8594
|
...fieldConfig.serial && { serial: {
|
|
@@ -8321,14 +8602,14 @@ function generateTailorDBTypeManifest(type, executorUsedTypes, namespaceGqlOpera
|
|
|
8321
8602
|
fields[fieldName] = fieldEntry;
|
|
8322
8603
|
});
|
|
8323
8604
|
const relationships = {};
|
|
8324
|
-
for (const [relationName, rel] of Object.entries(type.forwardRelationships)) relationships[relationName] = {
|
|
8605
|
+
for (const [relationName, rel] of Object.entries(type.forwardRelationships ?? {})) relationships[relationName] = {
|
|
8325
8606
|
refType: rel.targetType,
|
|
8326
8607
|
refField: rel.sourceField,
|
|
8327
8608
|
srcField: rel.targetField,
|
|
8328
8609
|
array: rel.isArray,
|
|
8329
8610
|
description: rel.description
|
|
8330
8611
|
};
|
|
8331
|
-
for (const [relationName, rel] of Object.entries(type.backwardRelationships)) relationships[relationName] = {
|
|
8612
|
+
for (const [relationName, rel] of Object.entries(type.backwardRelationships ?? {})) relationships[relationName] = {
|
|
8332
8613
|
refType: rel.targetType,
|
|
8333
8614
|
refField: rel.targetField,
|
|
8334
8615
|
srcField: rel.sourceField,
|
|
@@ -8346,7 +8627,7 @@ function generateTailorDBTypeManifest(type, executorUsedTypes, namespaceGqlOpera
|
|
|
8346
8627
|
if (type.files) Object.entries(type.files).forEach(([key, description]) => {
|
|
8347
8628
|
files[key] = { description: description || "" };
|
|
8348
8629
|
});
|
|
8349
|
-
const permission = type.permissions
|
|
8630
|
+
const permission = type.permissions?.record ? protoPermission(type.permissions.record) : {
|
|
8350
8631
|
create: [],
|
|
8351
8632
|
read: [],
|
|
8352
8633
|
update: [],
|
|
@@ -8392,7 +8673,7 @@ function processNestedFields(fields) {
|
|
|
8392
8673
|
allowedValues: nestedFieldConfig.allowedValues || [],
|
|
8393
8674
|
description: nestedFieldConfig.description || "",
|
|
8394
8675
|
validate: toProtoFieldValidate(nestedFieldConfig),
|
|
8395
|
-
required: nestedFieldConfig.required
|
|
8676
|
+
required: nestedFieldConfig.required,
|
|
8396
8677
|
array: nestedFieldConfig.array ?? false,
|
|
8397
8678
|
index: false,
|
|
8398
8679
|
unique: false,
|
|
@@ -8407,7 +8688,7 @@ function processNestedFields(fields) {
|
|
|
8407
8688
|
allowedValues: nestedType === "enum" ? nestedFieldConfig.allowedValues || [] : [],
|
|
8408
8689
|
description: nestedFieldConfig.description || "",
|
|
8409
8690
|
validate: toProtoFieldValidate(nestedFieldConfig),
|
|
8410
|
-
required: nestedFieldConfig.required
|
|
8691
|
+
required: nestedFieldConfig.required,
|
|
8411
8692
|
array: nestedFieldConfig.array ?? false,
|
|
8412
8693
|
index: false,
|
|
8413
8694
|
unique: false,
|
|
@@ -8425,9 +8706,12 @@ function processNestedFields(fields) {
|
|
|
8425
8706
|
return nestedFields;
|
|
8426
8707
|
}
|
|
8427
8708
|
function protoPermission(permission) {
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8709
|
+
return {
|
|
8710
|
+
create: permission.create.map((policy) => protoPolicy(policy)),
|
|
8711
|
+
read: permission.read.map((policy) => protoPolicy(policy)),
|
|
8712
|
+
update: permission.update.map((policy) => protoPolicy(policy)),
|
|
8713
|
+
delete: permission.delete.map((policy) => protoPolicy(policy))
|
|
8714
|
+
};
|
|
8431
8715
|
}
|
|
8432
8716
|
function protoPolicy(policy) {
|
|
8433
8717
|
let permit;
|
|
@@ -8479,23 +8763,25 @@ function protoCondition(condition) {
|
|
|
8479
8763
|
};
|
|
8480
8764
|
}
|
|
8481
8765
|
function protoOperand(operand) {
|
|
8482
|
-
if (
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8766
|
+
if (isSnapshotFieldRefOperand(operand)) {
|
|
8767
|
+
if ("user" in operand) return { kind: {
|
|
8768
|
+
case: "userField",
|
|
8769
|
+
value: operand.user
|
|
8770
|
+
} };
|
|
8771
|
+
if ("record" in operand) return { kind: {
|
|
8772
|
+
case: "recordField",
|
|
8773
|
+
value: operand.record
|
|
8774
|
+
} };
|
|
8775
|
+
if ("newRecord" in operand) return { kind: {
|
|
8776
|
+
case: "newRecordField",
|
|
8777
|
+
value: operand.newRecord
|
|
8778
|
+
} };
|
|
8779
|
+
if ("oldRecord" in operand) return { kind: {
|
|
8780
|
+
case: "oldRecordField",
|
|
8781
|
+
value: operand.oldRecord
|
|
8782
|
+
} };
|
|
8783
|
+
throw new Error(`Unknown field-ref operand shape: ${JSON.stringify(operand)}`);
|
|
8784
|
+
}
|
|
8499
8785
|
return { kind: {
|
|
8500
8786
|
case: "value",
|
|
8501
8787
|
value: fromJson(ValueSchema, operand)
|
|
@@ -8527,7 +8813,7 @@ async function planGqlPermissions(client, workspaceId, tailordbs, deletedService
|
|
|
8527
8813
|
});
|
|
8528
8814
|
const types = tailordb.types;
|
|
8529
8815
|
for (const typeName of Object.keys(types)) {
|
|
8530
|
-
const gqlPermission = types[typeName].permissions
|
|
8816
|
+
const gqlPermission = types[typeName].permissions?.gql;
|
|
8531
8817
|
if (!gqlPermission) continue;
|
|
8532
8818
|
const desiredPermission = protoGqlPermission(gqlPermission);
|
|
8533
8819
|
const existingPermission = existingGqlPermissions.find((entry) => entry.typeName === typeName);
|
|
@@ -8661,11 +8947,12 @@ function protoGqlCondition(condition) {
|
|
|
8661
8947
|
};
|
|
8662
8948
|
}
|
|
8663
8949
|
function protoGqlOperand(operand) {
|
|
8664
|
-
if (
|
|
8950
|
+
if (isSnapshotFieldRefOperand(operand)) {
|
|
8665
8951
|
if ("user" in operand) return { kind: {
|
|
8666
8952
|
case: "userField",
|
|
8667
8953
|
value: operand.user
|
|
8668
8954
|
} };
|
|
8955
|
+
throw new Error(`Unsupported field-ref operand in GQL permission: ${JSON.stringify(operand)} — GQL permissions only support { user } field references`);
|
|
8669
8956
|
}
|
|
8670
8957
|
return { kind: {
|
|
8671
8958
|
case: "value",
|
|
@@ -8674,7 +8961,7 @@ function protoGqlOperand(operand) {
|
|
|
8674
8961
|
}
|
|
8675
8962
|
/**
|
|
8676
8963
|
* Check if there are schema differences between migration snapshots and local definitions
|
|
8677
|
-
* @param {ReadonlyMap<string, Record<string,
|
|
8964
|
+
* @param {ReadonlyMap<string, Record<string, TailorDBSnapshotType>>} typesByNamespace - Snapshot-shaped local types by namespace
|
|
8678
8965
|
* @param {NamespaceWithMigrations[]} namespacesWithMigrations - Namespaces with migrations config
|
|
8679
8966
|
* @returns {Promise<MigrationCheckResult[]>} Results for each namespace
|
|
8680
8967
|
*/
|
|
@@ -13324,7 +13611,7 @@ function generateEmptyDbTypes(namespace) {
|
|
|
13324
13611
|
}
|
|
13325
13612
|
/**
|
|
13326
13613
|
* Generate table type definition from a snapshot type
|
|
13327
|
-
* @param {
|
|
13614
|
+
* @param {TailorDBSnapshotType} type - Snapshot type
|
|
13328
13615
|
* @param {BreakingChangeFieldInfo} breakingChangeFields - Breaking change field info
|
|
13329
13616
|
* @returns {{ typeDef: string; usedTimestamp: boolean; usedColumnType: boolean }} Generated type and utility type usage
|
|
13330
13617
|
*/
|
|
@@ -13552,8 +13839,11 @@ function generateMigrationScript(diff) {
|
|
|
13552
13839
|
return `/**
|
|
13553
13840
|
* Migration script for ${diff.namespace}
|
|
13554
13841
|
*
|
|
13555
|
-
* This script
|
|
13556
|
-
*
|
|
13842
|
+
* This script runs between the Pre-migration and Post-migration phases of
|
|
13843
|
+
* 'tailor-sdk deploy'. Use it to transform existing data so that the schema
|
|
13844
|
+
* change can complete safely (for breaking changes, this is hard-required;
|
|
13845
|
+
* for warning-tier changes it is optional). Edit this file to implement
|
|
13846
|
+
* your data migration logic.
|
|
13557
13847
|
*
|
|
13558
13848
|
* The transaction is managed by the deploy command.
|
|
13559
13849
|
* If any operation fails, all changes will be rolled back.
|
|
@@ -13803,6 +14093,10 @@ async function generateDiffFromSnapshot(previousSnapshot, currentSnapshot, migra
|
|
|
13803
14093
|
logger.newline();
|
|
13804
14094
|
}
|
|
13805
14095
|
}
|
|
14096
|
+
if (diff.hasWarnings) {
|
|
14097
|
+
logger.newline();
|
|
14098
|
+
logger.warn(formatWarnings(diff.warnings));
|
|
14099
|
+
}
|
|
13806
14100
|
const result = await generateDiffFiles(diff, migrationsDir, getNextMigrationNumber(migrationsDir), previousSnapshot, options.name);
|
|
13807
14101
|
logger.success(`Generated migration ${styles.bold(result.migrationNumber.toString().padStart(4, "0"))}`);
|
|
13808
14102
|
logger.info(` Diff file: ${result.diffFilePath}`);
|
|
@@ -13826,6 +14120,10 @@ async function generateDiffFromSnapshot(previousSnapshot, currentSnapshot, migra
|
|
|
13826
14120
|
} catch {
|
|
13827
14121
|
return;
|
|
13828
14122
|
}
|
|
14123
|
+
} else if (diff.hasWarnings) {
|
|
14124
|
+
logger.newline();
|
|
14125
|
+
logger.log(`Data loss is possible for this migration but no script was generated. To add a custom migrate.ts, run:`);
|
|
14126
|
+
logger.log(` ${styles.bold(`tailor-sdk tailordb migration script ${result.migrationNumber.toString().padStart(4, "0")} --namespace ${diff.namespace}`)}`);
|
|
13829
14127
|
}
|
|
13830
14128
|
}
|
|
13831
14129
|
/**
|
|
@@ -15872,5 +16170,5 @@ function isDeno() {
|
|
|
15872
16170
|
}
|
|
15873
16171
|
|
|
15874
16172
|
//#endregion
|
|
15875
|
-
export {
|
|
15876
|
-
//# sourceMappingURL=runtime-
|
|
16173
|
+
export { listCommand$5 as $, compareSnapshots as $t, truncate as A, workspaceArgs as An, startCommand as At, logBetaWarning as B, getExecutor as Bt, listCommand$2 as C, configArg as Cn, triggerExecutor as Ct, resumeWorkflow as D, pagedLogArgs as Dn, jobsCommand as Dt, resumeCommand as E, isVerbose as En, getExecutorJob as Et, writeDbTypesFile as F, getWorkflowExecution as Ft, organizationTree as G, parseMigrationLabelNumber as Gt, removeCommand$1 as H, executeScript as Ht, getConfiguredEditorCommand as I, listWorkflowExecutions as It, listOrganizations as J, DIFF_FILE_NAME as Jt, treeCommand as K, bundleMigrationScript as Kt, openInConfiguredEditor as L, functionExecutionStatusToString as Lt, generate as M, getCommand$5 as Mt, generateCommand as N, getWorkflow as Nt, listCommand$3 as O, paginationArgs as On, listExecutorJobs as Ot, generateMigrationScript as P, executionsCommand as Pt, updateFolder as Q, compareLocalTypesWithSnapshot as Qt, show as R, formatKeyValueTable as Rt, listApps as S, commonArgs as Sn, triggerCommand as St, healthCommand as T, deploymentArgs as Tn, listExecutors as Tt, updateCommand$1 as U, waitForExecution$1 as Ut, remove as V, deploy as Vt, updateOrganization as W, MIGRATION_LABEL_KEY as Wt, getOrganization as X, MIGRATE_FILE_NAME as Xt, getCommand$1 as Y, INITIAL_SCHEMA_NUMBER as Yt, updateCommand$2 as Z, SCHEMA_FILE_NAME as Zt, getWorkspace as _, prompt as _n, listFunctionRegistries as _t, updateUser as a, getMigrationFiles as an, createCommand$1 as at, createCommand as b, assertWritable as bn, listWebhookExecutors as bt, listCommand as c, loadDiff as cn, listOAuth2Clients as ct, inviteUser as d, formatMigrationDiff as dn, getMachineUserToken as dt, createSnapshotFromLocalTypes as en, listFolders as et, restoreCommand as f, hasChanges as fn, tokenCommand as ft, getCommand as g, generateUserTypes as gn, listCommand$8 as gt, listWorkspaces as h, trnPrefix as hn, generate$1 as ht, updateCommand as i, getMigrationFilePath as in, deleteFolder as it, truncateCommand as j, startWorkflow as jt, listWorkflows as k, toPageDirection as kn, watchExecutorJob as kt, listUsers as l, reconstructSnapshotFromMigrations as ln, getCommand$3 as lt, listCommand$1 as m, sdkNameLabelKey as mn, listMachineUsers as mt, query as n, getLatestMigrationNumber as nn, getFolder as nt, removeCommand as o, getNextMigrationNumber as on, createFolder as ot, restoreWorkspace as p, getNamespacesWithMigrations as pn, listCommand$7 as pt, listCommand$4 as q, DB_TYPES_FILE_NAME as qt, queryCommand as r, getMigrationDirPath as rn, deleteCommand$1 as rt, removeUser as s, isValidMigrationNumber as sn, listCommand$6 as st, isNativeTypeScriptRuntime as t, formatMigrationNumber as tn, getCommand$2 as tt, inviteCommand as u, formatDiffSummary as un, getOAuth2Client as ut, deleteCommand as v, apiCommand as vn, getCommand$4 as vt, getAppHealth as w, confirmationArgs as wn, listCommand$9 as wt, createWorkspace as x, defineAppCommand as xn, webhookCommand as xt, deleteWorkspace as y, apiCall as yn, getFunctionRegistry as yt, showCommand as z, getCommand$6 as zt };
|
|
16174
|
+
//# sourceMappingURL=runtime-B2K6JW7V.mjs.map
|