instant-cli 0.22.96-experimental.drewh-ts-target.20761590091.1 → 0.22.96-experimental.surgical.20765817844.1
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/.turbo/turbo-build.log +1 -1
- package/__tests__/__snapshots__/updateSchemaFile.test.ts.snap +248 -0
- package/__tests__/updateSchemaFile.test.ts +557 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1152 -1044
- package/dist/index.js.map +1 -1
- package/dist/rename.js +69 -58
- package/dist/rename.js.map +1 -1
- package/dist/renderSchemaPlan.js +22 -10
- package/dist/renderSchemaPlan.js.map +1 -1
- package/dist/ui/index.js +102 -115
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/lib.js +30 -29
- package/dist/ui/lib.js.map +1 -1
- package/dist/util/fs.js +30 -17
- package/dist/util/fs.js.map +1 -1
- package/dist/util/isHeadlessEnvironment.js +1 -1
- package/dist/util/isHeadlessEnvironment.js.map +1 -1
- package/dist/util/loadConfig.js +32 -32
- package/dist/util/loadConfig.js.map +1 -1
- package/dist/util/packageManager.js +37 -26
- package/dist/util/packageManager.js.map +1 -1
- package/dist/util/projectDir.js +27 -16
- package/dist/util/projectDir.js.map +1 -1
- package/dist/util/promptOk.js +21 -14
- package/dist/util/promptOk.js.map +1 -1
- package/dist/util/renamePrompt.js +2 -4
- package/dist/util/renamePrompt.js.map +1 -1
- package/dist/util/updateSchemaFile.d.ts +3 -0
- package/dist/util/updateSchemaFile.d.ts.map +1 -0
- package/dist/util/updateSchemaFile.js +610 -0
- package/dist/util/updateSchemaFile.js.map +1 -0
- package/package.json +4 -4
- package/src/index.js +19 -10
- package/src/util/updateSchemaFile.ts +760 -0
- package/__tests__/mergeSchema.test.ts +0 -197
- package/dist/util/mergeSchema.d.ts +0 -2
- package/dist/util/mergeSchema.d.ts.map +0 -1
- package/dist/util/mergeSchema.js +0 -334
- package/dist/util/mergeSchema.js.map +0 -1
- package/src/util/mergeSchema.js +0 -364
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import * as acorn from 'acorn';
|
|
11
|
+
import { tsPlugin } from 'acorn-typescript';
|
|
12
|
+
import { diffSchemas, renderAttrCall, renderAttrProperty, renderEntityProperty, renderLinkProperty, renderLinkValue, } from '@instantdb/platform';
|
|
13
|
+
const parser = acorn.Parser.extend(tsPlugin({ dts: false }));
|
|
14
|
+
const DEFAULT_INDENT = ' ';
|
|
15
|
+
export function updateSchemaFile(existingFileContent, localSchema, serverSchema) {
|
|
16
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
const ast = parseFile(existingFileContent);
|
|
18
|
+
const schemaObj = findSchemaObject(ast);
|
|
19
|
+
if (!schemaObj) {
|
|
20
|
+
throw new Error('Could not find i.schema(...) in schema file.');
|
|
21
|
+
}
|
|
22
|
+
const { entitiesObj, linksObj } = getSchemaSections(schemaObj);
|
|
23
|
+
const diff = yield diffSchemas(localSchema, serverSchema, (created) => __awaiter(this, void 0, void 0, function* () { return created; }), {});
|
|
24
|
+
if (diff.length === 0) {
|
|
25
|
+
return existingFileContent;
|
|
26
|
+
}
|
|
27
|
+
const { entitiesByName } = buildEntitiesIndex(entitiesObj);
|
|
28
|
+
const { localLinksByForward, serverLinksByForward } = buildLinkMaps(localSchema.links || {}, serverSchema.links || {});
|
|
29
|
+
const changeBuckets = collectChanges(diff, localLinksByForward, serverLinksByForward);
|
|
30
|
+
const edits = [];
|
|
31
|
+
edits.push(...collectEntityEdits(existingFileContent, entitiesObj, entitiesByName, changeBuckets, serverSchema));
|
|
32
|
+
edits.push(...collectLinkEdits(existingFileContent, linksObj, changeBuckets, localLinksByForward, serverLinksByForward));
|
|
33
|
+
const updated = applyEdits(existingFileContent, edits);
|
|
34
|
+
return normalizeEmptyLinksObject(updated);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function parseFile(content) {
|
|
38
|
+
return parser.parse(content, {
|
|
39
|
+
sourceType: 'module',
|
|
40
|
+
ecmaVersion: 'latest',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function getSchemaSections(schemaObj) {
|
|
44
|
+
const entitiesProp = findObjectProperty(schemaObj, 'entities');
|
|
45
|
+
if (!entitiesProp || !isObjectExpression(entitiesProp.value)) {
|
|
46
|
+
throw new Error('Could not find entities object in schema file.');
|
|
47
|
+
}
|
|
48
|
+
const linksProp = findObjectProperty(schemaObj, 'links');
|
|
49
|
+
if (!linksProp || !isObjectExpression(linksProp.value)) {
|
|
50
|
+
throw new Error('Could not find links object in schema file.');
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
entitiesObj: entitiesProp.value,
|
|
54
|
+
linksObj: linksProp.value,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function buildEntitiesIndex(entitiesObj) {
|
|
58
|
+
const entitiesByName = new Map();
|
|
59
|
+
for (const prop of entitiesObj.properties) {
|
|
60
|
+
if (!isProperty(prop))
|
|
61
|
+
continue;
|
|
62
|
+
const name = getPropName(prop);
|
|
63
|
+
if (!name)
|
|
64
|
+
continue;
|
|
65
|
+
const attrsObj = getEntityAttrsObject(prop.value);
|
|
66
|
+
if (!attrsObj)
|
|
67
|
+
continue;
|
|
68
|
+
const attrsByName = new Map();
|
|
69
|
+
for (const attrProp of attrsObj.properties) {
|
|
70
|
+
if (!isProperty(attrProp))
|
|
71
|
+
continue;
|
|
72
|
+
const attrName = getPropName(attrProp);
|
|
73
|
+
if (!attrName)
|
|
74
|
+
continue;
|
|
75
|
+
attrsByName.set(attrName, attrProp);
|
|
76
|
+
}
|
|
77
|
+
entitiesByName.set(name, { prop, attrsObj, attrsByName });
|
|
78
|
+
}
|
|
79
|
+
return { entitiesByName };
|
|
80
|
+
}
|
|
81
|
+
function buildLinkMaps(localLinks, serverLinks) {
|
|
82
|
+
return {
|
|
83
|
+
localLinksByForward: buildLinkForwardMap(localLinks),
|
|
84
|
+
serverLinksByForward: buildLinkForwardMap(serverLinks),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function collectEntityEdits(content, entitiesObj, entitiesByName, changeBuckets, serverSchema) {
|
|
88
|
+
var _a, _b, _c, _d, _e;
|
|
89
|
+
const edits = [];
|
|
90
|
+
for (const entityName of changeBuckets.deleteEntities) {
|
|
91
|
+
const entity = entitiesByName.get(entityName);
|
|
92
|
+
if (!entity)
|
|
93
|
+
continue;
|
|
94
|
+
edits.push(removeProperty(content, entitiesObj, entity.prop));
|
|
95
|
+
}
|
|
96
|
+
for (const entityName of changeBuckets.createEntities) {
|
|
97
|
+
if (entitiesByName.has(entityName))
|
|
98
|
+
continue;
|
|
99
|
+
const entityDef = (_a = serverSchema.entities) === null || _a === void 0 ? void 0 : _a[entityName];
|
|
100
|
+
if (!entityDef)
|
|
101
|
+
continue;
|
|
102
|
+
const propText = renderEntityProperty(entityName, entityDef.attrs);
|
|
103
|
+
const indent = getObjectPropIndent(content, entitiesObj);
|
|
104
|
+
edits.push(insertProperty(content, entitiesObj, propText, indent));
|
|
105
|
+
}
|
|
106
|
+
for (const [entityName, attrs] of changeBuckets.deleteAttrs) {
|
|
107
|
+
const entity = entitiesByName.get(entityName);
|
|
108
|
+
if (!entity)
|
|
109
|
+
continue;
|
|
110
|
+
for (const attrName of attrs) {
|
|
111
|
+
const attrProp = entity.attrsByName.get(attrName);
|
|
112
|
+
if (!attrProp)
|
|
113
|
+
continue;
|
|
114
|
+
edits.push(removeProperty(content, entity.attrsObj, attrProp));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
for (const [entityName, attrs] of changeBuckets.addAttrs) {
|
|
118
|
+
const entity = entitiesByName.get(entityName);
|
|
119
|
+
if (!entity)
|
|
120
|
+
continue;
|
|
121
|
+
const entityDef = (_b = serverSchema.entities) === null || _b === void 0 ? void 0 : _b[entityName];
|
|
122
|
+
if (!entityDef)
|
|
123
|
+
continue;
|
|
124
|
+
const indent = getObjectPropIndent(content, entity.attrsObj);
|
|
125
|
+
for (const attrName of attrs) {
|
|
126
|
+
const attrDef = (_c = entityDef.attrs) === null || _c === void 0 ? void 0 : _c[attrName];
|
|
127
|
+
if (!attrDef)
|
|
128
|
+
continue;
|
|
129
|
+
const propText = renderAttrProperty(attrName, attrDef);
|
|
130
|
+
edits.push(insertPropertyExpandingSingleLine(content, entity.attrsObj, propText, indent));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
for (const [entityName, attrs] of changeBuckets.updateAttrs) {
|
|
134
|
+
const entity = entitiesByName.get(entityName);
|
|
135
|
+
if (!entity)
|
|
136
|
+
continue;
|
|
137
|
+
const entityDef = (_d = serverSchema.entities) === null || _d === void 0 ? void 0 : _d[entityName];
|
|
138
|
+
if (!entityDef)
|
|
139
|
+
continue;
|
|
140
|
+
for (const attrName of attrs) {
|
|
141
|
+
const attrProp = entity.attrsByName.get(attrName);
|
|
142
|
+
const attrDef = (_e = entityDef.attrs) === null || _e === void 0 ? void 0 : _e[attrName];
|
|
143
|
+
if (!attrProp || !attrDef)
|
|
144
|
+
continue;
|
|
145
|
+
edits.push(updateAttrEdit(content, attrProp, attrDef));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return edits;
|
|
149
|
+
}
|
|
150
|
+
function collectLinkEdits(content, linksObj, changeBuckets, localLinksByForward, serverLinksByForward) {
|
|
151
|
+
const edits = [];
|
|
152
|
+
for (const forwardKey of changeBuckets.deleteLinks) {
|
|
153
|
+
const localLink = localLinksByForward.get(forwardKey);
|
|
154
|
+
if (!localLink)
|
|
155
|
+
continue;
|
|
156
|
+
const linkProp = findObjectProperty(linksObj, localLink.name);
|
|
157
|
+
if (!linkProp)
|
|
158
|
+
continue;
|
|
159
|
+
edits.push(removeProperty(content, linksObj, linkProp));
|
|
160
|
+
}
|
|
161
|
+
for (const forwardKey of changeBuckets.addLinks) {
|
|
162
|
+
const serverLink = serverLinksByForward.get(forwardKey);
|
|
163
|
+
if (!serverLink)
|
|
164
|
+
continue;
|
|
165
|
+
const linkName = serverLink.name;
|
|
166
|
+
if (findObjectProperty(linksObj, linkName))
|
|
167
|
+
continue;
|
|
168
|
+
const propText = renderLinkProperty(linkName, serverLink.link);
|
|
169
|
+
const indent = getObjectPropIndent(content, linksObj);
|
|
170
|
+
edits.push(insertProperty(content, linksObj, propText, indent));
|
|
171
|
+
}
|
|
172
|
+
for (const forwardKey of changeBuckets.updateLinks) {
|
|
173
|
+
const serverLink = serverLinksByForward.get(forwardKey);
|
|
174
|
+
const localLink = localLinksByForward.get(forwardKey);
|
|
175
|
+
if (!serverLink || !localLink)
|
|
176
|
+
continue;
|
|
177
|
+
const linkProp = findObjectProperty(linksObj, localLink.name);
|
|
178
|
+
if (!linkProp)
|
|
179
|
+
continue;
|
|
180
|
+
const nextValue = renderLinkValue(serverLink.link);
|
|
181
|
+
const propIndent = getLineIndent(content, linkProp.start);
|
|
182
|
+
edits.push({
|
|
183
|
+
start: linkProp.value.start,
|
|
184
|
+
end: linkProp.value.end,
|
|
185
|
+
text: indentValueAfterFirstLine(nextValue, propIndent),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return edits;
|
|
189
|
+
}
|
|
190
|
+
function updateAttrEdit(content, attrProp, attrDef) {
|
|
191
|
+
const { typeParams } = analyzeChain(attrProp.value);
|
|
192
|
+
const typeParamsText = typeParams
|
|
193
|
+
? content.slice(typeParams.start, typeParams.end)
|
|
194
|
+
: null;
|
|
195
|
+
const nextValue = renderAttrCall(attrDef, typeParamsText);
|
|
196
|
+
return {
|
|
197
|
+
start: attrProp.value.start,
|
|
198
|
+
end: attrProp.value.end,
|
|
199
|
+
text: nextValue,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function applyEdits(content, edits) {
|
|
203
|
+
if (edits.length === 0) {
|
|
204
|
+
return content;
|
|
205
|
+
}
|
|
206
|
+
const sorted = [...edits].sort((a, b) => b.start - a.start);
|
|
207
|
+
let output = content;
|
|
208
|
+
for (const edit of sorted) {
|
|
209
|
+
output = output.slice(0, edit.start) + edit.text + output.slice(edit.end);
|
|
210
|
+
}
|
|
211
|
+
return output;
|
|
212
|
+
}
|
|
213
|
+
function collectChanges(steps, localLinksByForward, serverLinksByForward) {
|
|
214
|
+
var _a;
|
|
215
|
+
const buckets = {
|
|
216
|
+
createEntities: new Set(),
|
|
217
|
+
deleteEntities: new Set(),
|
|
218
|
+
addAttrs: new Map(),
|
|
219
|
+
deleteAttrs: new Map(),
|
|
220
|
+
updateAttrs: new Map(),
|
|
221
|
+
addLinks: new Set(),
|
|
222
|
+
deleteLinks: new Set(),
|
|
223
|
+
updateLinks: new Set(),
|
|
224
|
+
};
|
|
225
|
+
for (const step of steps) {
|
|
226
|
+
const namespace = step.identifier.namespace;
|
|
227
|
+
const attrName = step.identifier.attrName;
|
|
228
|
+
const forwardKey = `${namespace}.${attrName}`;
|
|
229
|
+
switch (step.type) {
|
|
230
|
+
case 'add-attr': {
|
|
231
|
+
if (attrName === 'id') {
|
|
232
|
+
buckets.createEntities.add(namespace);
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
if (step['value-type'] === 'ref') {
|
|
236
|
+
buckets.addLinks.add(forwardKey);
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
ensureSet(buckets.addAttrs, namespace).add(attrName);
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
case 'delete-attr': {
|
|
243
|
+
if (attrName === 'id') {
|
|
244
|
+
buckets.deleteEntities.add(namespace);
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
if (localLinksByForward.has(forwardKey)) {
|
|
248
|
+
buckets.deleteLinks.add(forwardKey);
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
ensureSet(buckets.deleteAttrs, namespace).add(attrName);
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
case 'update-attr': {
|
|
255
|
+
if (((_a = step.partialAttr) === null || _a === void 0 ? void 0 : _a['value-type']) === 'ref') {
|
|
256
|
+
buckets.updateLinks.add(forwardKey);
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
ensureSet(buckets.updateAttrs, namespace).add(attrName);
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
case 'index':
|
|
263
|
+
case 'remove-index':
|
|
264
|
+
case 'unique':
|
|
265
|
+
case 'remove-unique':
|
|
266
|
+
case 'required':
|
|
267
|
+
case 'remove-required':
|
|
268
|
+
case 'check-data-type':
|
|
269
|
+
case 'remove-data-type': {
|
|
270
|
+
if (serverLinksByForward.has(forwardKey)) {
|
|
271
|
+
buckets.updateLinks.add(forwardKey);
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
ensureSet(buckets.updateAttrs, namespace).add(attrName);
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
default: {
|
|
278
|
+
assertNever(step);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
pruneNamespaceBuckets(buckets);
|
|
283
|
+
return buckets;
|
|
284
|
+
}
|
|
285
|
+
function ensureSet(map, key) {
|
|
286
|
+
if (!map.has(key))
|
|
287
|
+
map.set(key, new Set());
|
|
288
|
+
return map.get(key);
|
|
289
|
+
}
|
|
290
|
+
function pruneNamespaceBuckets(buckets) {
|
|
291
|
+
const namespaces = new Set([
|
|
292
|
+
...buckets.createEntities,
|
|
293
|
+
...buckets.deleteEntities,
|
|
294
|
+
]);
|
|
295
|
+
for (const namespace of namespaces) {
|
|
296
|
+
buckets.addAttrs.delete(namespace);
|
|
297
|
+
buckets.deleteAttrs.delete(namespace);
|
|
298
|
+
buckets.updateAttrs.delete(namespace);
|
|
299
|
+
removeNamespaceLinks(buckets.addLinks, namespace);
|
|
300
|
+
removeNamespaceLinks(buckets.deleteLinks, namespace);
|
|
301
|
+
removeNamespaceLinks(buckets.updateLinks, namespace);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function removeNamespaceLinks(set, namespace) {
|
|
305
|
+
const prefix = `${namespace}.`;
|
|
306
|
+
for (const key of Array.from(set)) {
|
|
307
|
+
if (key.startsWith(prefix)) {
|
|
308
|
+
set.delete(key);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function assertNever(value) {
|
|
313
|
+
throw new Error(`Unhandled migration step: ${JSON.stringify(value)}`);
|
|
314
|
+
}
|
|
315
|
+
function analyzeChain(node) {
|
|
316
|
+
var _a;
|
|
317
|
+
let curr = node;
|
|
318
|
+
let typeParams = null;
|
|
319
|
+
while ((curr === null || curr === void 0 ? void 0 : curr.type) === 'CallExpression') {
|
|
320
|
+
if (curr.typeParameters) {
|
|
321
|
+
typeParams = curr.typeParameters;
|
|
322
|
+
}
|
|
323
|
+
if (((_a = curr.callee) === null || _a === void 0 ? void 0 : _a.type) === 'MemberExpression') {
|
|
324
|
+
curr = curr.callee.object;
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return { typeParams };
|
|
331
|
+
}
|
|
332
|
+
function findSchemaObject(ast) {
|
|
333
|
+
let schemaObj = null;
|
|
334
|
+
const walk = (node) => {
|
|
335
|
+
var _a, _b, _c, _d;
|
|
336
|
+
if (!node || schemaObj)
|
|
337
|
+
return;
|
|
338
|
+
if (node.type === 'CallExpression' &&
|
|
339
|
+
((_a = node.callee) === null || _a === void 0 ? void 0 : _a.type) === 'MemberExpression' &&
|
|
340
|
+
((_b = node.callee.object) === null || _b === void 0 ? void 0 : _b.type) === 'Identifier' &&
|
|
341
|
+
node.callee.object.name === 'i' &&
|
|
342
|
+
((_c = node.callee.property) === null || _c === void 0 ? void 0 : _c.name) === 'schema' &&
|
|
343
|
+
((_d = node.arguments) === null || _d === void 0 ? void 0 : _d.length) > 0) {
|
|
344
|
+
const arg = node.arguments[0];
|
|
345
|
+
if (isObjectExpression(arg)) {
|
|
346
|
+
schemaObj = arg;
|
|
347
|
+
}
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
for (const key in node) {
|
|
351
|
+
if (key === 'loc' || key === 'start' || key === 'end')
|
|
352
|
+
continue;
|
|
353
|
+
const value = node[key];
|
|
354
|
+
if (!value || typeof value !== 'object')
|
|
355
|
+
continue;
|
|
356
|
+
if (Array.isArray(value)) {
|
|
357
|
+
value.forEach(walk);
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
walk(value);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
walk(ast);
|
|
365
|
+
return schemaObj;
|
|
366
|
+
}
|
|
367
|
+
function findObjectProperty(obj, name) {
|
|
368
|
+
for (const prop of obj.properties) {
|
|
369
|
+
if (!isProperty(prop))
|
|
370
|
+
continue;
|
|
371
|
+
const propName = getPropName(prop);
|
|
372
|
+
if (propName === name)
|
|
373
|
+
return prop;
|
|
374
|
+
}
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
function getEntityAttrsObject(value) {
|
|
378
|
+
var _a, _b, _c, _d;
|
|
379
|
+
if ((value === null || value === void 0 ? void 0 : value.type) !== 'CallExpression' ||
|
|
380
|
+
((_a = value.callee) === null || _a === void 0 ? void 0 : _a.type) !== 'MemberExpression' ||
|
|
381
|
+
((_b = value.callee.object) === null || _b === void 0 ? void 0 : _b.type) !== 'Identifier' ||
|
|
382
|
+
value.callee.object.name !== 'i' ||
|
|
383
|
+
((_c = value.callee.property) === null || _c === void 0 ? void 0 : _c.name) !== 'entity') {
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
const attrsObj = (_d = value.arguments) === null || _d === void 0 ? void 0 : _d[0];
|
|
387
|
+
return isObjectExpression(attrsObj) ? attrsObj : null;
|
|
388
|
+
}
|
|
389
|
+
function buildLinkForwardMap(links) {
|
|
390
|
+
const map = new Map();
|
|
391
|
+
for (const [name, link] of Object.entries(links || {})) {
|
|
392
|
+
map.set(linkForwardKey(link), { name, link });
|
|
393
|
+
}
|
|
394
|
+
return map;
|
|
395
|
+
}
|
|
396
|
+
function linkForwardKey(link) {
|
|
397
|
+
return `${link.forward.on}.${link.forward.label}`;
|
|
398
|
+
}
|
|
399
|
+
function isObjectExpression(node) {
|
|
400
|
+
return (node === null || node === void 0 ? void 0 : node.type) === 'ObjectExpression';
|
|
401
|
+
}
|
|
402
|
+
function isProperty(node) {
|
|
403
|
+
return (node === null || node === void 0 ? void 0 : node.type) === 'Property';
|
|
404
|
+
}
|
|
405
|
+
function getPropName(prop) {
|
|
406
|
+
if (prop.key.type === 'Identifier')
|
|
407
|
+
return prop.key.name;
|
|
408
|
+
if (prop.key.type === 'Literal')
|
|
409
|
+
return String(prop.key.value);
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
412
|
+
function indentLines(text, indent) {
|
|
413
|
+
return text
|
|
414
|
+
.split('\n')
|
|
415
|
+
.map((line) => (line.length ? indent + line : line))
|
|
416
|
+
.join('\n');
|
|
417
|
+
}
|
|
418
|
+
function getObjectPropIndent(source, obj) {
|
|
419
|
+
const props = obj.properties.filter(isProperty);
|
|
420
|
+
if (props.length > 0) {
|
|
421
|
+
return getLineIndent(source, props[0].start);
|
|
422
|
+
}
|
|
423
|
+
const closingIndent = getLineIndent(source, obj.end - 1);
|
|
424
|
+
return closingIndent + DEFAULT_INDENT;
|
|
425
|
+
}
|
|
426
|
+
function getLineIndent(source, pos) {
|
|
427
|
+
const lineStart = source.lastIndexOf('\n', pos - 1) + 1;
|
|
428
|
+
const match = source.slice(lineStart, pos).match(/^[\t ]*/);
|
|
429
|
+
return match ? match[0] : '';
|
|
430
|
+
}
|
|
431
|
+
function insertProperty(source, obj, propText, indent) {
|
|
432
|
+
const props = obj.properties.filter(isProperty);
|
|
433
|
+
const closingBrace = obj.end - 1;
|
|
434
|
+
const propTextWithIndent = indentLines(propText, indent);
|
|
435
|
+
const propTextSingleLine = propText.trim();
|
|
436
|
+
const innerStart = obj.start + 1;
|
|
437
|
+
const innerEnd = closingBrace;
|
|
438
|
+
const innerContent = source.slice(innerStart, innerEnd);
|
|
439
|
+
const innerWhitespaceOnly = /^[\s]*$/.test(innerContent);
|
|
440
|
+
if (props.length === 0) {
|
|
441
|
+
const objSource = source.slice(obj.start, obj.end);
|
|
442
|
+
const multiline = objSource.includes('\n') || propText.includes('\n');
|
|
443
|
+
if (!multiline) {
|
|
444
|
+
return {
|
|
445
|
+
start: closingBrace,
|
|
446
|
+
end: closingBrace,
|
|
447
|
+
text: ` ${propTextSingleLine} `,
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
const closingIndent = getLineIndent(source, closingBrace);
|
|
451
|
+
if (innerWhitespaceOnly) {
|
|
452
|
+
return {
|
|
453
|
+
start: innerStart,
|
|
454
|
+
end: innerEnd,
|
|
455
|
+
text: `\n${propTextWithIndent},\n${closingIndent}`,
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
return {
|
|
459
|
+
start: closingBrace,
|
|
460
|
+
end: closingBrace,
|
|
461
|
+
text: `\n${propTextWithIndent},\n${closingIndent}`,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
const lastProp = props[props.length - 1];
|
|
465
|
+
const multiline = source.slice(lastProp.end, closingBrace).includes('\n') ||
|
|
466
|
+
propText.includes('\n');
|
|
467
|
+
const needsComma = !hasTrailingComma(source, lastProp.end, obj.end);
|
|
468
|
+
if (!multiline) {
|
|
469
|
+
let insertPos = closingBrace;
|
|
470
|
+
while (insertPos > lastProp.end && /\s/.test(source[insertPos - 1])) {
|
|
471
|
+
insertPos -= 1;
|
|
472
|
+
}
|
|
473
|
+
return {
|
|
474
|
+
start: insertPos,
|
|
475
|
+
end: insertPos,
|
|
476
|
+
text: `${needsComma ? ',' : ''} ${propTextSingleLine}`,
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
const lineStart = source.lastIndexOf('\n', closingBrace);
|
|
480
|
+
return {
|
|
481
|
+
start: lineStart,
|
|
482
|
+
end: lineStart,
|
|
483
|
+
text: `${needsComma ? ',' : ''}\n${propTextWithIndent},`,
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
function removeProperty(source, obj, prop) {
|
|
487
|
+
let start = prop.start;
|
|
488
|
+
let end = prop.end;
|
|
489
|
+
const lineStart = source.lastIndexOf('\n', start - 1) + 1;
|
|
490
|
+
let shouldTrimLineEnd = false;
|
|
491
|
+
if (/^[\t ]*$/.test(source.slice(lineStart, start))) {
|
|
492
|
+
start = lineStart;
|
|
493
|
+
shouldTrimLineEnd = true;
|
|
494
|
+
}
|
|
495
|
+
const after = skipWhitespaceAndComments(source, end, obj.end);
|
|
496
|
+
if (source[after] === ',') {
|
|
497
|
+
end = after + 1;
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
const before = skipWhitespaceAndCommentsBackward(source, start, obj.start);
|
|
501
|
+
if (source[before] === ',') {
|
|
502
|
+
start = before;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (shouldTrimLineEnd) {
|
|
506
|
+
const lineEnd = source.indexOf('\n', end);
|
|
507
|
+
if (lineEnd !== -1 && /^[\t ]*$/.test(source.slice(end, lineEnd))) {
|
|
508
|
+
end = lineEnd + 1;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return { start, end, text: '' };
|
|
512
|
+
}
|
|
513
|
+
function indentValueAfterFirstLine(value, indent) {
|
|
514
|
+
const lines = value.split('\n');
|
|
515
|
+
if (lines.length <= 1)
|
|
516
|
+
return value;
|
|
517
|
+
return [
|
|
518
|
+
lines[0],
|
|
519
|
+
...lines.slice(1).map((line) => (line ? indent + line : line)),
|
|
520
|
+
].join('\n');
|
|
521
|
+
}
|
|
522
|
+
function insertPropertyExpandingSingleLine(source, obj, propText, indent) {
|
|
523
|
+
const props = obj.properties.filter(isProperty);
|
|
524
|
+
if (!props.length) {
|
|
525
|
+
return insertProperty(source, obj, propText, indent);
|
|
526
|
+
}
|
|
527
|
+
const objSource = source.slice(obj.start, obj.end);
|
|
528
|
+
if (objSource.includes('\n') || propText.includes('\n')) {
|
|
529
|
+
return insertProperty(source, obj, propText, indent);
|
|
530
|
+
}
|
|
531
|
+
const closingBrace = obj.end - 1;
|
|
532
|
+
const closingIndent = getLineIndent(source, closingBrace);
|
|
533
|
+
const innerIndent = closingIndent + DEFAULT_INDENT;
|
|
534
|
+
const propTexts = props.map((prop) => source.slice(prop.start, prop.end).trim());
|
|
535
|
+
const lines = [...propTexts, propText.trim()].map((prop) => `${innerIndent}${prop},`);
|
|
536
|
+
const nextObject = `{\n${lines.join('\n')}\n${closingIndent}}`;
|
|
537
|
+
return { start: obj.start, end: obj.end, text: nextObject };
|
|
538
|
+
}
|
|
539
|
+
function normalizeEmptyLinksObject(content) {
|
|
540
|
+
let ast;
|
|
541
|
+
try {
|
|
542
|
+
ast = parseFile(content);
|
|
543
|
+
}
|
|
544
|
+
catch (_a) {
|
|
545
|
+
return content;
|
|
546
|
+
}
|
|
547
|
+
const schemaObj = findSchemaObject(ast);
|
|
548
|
+
if (!schemaObj)
|
|
549
|
+
return content;
|
|
550
|
+
const linksProp = findObjectProperty(schemaObj, 'links');
|
|
551
|
+
if (!linksProp || !isObjectExpression(linksProp.value))
|
|
552
|
+
return content;
|
|
553
|
+
if (linksProp.value.properties.some(isProperty))
|
|
554
|
+
return content;
|
|
555
|
+
const inner = content.slice(linksProp.value.start + 1, linksProp.value.end - 1);
|
|
556
|
+
if (!/^[\s]*$/.test(inner))
|
|
557
|
+
return content;
|
|
558
|
+
return (content.slice(0, linksProp.value.start) +
|
|
559
|
+
'{}' +
|
|
560
|
+
content.slice(linksProp.value.end));
|
|
561
|
+
}
|
|
562
|
+
function hasTrailingComma(source, afterPos, endPos) {
|
|
563
|
+
const next = skipWhitespaceAndComments(source, afterPos, endPos);
|
|
564
|
+
return source[next] === ',';
|
|
565
|
+
}
|
|
566
|
+
function skipWhitespaceAndComments(source, start, end) {
|
|
567
|
+
let i = start;
|
|
568
|
+
while (i < end) {
|
|
569
|
+
const ch = source[i];
|
|
570
|
+
if (/\s/.test(ch)) {
|
|
571
|
+
i += 1;
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
if (ch === '/' && source[i + 1] === '/') {
|
|
575
|
+
const nextLine = source.indexOf('\n', i + 2);
|
|
576
|
+
i = nextLine === -1 ? end : nextLine + 1;
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
if (ch === '/' && source[i + 1] === '*') {
|
|
580
|
+
const close = source.indexOf('*/', i + 2);
|
|
581
|
+
i = close === -1 ? end : close + 2;
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
return i;
|
|
587
|
+
}
|
|
588
|
+
function skipWhitespaceAndCommentsBackward(source, start, end) {
|
|
589
|
+
let i = start - 1;
|
|
590
|
+
while (i >= end) {
|
|
591
|
+
const ch = source[i];
|
|
592
|
+
if (/\s/.test(ch)) {
|
|
593
|
+
i -= 1;
|
|
594
|
+
continue;
|
|
595
|
+
}
|
|
596
|
+
if (ch === '/' && source[i - 1] === '/') {
|
|
597
|
+
const prevLine = source.lastIndexOf('\n', i - 2);
|
|
598
|
+
i = prevLine === -1 ? end - 1 : prevLine - 1;
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
if (ch === '/' && source[i - 1] === '*') {
|
|
602
|
+
const open = source.lastIndexOf('/*', i - 2);
|
|
603
|
+
i = open === -1 ? end - 1 : open - 1;
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
return i;
|
|
609
|
+
}
|
|
610
|
+
//# sourceMappingURL=updateSchemaFile.js.map
|