@valbuild/server 0.60.3 → 0.60.4
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.
@@ -37,7 +37,7 @@ function _interopNamespace(e) {
|
|
37
37
|
return Object.freeze(n);
|
38
38
|
}
|
39
39
|
|
40
|
-
var
|
40
|
+
var ts__default = /*#__PURE__*/_interopDefault(ts);
|
41
41
|
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
42
42
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
43
43
|
var z__default = /*#__PURE__*/_interopDefault(z);
|
@@ -73,12 +73,12 @@ function formatSyntaxErrorTree(tree, sourceFile) {
|
|
73
73
|
return flatMapErrors(tree, error => formatSyntaxError(error, sourceFile));
|
74
74
|
}
|
75
75
|
function isLiteralPropertyName(name) {
|
76
|
-
return
|
76
|
+
return ts__default["default"].isIdentifier(name) || ts__default["default"].isStringLiteral(name) || ts__default["default"].isNumericLiteral(name);
|
77
77
|
}
|
78
78
|
function validateObjectProperties(nodes) {
|
79
79
|
const errors = [];
|
80
80
|
for (const node of nodes) {
|
81
|
-
if (!
|
81
|
+
if (!ts__default["default"].isPropertyAssignment(node)) {
|
82
82
|
errors.push(new ValSyntaxError("Object literal element must be property assignment", node));
|
83
83
|
} else if (!isLiteralPropertyName(node.name)) {
|
84
84
|
errors.push(new ValSyntaxError("Object literal element key must be an identifier or a literal", node));
|
@@ -95,7 +95,7 @@ function validateObjectProperties(nodes) {
|
|
95
95
|
* validating its children.
|
96
96
|
*/
|
97
97
|
function shallowValidateExpression(value) {
|
98
|
-
return
|
98
|
+
return ts__default["default"].isStringLiteralLike(value) || ts__default["default"].isNumericLiteral(value) || value.kind === ts__default["default"].SyntaxKind.TrueKeyword || value.kind === ts__default["default"].SyntaxKind.FalseKeyword || value.kind === ts__default["default"].SyntaxKind.NullKeyword || ts__default["default"].isArrayLiteralExpression(value) || ts__default["default"].isObjectLiteralExpression(value) || isValFileMethodCall(value) ? undefined : new ValSyntaxError("Expression must be a literal or call c.file", value);
|
99
99
|
}
|
100
100
|
|
101
101
|
/**
|
@@ -107,19 +107,19 @@ function evaluateExpression(value) {
|
|
107
107
|
// For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
|
108
108
|
// https://github.com/microsoft/TypeScript/blob/4b794fe1dd0d184d3f8f17e94d8187eace57c91e/src/compiler/types.ts#L2127-L2131
|
109
109
|
|
110
|
-
if (
|
110
|
+
if (ts__default["default"].isStringLiteralLike(value)) {
|
111
111
|
return fp.result.ok(value.text);
|
112
|
-
} else if (
|
112
|
+
} else if (ts__default["default"].isNumericLiteral(value)) {
|
113
113
|
return fp.result.ok(Number(value.text));
|
114
|
-
} else if (value.kind ===
|
114
|
+
} else if (value.kind === ts__default["default"].SyntaxKind.TrueKeyword) {
|
115
115
|
return fp.result.ok(true);
|
116
|
-
} else if (value.kind ===
|
116
|
+
} else if (value.kind === ts__default["default"].SyntaxKind.FalseKeyword) {
|
117
117
|
return fp.result.ok(false);
|
118
|
-
} else if (value.kind ===
|
118
|
+
} else if (value.kind === ts__default["default"].SyntaxKind.NullKeyword) {
|
119
119
|
return fp.result.ok(null);
|
120
|
-
} else if (
|
120
|
+
} else if (ts__default["default"].isArrayLiteralExpression(value)) {
|
121
121
|
return fp.result.all(value.elements.map(evaluateExpression));
|
122
|
-
} else if (
|
122
|
+
} else if (ts__default["default"].isObjectLiteralExpression(value)) {
|
123
123
|
return fp.pipe(validateObjectProperties(value.properties), fp.result.flatMap(assignments => fp.pipe(assignments.map(assignment => fp.pipe(evaluateExpression(assignment.initializer), fp.result.map(value => [assignment.name.text, value]))), fp.result.all)), fp.result.map(Object.fromEntries));
|
124
124
|
} else if (isValFileMethodCall(value)) {
|
125
125
|
return fp.pipe(findValFileNodeArg(value), fp.result.flatMap(ref => {
|
@@ -152,14 +152,14 @@ function findObjectPropertyAssignment(value, key) {
|
|
152
152
|
}));
|
153
153
|
}
|
154
154
|
function isValFileMethodCall(node) {
|
155
|
-
return
|
155
|
+
return ts__default["default"].isCallExpression(node) && ts__default["default"].isPropertyAccessExpression(node.expression) && ts__default["default"].isIdentifier(node.expression.expression) && node.expression.expression.text === "c" && node.expression.name.text === "file";
|
156
156
|
}
|
157
157
|
function findValFileNodeArg(node) {
|
158
158
|
if (node.arguments.length === 0) {
|
159
159
|
return fp.result.err(new ValSyntaxError(`Invalid c.file() call: missing ref argument`, node));
|
160
160
|
} else if (node.arguments.length > 2) {
|
161
161
|
return fp.result.err(new ValSyntaxError(`Invalid c.file() call: too many arguments ${node.arguments.length}}`, node));
|
162
|
-
} else if (!
|
162
|
+
} else if (!ts__default["default"].isStringLiteral(node.arguments[0])) {
|
163
163
|
return fp.result.err(new ValSyntaxError(`Invalid c.file() call: ref must be a string literal`, node));
|
164
164
|
}
|
165
165
|
const refNode = node.arguments[0];
|
@@ -171,7 +171,7 @@ function findValFileMetadataArg(node) {
|
|
171
171
|
} else if (node.arguments.length > 2) {
|
172
172
|
return fp.result.err(new ValSyntaxError(`Invalid c.file() call: too many arguments ${node.arguments.length}}`, node));
|
173
173
|
} else if (node.arguments.length === 2) {
|
174
|
-
if (!
|
174
|
+
if (!ts__default["default"].isObjectLiteralExpression(node.arguments[1])) {
|
175
175
|
return fp.result.err(new ValSyntaxError(`Invalid c.file() call: metadata must be a object literal`, node));
|
176
176
|
}
|
177
177
|
return fp.result.ok(node.arguments[1]);
|
@@ -186,7 +186,7 @@ function findValFileMetadataArg(node) {
|
|
186
186
|
*/
|
187
187
|
function validateInitializers(nodes) {
|
188
188
|
for (const node of nodes) {
|
189
|
-
if (
|
189
|
+
if (ts__default["default"].isSpreadElement(node)) {
|
190
190
|
return new ValSyntaxError("Unexpected spread element", node);
|
191
191
|
}
|
192
192
|
}
|
@@ -197,22 +197,22 @@ function isPath(node, path) {
|
|
197
197
|
let currentNode = node;
|
198
198
|
for (let i = path.length - 1; i > 0; --i) {
|
199
199
|
const name = path[i];
|
200
|
-
if (!
|
200
|
+
if (!ts__default["default"].isPropertyAccessExpression(currentNode)) {
|
201
201
|
return false;
|
202
202
|
}
|
203
|
-
if (!
|
203
|
+
if (!ts__default["default"].isIdentifier(currentNode.name) || currentNode.name.text !== name) {
|
204
204
|
return false;
|
205
205
|
}
|
206
206
|
currentNode = currentNode.expression;
|
207
207
|
}
|
208
|
-
return
|
208
|
+
return ts__default["default"].isIdentifier(currentNode) && currentNode.text === path[0];
|
209
209
|
}
|
210
210
|
function validateArguments(node, validators) {
|
211
211
|
return fp.result.allV([node.arguments.length === validators.length ? fp.result.voidOk : fp.result.err(new ValSyntaxError(`Expected ${validators.length} arguments`, node)), ...node.arguments.slice(0, validators.length).map((argument, index) => validators[index](argument))]);
|
212
212
|
}
|
213
213
|
function analyzeDefaultExport(node) {
|
214
214
|
const cDefine = node.expression;
|
215
|
-
if (!
|
215
|
+
if (!ts__default["default"].isCallExpression(cDefine)) {
|
216
216
|
return fp.result.err(new ValSyntaxError("Expected default expression to be a call expression", cDefine));
|
217
217
|
}
|
218
218
|
if (!isPath(cDefine.expression, ["c", "define"])) {
|
@@ -220,7 +220,7 @@ function analyzeDefaultExport(node) {
|
|
220
220
|
}
|
221
221
|
return fp.pipe(validateArguments(cDefine, [id => {
|
222
222
|
// TODO: validate ID value here?
|
223
|
-
if (!
|
223
|
+
if (!ts__default["default"].isStringLiteralLike(id)) {
|
224
224
|
return fp.result.err(new ValSyntaxError("Expected first argument to c.define to be a string literal", id));
|
225
225
|
}
|
226
226
|
return fp.result.voidOk;
|
@@ -238,7 +238,7 @@ function analyzeDefaultExport(node) {
|
|
238
238
|
}
|
239
239
|
function analyzeValModule(sourceFile) {
|
240
240
|
const analysis = sourceFile.forEachChild(node => {
|
241
|
-
if (
|
241
|
+
if (ts__default["default"].isExportAssignment(node)) {
|
242
242
|
return analyzeDefaultExport(node);
|
243
243
|
}
|
244
244
|
});
|
@@ -252,62 +252,62 @@ function isValidIdentifier(text) {
|
|
252
252
|
if (text.length === 0) {
|
253
253
|
return false;
|
254
254
|
}
|
255
|
-
if (!
|
255
|
+
if (!ts__default["default"].isIdentifierStart(text.charCodeAt(0), ts__default["default"].ScriptTarget.ES2020)) {
|
256
256
|
return false;
|
257
257
|
}
|
258
258
|
for (let i = 1; i < text.length; ++i) {
|
259
|
-
if (!
|
259
|
+
if (!ts__default["default"].isIdentifierPart(text.charCodeAt(i), ts__default["default"].ScriptTarget.ES2020)) {
|
260
260
|
return false;
|
261
261
|
}
|
262
262
|
}
|
263
263
|
return true;
|
264
264
|
}
|
265
265
|
function createPropertyAssignment(key, value) {
|
266
|
-
return
|
266
|
+
return ts__default["default"].factory.createPropertyAssignment(isValidIdentifier(key) ? ts__default["default"].factory.createIdentifier(key) : ts__default["default"].factory.createStringLiteral(key), toExpression(value));
|
267
267
|
}
|
268
268
|
function createValFileReference(value) {
|
269
|
-
const args = [
|
269
|
+
const args = [ts__default["default"].factory.createStringLiteral(value[core.FILE_REF_PROP])];
|
270
270
|
if (value.metadata) {
|
271
271
|
args.push(toExpression(value.metadata));
|
272
272
|
}
|
273
|
-
return
|
273
|
+
return ts__default["default"].factory.createCallExpression(ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createIdentifier("c"), ts__default["default"].factory.createIdentifier("file")), undefined, args);
|
274
274
|
}
|
275
275
|
function createValRichTextImage(value) {
|
276
|
-
const args = [
|
276
|
+
const args = [ts__default["default"].factory.createStringLiteral(value[core.FILE_REF_PROP])];
|
277
277
|
if (value.metadata) {
|
278
278
|
args.push(toExpression(value.metadata));
|
279
279
|
}
|
280
|
-
return
|
280
|
+
return ts__default["default"].factory.createCallExpression(ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createIdentifier("c"), "rt"), ts__default["default"].factory.createIdentifier("image")), undefined, args);
|
281
281
|
}
|
282
282
|
function createValLink(value) {
|
283
|
-
const args = [
|
283
|
+
const args = [ts__default["default"].factory.createStringLiteral(value.children[0]), toExpression({
|
284
284
|
href: value.href
|
285
285
|
})];
|
286
|
-
return
|
286
|
+
return ts__default["default"].factory.createCallExpression(ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createIdentifier("c"), "rt"), ts__default["default"].factory.createIdentifier("link")), undefined, args);
|
287
287
|
}
|
288
288
|
function createValRichTextTaggedStringTemplate(value) {
|
289
289
|
const {
|
290
290
|
templateStrings: [head, ...others],
|
291
291
|
exprs
|
292
292
|
} = value;
|
293
|
-
const tag =
|
293
|
+
const tag = ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createIdentifier("c"), ts__default["default"].factory.createIdentifier("richtext"));
|
294
294
|
if (exprs.length > 0) {
|
295
|
-
return
|
295
|
+
return ts__default["default"].factory.createTaggedTemplateExpression(tag, undefined, ts__default["default"].factory.createTemplateExpression(ts__default["default"].factory.createTemplateHead(head, head), others.map((s, i) => ts__default["default"].factory.createTemplateSpan(toExpression(exprs[i]), i < others.length - 1 ? ts__default["default"].factory.createTemplateMiddle(s, s) : ts__default["default"].factory.createTemplateTail(s, s)))));
|
296
296
|
}
|
297
|
-
return
|
297
|
+
return ts__default["default"].factory.createTaggedTemplateExpression(tag, undefined, ts__default["default"].factory.createNoSubstitutionTemplateLiteral(head, head));
|
298
298
|
}
|
299
299
|
function toExpression(value) {
|
300
300
|
if (typeof value === "string") {
|
301
301
|
// TODO: Use configuration/heuristics to determine use of single quote or double quote
|
302
|
-
return
|
302
|
+
return ts__default["default"].factory.createStringLiteral(value);
|
303
303
|
} else if (typeof value === "number") {
|
304
|
-
return
|
304
|
+
return ts__default["default"].factory.createNumericLiteral(value);
|
305
305
|
} else if (typeof value === "boolean") {
|
306
|
-
return value ?
|
306
|
+
return value ? ts__default["default"].factory.createTrue() : ts__default["default"].factory.createFalse();
|
307
307
|
} else if (value === null) {
|
308
|
-
return
|
308
|
+
return ts__default["default"].factory.createNull();
|
309
309
|
} else if (Array.isArray(value)) {
|
310
|
-
return
|
310
|
+
return ts__default["default"].factory.createArrayLiteralExpression(value.map(toExpression));
|
311
311
|
} else if (typeof value === "object") {
|
312
312
|
if (isValFileValue(value)) {
|
313
313
|
if (isValRichTextImageValue(value)) {
|
@@ -319,24 +319,24 @@ function toExpression(value) {
|
|
319
319
|
} else if (isValRichTextValue(value)) {
|
320
320
|
return createValRichTextTaggedStringTemplate(value);
|
321
321
|
}
|
322
|
-
return
|
322
|
+
return ts__default["default"].factory.createObjectLiteralExpression(Object.entries(value).map(([key, value]) => createPropertyAssignment(key, value)));
|
323
323
|
} else {
|
324
|
-
return
|
324
|
+
return ts__default["default"].factory.createStringLiteral(value);
|
325
325
|
}
|
326
326
|
}
|
327
327
|
|
328
328
|
// TODO: Choose newline based on project settings/heuristics/system default?
|
329
|
-
const newLine =
|
329
|
+
const newLine = ts__default["default"].NewLineKind.LineFeed;
|
330
330
|
// TODO: Handle indentation of printed code
|
331
|
-
const printer =
|
331
|
+
const printer = ts__default["default"].createPrinter({
|
332
332
|
newLine: newLine
|
333
333
|
// neverAsciiEscape: true,
|
334
334
|
});
|
335
335
|
function replaceNodeValue(document, node, value) {
|
336
|
-
const replacementText = printer.printNode(
|
337
|
-
const span =
|
338
|
-
const newText = `${document.text.substring(0, span.start)}${replacementText}${document.text.substring(
|
339
|
-
return [document.update(newText,
|
336
|
+
const replacementText = printer.printNode(ts__default["default"].EmitHint.Unspecified, toExpression(value), document);
|
337
|
+
const span = ts__default["default"].createTextSpanFromBounds(node.getStart(document, false), node.end);
|
338
|
+
const newText = `${document.text.substring(0, span.start)}${replacementText}${document.text.substring(ts__default["default"].textSpanEnd(span))}`;
|
339
|
+
return [document.update(newText, ts__default["default"].createTextChangeRange(span, replacementText.length)), node];
|
340
340
|
}
|
341
341
|
function isIndentation(s) {
|
342
342
|
for (let i = 0; i < s.length; ++i) {
|
@@ -348,7 +348,7 @@ function isIndentation(s) {
|
|
348
348
|
return true;
|
349
349
|
}
|
350
350
|
function newLineStr(kind) {
|
351
|
-
if (kind ===
|
351
|
+
if (kind === ts__default["default"].NewLineKind.CarriageReturnLineFeed) {
|
352
352
|
return "\r\n";
|
353
353
|
} else {
|
354
354
|
return "\n";
|
@@ -370,38 +370,38 @@ function insertAt(document, nodes, index, node) {
|
|
370
370
|
let replacementText;
|
371
371
|
if (nodes.length === 0) {
|
372
372
|
// Replace entire range of nodes
|
373
|
-
replacementText = printer.printNode(
|
374
|
-
span =
|
373
|
+
replacementText = printer.printNode(ts__default["default"].EmitHint.Unspecified, node, document);
|
374
|
+
span = ts__default["default"].createTextSpanFromBounds(nodes.pos, nodes.end);
|
375
375
|
} else if (index === nodes.length) {
|
376
376
|
// Insert after last node
|
377
377
|
const neighbor = nodes[nodes.length - 1];
|
378
|
-
replacementText = `${getSeparator(document, neighbor)}${printer.printNode(
|
379
|
-
span =
|
378
|
+
replacementText = `${getSeparator(document, neighbor)}${printer.printNode(ts__default["default"].EmitHint.Unspecified, node, document)}`;
|
379
|
+
span = ts__default["default"].createTextSpan(neighbor.end, 0);
|
380
380
|
} else {
|
381
381
|
// Insert before node
|
382
382
|
const neighbor = nodes[index];
|
383
|
-
replacementText = `${printer.printNode(
|
384
|
-
span =
|
383
|
+
replacementText = `${printer.printNode(ts__default["default"].EmitHint.Unspecified, node, document)}${getSeparator(document, neighbor)}`;
|
384
|
+
span = ts__default["default"].createTextSpan(neighbor.getStart(document, true), 0);
|
385
385
|
}
|
386
|
-
const newText = `${document.text.substring(0, span.start)}${replacementText}${document.text.substring(
|
387
|
-
return document.update(newText,
|
386
|
+
const newText = `${document.text.substring(0, span.start)}${replacementText}${document.text.substring(ts__default["default"].textSpanEnd(span))}`;
|
387
|
+
return document.update(newText, ts__default["default"].createTextChangeRange(span, replacementText.length));
|
388
388
|
}
|
389
389
|
function removeAt(document, nodes, index) {
|
390
390
|
const node = nodes[index];
|
391
391
|
let span;
|
392
392
|
if (nodes.length === 1) {
|
393
|
-
span =
|
393
|
+
span = ts__default["default"].createTextSpanFromBounds(nodes.pos, nodes.end);
|
394
394
|
} else if (index === nodes.length - 1) {
|
395
395
|
// Remove until previous node
|
396
396
|
const neighbor = nodes[index - 1];
|
397
|
-
span =
|
397
|
+
span = ts__default["default"].createTextSpanFromBounds(neighbor.end, node.end);
|
398
398
|
} else {
|
399
399
|
// Remove before next node
|
400
400
|
const neighbor = nodes[index + 1];
|
401
|
-
span =
|
401
|
+
span = ts__default["default"].createTextSpanFromBounds(node.getStart(document, true), neighbor.getStart(document, true));
|
402
402
|
}
|
403
|
-
const newText = `${document.text.substring(0, span.start)}${document.text.substring(
|
404
|
-
return [document.update(newText,
|
403
|
+
const newText = `${document.text.substring(0, span.start)}${document.text.substring(ts__default["default"].textSpanEnd(span))}`;
|
404
|
+
return [document.update(newText, ts__default["default"].createTextChangeRange(span, 0)), node];
|
405
405
|
}
|
406
406
|
function parseAndValidateArrayInsertIndex(key, nodes) {
|
407
407
|
if (key === "-") {
|
@@ -443,9 +443,9 @@ function parseAndValidateArrayInboundsIndex(key, nodes) {
|
|
443
443
|
}));
|
444
444
|
}
|
445
445
|
function replaceInNode(document, node, key, value) {
|
446
|
-
if (
|
446
|
+
if (ts__default["default"].isArrayLiteralExpression(node)) {
|
447
447
|
return fp.pipe(parseAndValidateArrayInboundsIndex(key, node.elements), fp.result.map(index => replaceNodeValue(document, node.elements[index], value)));
|
448
|
-
} else if (
|
448
|
+
} else if (ts__default["default"].isObjectLiteralExpression(node)) {
|
449
449
|
return fp.pipe(findObjectPropertyAssignment(node, key), fp.result.flatMap(assignment => {
|
450
450
|
if (!assignment) {
|
451
451
|
return fp.result.err(new patch.PatchError("Cannot replace object element which does not exist"));
|
@@ -468,7 +468,7 @@ function replaceInNode(document, node, key, value) {
|
|
468
468
|
}
|
469
469
|
return replaceInNode(document,
|
470
470
|
// TODO: creating a fake object here might not be right - seems to work though
|
471
|
-
|
471
|
+
ts__default["default"].factory.createObjectLiteralExpression([ts__default["default"].factory.createPropertyAssignment(key, metadataArgNode)]), key, value);
|
472
472
|
}));
|
473
473
|
}
|
474
474
|
} else {
|
@@ -483,9 +483,9 @@ function replaceAtPath(document, rootNode, path, value) {
|
|
483
483
|
}
|
484
484
|
}
|
485
485
|
function getFromNode(node, key) {
|
486
|
-
if (
|
486
|
+
if (ts__default["default"].isArrayLiteralExpression(node)) {
|
487
487
|
return fp.pipe(parseAndValidateArrayInboundsIndex(key, node.elements), fp.result.map(index => node.elements[index]));
|
488
|
-
} else if (
|
488
|
+
} else if (ts__default["default"].isObjectLiteralExpression(node)) {
|
489
489
|
return fp.pipe(findObjectPropertyAssignment(node, key), fp.result.map(assignment => assignment === null || assignment === void 0 ? void 0 : assignment.initializer));
|
490
490
|
} else if (isValFileMethodCall(node)) {
|
491
491
|
if (key === core.FILE_REF_PROP) {
|
@@ -515,9 +515,9 @@ function getAtPath(rootNode, path) {
|
|
515
515
|
return fp.pipe(path, fp.result.flatMapReduce((node, key) => fp.pipe(getFromNode(node, key), fp.result.filterOrElse(childNode => childNode !== undefined, () => new patch.PatchError("Path refers to non-existing object/array"))), rootNode));
|
516
516
|
}
|
517
517
|
function removeFromNode(document, node, key) {
|
518
|
-
if (
|
518
|
+
if (ts__default["default"].isArrayLiteralExpression(node)) {
|
519
519
|
return fp.pipe(parseAndValidateArrayInboundsIndex(key, node.elements), fp.result.map(index => removeAt(document, node.elements, index)));
|
520
|
-
} else if (
|
520
|
+
} else if (ts__default["default"].isObjectLiteralExpression(node)) {
|
521
521
|
return fp.pipe(findObjectPropertyAssignment(node, key), fp.result.flatMap(assignment => {
|
522
522
|
if (!assignment) {
|
523
523
|
return fp.result.err(new patch.PatchError("Cannot replace object element which does not exist"));
|
@@ -563,9 +563,9 @@ function isValRichTextValue(value) {
|
|
563
563
|
return !!(typeof value === "object" && value && core.VAL_EXTENSION in value && value[core.VAL_EXTENSION] === "richtext" && "templateStrings" in value && typeof value.templateStrings === "object" && Array.isArray(value.templateStrings));
|
564
564
|
}
|
565
565
|
function addToNode(document, node, key, value) {
|
566
|
-
if (
|
566
|
+
if (ts__default["default"].isArrayLiteralExpression(node)) {
|
567
567
|
return fp.pipe(parseAndValidateArrayInsertIndex(key, node.elements), fp.result.map(index => [insertAt(document, node.elements, index, toExpression(value))]));
|
568
|
-
} else if (
|
568
|
+
} else if (ts__default["default"].isObjectLiteralExpression(node)) {
|
569
569
|
if (key === core.FILE_REF_PROP) {
|
570
570
|
return fp.result.err(new patch.PatchError("Cannot add a key ref to object"));
|
571
571
|
}
|
@@ -687,7 +687,7 @@ function convertDataUrlToBase64(dataUrl) {
|
|
687
687
|
}
|
688
688
|
const patchSourceFile = (sourceFile, patch$1) => {
|
689
689
|
if (typeof sourceFile === "string") {
|
690
|
-
return patch.applyPatch(
|
690
|
+
return patch.applyPatch(ts__default["default"].createSourceFile("<val>", sourceFile, ts__default["default"].ScriptTarget.ES2015), ops$1, patch$1);
|
691
691
|
}
|
692
692
|
return patch.applyPatch(sourceFile, ops$1, patch$1);
|
693
693
|
};
|
@@ -803,7 +803,7 @@ const getCompilerOptions = (rootDir, parseConfigHost) => {
|
|
803
803
|
const {
|
804
804
|
config,
|
805
805
|
error
|
806
|
-
} =
|
806
|
+
} = ts__default["default"].readConfigFile(configFilePath, parseConfigHost.readFile.bind(parseConfigHost));
|
807
807
|
if (error) {
|
808
808
|
if (typeof error.messageText === "string") {
|
809
809
|
throw Error(`Could not parse config file: ${configFilePath}. Error: ${error.messageText}`);
|
@@ -811,7 +811,7 @@ const getCompilerOptions = (rootDir, parseConfigHost) => {
|
|
811
811
|
throw Error(`Could not parse config file: ${configFilePath}. Error: ${error.messageText.messageText}`);
|
812
812
|
}
|
813
813
|
const optionsOverrides = undefined;
|
814
|
-
const parsedConfigFile =
|
814
|
+
const parsedConfigFile = ts__default["default"].parseJsonConfigFileContent(config, parseConfigHost, rootDir, optionsOverrides, configFilePath);
|
815
815
|
if (parsedConfigFile.errors.length > 0) {
|
816
816
|
throw Error(`Could not parse config file: ${configFilePath}. Errors: ${parsedConfigFile.errors.map(e => e.messageText).join("\n")}`);
|
817
817
|
}
|
@@ -820,7 +820,7 @@ const getCompilerOptions = (rootDir, parseConfigHost) => {
|
|
820
820
|
|
821
821
|
class ValSourceFileHandler {
|
822
822
|
constructor(projectRoot, compilerOptions, host = {
|
823
|
-
...
|
823
|
+
...ts__default["default"].sys,
|
824
824
|
writeFile: (fileName, data, encoding) => {
|
825
825
|
fs__default["default"].mkdirSync(path__namespace["default"].dirname(fileName), {
|
826
826
|
recursive: true
|
@@ -835,9 +835,9 @@ class ValSourceFileHandler {
|
|
835
835
|
}
|
836
836
|
getSourceFile(filePath) {
|
837
837
|
const fileContent = this.host.readFile(filePath);
|
838
|
-
const scriptTarget = this.compilerOptions.target ??
|
838
|
+
const scriptTarget = this.compilerOptions.target ?? ts__default["default"].ScriptTarget.ES2020;
|
839
839
|
if (fileContent) {
|
840
|
-
return
|
840
|
+
return ts__default["default"].createSourceFile(filePath, fileContent, scriptTarget);
|
841
841
|
}
|
842
842
|
}
|
843
843
|
writeSourceFile(sourceFile) {
|
@@ -849,7 +849,7 @@ class ValSourceFileHandler {
|
|
849
849
|
this.host.writeFile(filePath, content, encoding);
|
850
850
|
}
|
851
851
|
resolveSourceModulePath(containingFilePath, requestedModuleName) {
|
852
|
-
const resolutionRes =
|
852
|
+
const resolutionRes = ts__default["default"].resolveModuleName(requestedModuleName, path__namespace["default"].isAbsolute(containingFilePath) ? containingFilePath : path__namespace["default"].resolve(this.projectRoot, containingFilePath), this.compilerOptions, this.host, undefined, undefined, ts__default["default"].ModuleKind.ESNext);
|
853
853
|
const resolvedModule = resolutionRes.resolvedModule;
|
854
854
|
if (!resolvedModule) {
|
855
855
|
throw Error(`Could not resolve module "${requestedModuleName}", base: "${containingFilePath}": No resolved modules returned: ${JSON.stringify(resolutionRes)}`);
|
@@ -870,7 +870,7 @@ class ValModuleLoader {
|
|
870
870
|
compilerOptions,
|
871
871
|
// TODO: remove this?
|
872
872
|
sourceFileHandler, host = {
|
873
|
-
...
|
873
|
+
...ts__default["default"].sys,
|
874
874
|
writeFile: (fileName, data, encoding) => {
|
875
875
|
fs__default["default"].mkdirSync(path__namespace["default"].dirname(fileName), {
|
876
876
|
recursive: true
|
@@ -1130,7 +1130,7 @@ export const IS_DEV = false;2
|
|
1130
1130
|
}
|
1131
1131
|
|
1132
1132
|
async function createService(projectRoot, opts, host = {
|
1133
|
-
...
|
1133
|
+
...ts__default["default"].sys,
|
1134
1134
|
writeFile: (fileName, data, encoding) => {
|
1135
1135
|
fs__default["default"].mkdirSync(path__namespace["default"].dirname(fileName), {
|
1136
1136
|
recursive: true
|
@@ -1782,7 +1782,11 @@ class ValServer {
|
|
1782
1782
|
}
|
1783
1783
|
let modules;
|
1784
1784
|
if (commit) {
|
1785
|
-
|
1785
|
+
const commitRes = await this.execCommit(patches, cookies);
|
1786
|
+
if (commitRes.status !== 200) {
|
1787
|
+
return commitRes;
|
1788
|
+
}
|
1789
|
+
modules = commitRes.json;
|
1786
1790
|
} else {
|
1787
1791
|
modules = await this.getPatchedModules(patches);
|
1788
1792
|
}
|
@@ -1980,6 +1984,9 @@ function guessMimeTypeFromPath(filePath) {
|
|
1980
1984
|
}
|
1981
1985
|
return null;
|
1982
1986
|
}
|
1987
|
+
function isCachedPatchFileOp(op) {
|
1988
|
+
return !!(op.op === "file" && typeof op.filePath === "string" && op.value && typeof op.value === "object" && !Array.isArray(op.value) && "sha256" in op.value && typeof op.value.sha256 === "string");
|
1989
|
+
}
|
1983
1990
|
|
1984
1991
|
const textEncoder = new TextEncoder();
|
1985
1992
|
class LocalValServer extends ValServer {
|
@@ -2248,7 +2255,10 @@ class LocalValServer extends ValServer {
|
|
2248
2255
|
this.host.rmFile(this.getPatchFilePath(patchId));
|
2249
2256
|
await this.options.service.patch(moduleId, patch);
|
2250
2257
|
}
|
2251
|
-
return
|
2258
|
+
return {
|
2259
|
+
status: 200,
|
2260
|
+
json: await this.getPatchedModules(patches)
|
2261
|
+
};
|
2252
2262
|
}
|
2253
2263
|
|
2254
2264
|
/* Bad requests on Local Server: */
|
@@ -2263,9 +2273,6 @@ class LocalValServer extends ValServer {
|
|
2263
2273
|
return this.badRequest();
|
2264
2274
|
}
|
2265
2275
|
}
|
2266
|
-
function isCachedPatchFileOp(op) {
|
2267
|
-
return !!(op.op === "file" && typeof op.filePath === "string" && op.value && typeof op.value === "object" && !Array.isArray(op.value) && "sha256" in op.value && typeof op.value.sha256 === "string");
|
2268
|
-
}
|
2269
2276
|
|
2270
2277
|
function decodeJwt(token, secretKey) {
|
2271
2278
|
const [headerBase64, payloadBase64, signatureBase64, ...rest] = token.split(".");
|
@@ -2343,8 +2350,12 @@ class RemoteFS {
|
|
2343
2350
|
}
|
2344
2351
|
async getPendingOperations() {
|
2345
2352
|
const modified = {};
|
2346
|
-
for (const modifiedFile
|
2347
|
-
|
2353
|
+
for (const modifiedFile of this.modifiedFiles) {
|
2354
|
+
const {
|
2355
|
+
directory,
|
2356
|
+
filename
|
2357
|
+
} = RemoteFS.parsePath(modifiedFile);
|
2358
|
+
modified[modifiedFile] = this.data[directory].utf8Files[filename];
|
2348
2359
|
}
|
2349
2360
|
return {
|
2350
2361
|
modified: modified,
|
@@ -2384,7 +2395,7 @@ class RemoteFS {
|
|
2384
2395
|
}
|
2385
2396
|
}
|
2386
2397
|
}
|
2387
|
-
return
|
2398
|
+
return ts__default["default"].sys.readDirectory(rootDir, extensions, excludes, includes, depth).concat(files);
|
2388
2399
|
};
|
2389
2400
|
writeFile = (filePath, data, encoding) => {
|
2390
2401
|
// never write real fs
|
@@ -2421,7 +2432,7 @@ class RemoteFS {
|
|
2421
2432
|
}
|
2422
2433
|
fileExists = filePath => {
|
2423
2434
|
var _this$data$directory;
|
2424
|
-
if (
|
2435
|
+
if (ts__default["default"].sys.fileExists(filePath)) {
|
2425
2436
|
return true;
|
2426
2437
|
}
|
2427
2438
|
const {
|
@@ -2432,7 +2443,7 @@ class RemoteFS {
|
|
2432
2443
|
return !!((_this$data$directory = this.data[directory]) !== null && _this$data$directory !== void 0 && _this$data$directory.utf8Files[filename]);
|
2433
2444
|
};
|
2434
2445
|
readFile = filePath => {
|
2435
|
-
const realFile =
|
2446
|
+
const realFile = ts__default["default"].sys.readFile(filePath);
|
2436
2447
|
if (realFile !== undefined) {
|
2437
2448
|
return realFile;
|
2438
2449
|
}
|
@@ -2448,8 +2459,8 @@ class RemoteFS {
|
|
2448
2459
|
return content;
|
2449
2460
|
};
|
2450
2461
|
realpath(fullPath) {
|
2451
|
-
if (
|
2452
|
-
return
|
2462
|
+
if (ts__default["default"].sys.fileExists(fullPath) && ts__default["default"].sys.realpath) {
|
2463
|
+
return ts__default["default"].sys.realpath(fullPath);
|
2453
2464
|
}
|
2454
2465
|
// TODO: this only works in a very limited way.
|
2455
2466
|
// It does not support symlinks to symlinks nor symlinked directories for instance.
|
@@ -2540,28 +2551,47 @@ class ProxyValServer extends ValServer {
|
|
2540
2551
|
}
|
2541
2552
|
};
|
2542
2553
|
}
|
2543
|
-
const params = `commit=${encodeURIComponent(commit)}`;
|
2554
|
+
const params = `commit=${encodeURIComponent(commit)}&root=${encodeURIComponent(this.apiOptions.root || "/")}&cwd=${encodeURIComponent(this.cwd)}`;
|
2544
2555
|
const url = new URL(`/v1/commit/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
|
2545
2556
|
|
2546
|
-
// Creates a fresh copy of the fs. We cannot touch the existing fs, since
|
2547
|
-
// other operations on it.
|
2557
|
+
// Creates a fresh copy of the fs. We cannot touch the existing fs, since there might be parallel operations?
|
2548
2558
|
// We could perhaps free up the other fs while doing this operation, but uncertain if we can actually do that and if that would actually help on memory.
|
2549
|
-
// It is a concern we have, since we might be using quite a lot of memory when having the whole FS in memory.
|
2559
|
+
// It is a concern we have, since we might be using quite a lot of memory when having the whole FS in memory.
|
2560
|
+
// NOTE that base64 values from patches are not part of the patches, nor are they part of the fs so at least we do not have to worry about them.
|
2561
|
+
// This NOTE was written after we wrote the comments above. We are a bit uncertain whether memory usage should be a concern at this point.
|
2550
2562
|
const remoteFS = new RemoteFS();
|
2551
2563
|
const initRes = await this.initRemoteFS(commit, remoteFS, token);
|
2552
2564
|
if (initRes.status !== 200) {
|
2553
2565
|
return initRes;
|
2554
2566
|
}
|
2555
2567
|
const service = await createService(this.cwd, this.apiOptions, remoteFS);
|
2556
|
-
|
2557
|
-
|
2568
|
+
// TODO: optimize patches, e.g. only take the last replace for a given thing, etc...
|
2569
|
+
const patchIds = [];
|
2570
|
+
const binaryFileUpdates = {};
|
2571
|
+
for (const [patchId, moduleId, patch] of patches) {
|
2572
|
+
const patchableOps = [];
|
2573
|
+
for (const op of patch) {
|
2574
|
+
if (isCachedPatchFileOp(op)) {
|
2575
|
+
binaryFileUpdates[op.filePath] = op.value;
|
2576
|
+
} else {
|
2577
|
+
if (core.Internal.isFileOp(op)) {
|
2578
|
+
throw new Error(`Val: Unexpected file operation (file: ${op.filePath}). This is likely a Val bug.`);
|
2579
|
+
}
|
2580
|
+
patchableOps.push(op);
|
2581
|
+
}
|
2582
|
+
}
|
2583
|
+
await service.patch(moduleId, patchableOps);
|
2584
|
+
patchIds.push(patchId);
|
2558
2585
|
}
|
2559
|
-
const
|
2586
|
+
const sourceFileUpdates = await remoteFS.getPendingOperations();
|
2560
2587
|
const fetchRes = await fetch(url, {
|
2561
2588
|
method: "POST",
|
2562
2589
|
headers: getAuthHeaders(token, "application/json"),
|
2563
2590
|
body: JSON.stringify({
|
2564
|
-
|
2591
|
+
sourceFileUpdates: sourceFileUpdates.modified,
|
2592
|
+
binaryFileUpdates,
|
2593
|
+
deletedFiles: sourceFileUpdates.deleted,
|
2594
|
+
patchIds
|
2565
2595
|
})
|
2566
2596
|
});
|
2567
2597
|
if (fetchRes.status === 200) {
|
@@ -2570,13 +2600,7 @@ class ProxyValServer extends ValServer {
|
|
2570
2600
|
json: await fetchRes.json()
|
2571
2601
|
};
|
2572
2602
|
} else {
|
2573
|
-
|
2574
|
-
return {
|
2575
|
-
status: fetchRes.status,
|
2576
|
-
json: {
|
2577
|
-
message: "Failed to get patches"
|
2578
|
-
}
|
2579
|
-
};
|
2603
|
+
return createJsonError(fetchRes);
|
2580
2604
|
}
|
2581
2605
|
});
|
2582
2606
|
}
|
@@ -2596,32 +2620,42 @@ class ProxyValServer extends ValServer {
|
|
2596
2620
|
});
|
2597
2621
|
if (fetchRes.status === 200) {
|
2598
2622
|
const json = await fetchRes.json();
|
2599
|
-
|
2623
|
+
let error = false;
|
2624
|
+
if (typeof json !== "object") {
|
2625
|
+
error = {
|
2626
|
+
details: "Invalid response: not an object"
|
2627
|
+
};
|
2628
|
+
}
|
2629
|
+
if (typeof json.git !== "object") {
|
2630
|
+
error = {
|
2631
|
+
details: "Invalid response: missing git"
|
2632
|
+
};
|
2633
|
+
}
|
2634
|
+
if (typeof json.git.commit !== "string") {
|
2635
|
+
error = {
|
2636
|
+
details: "Invalid response: missing git.commit"
|
2637
|
+
};
|
2638
|
+
}
|
2639
|
+
if (typeof json.directories !== "object" || json.directories === null) {
|
2640
|
+
error = {
|
2641
|
+
details: "Invalid response: missing directories"
|
2642
|
+
};
|
2643
|
+
}
|
2644
|
+
if (error) {
|
2645
|
+
return {
|
2646
|
+
status: 500,
|
2647
|
+
json: {
|
2648
|
+
message: "Failed to fetch remote files",
|
2649
|
+
...error
|
2650
|
+
}
|
2651
|
+
};
|
2652
|
+
}
|
2653
|
+
remoteFS.initializeWith(json.directories);
|
2600
2654
|
return {
|
2601
2655
|
status: 200
|
2602
2656
|
};
|
2603
2657
|
} else {
|
2604
|
-
|
2605
|
-
var _fetchRes$headers$get;
|
2606
|
-
if ((_fetchRes$headers$get = fetchRes.headers.get("Content-Type")) !== null && _fetchRes$headers$get !== void 0 && _fetchRes$headers$get.includes("application/json")) {
|
2607
|
-
const json = await fetchRes.json();
|
2608
|
-
return {
|
2609
|
-
status: fetchRes.status,
|
2610
|
-
json: {
|
2611
|
-
message: "Failed to fetch remote files",
|
2612
|
-
details: json
|
2613
|
-
}
|
2614
|
-
};
|
2615
|
-
}
|
2616
|
-
} catch (err) {
|
2617
|
-
console.error(err);
|
2618
|
-
}
|
2619
|
-
return {
|
2620
|
-
status: fetchRes.status,
|
2621
|
-
json: {
|
2622
|
-
message: "Unknown failure while fetching remote files"
|
2623
|
-
}
|
2624
|
-
};
|
2658
|
+
return createJsonError(fetchRes);
|
2625
2659
|
}
|
2626
2660
|
} catch (err) {
|
2627
2661
|
return {
|
@@ -2830,11 +2864,13 @@ class ProxyValServer extends ValServer {
|
|
2830
2864
|
token
|
2831
2865
|
}) => {
|
2832
2866
|
const patchIds = query.id || [];
|
2833
|
-
const
|
2834
|
-
const url = new URL(`/v1/patches/${this.options.valName}/heads/${this.options.git.branch}/~?${params}`, this.options.valContentUrl);
|
2867
|
+
const url = new URL(`/v1/patches/${this.options.valName}/heads/${this.options.git.branch}/~`, this.options.valContentUrl);
|
2835
2868
|
const fetchRes = await fetch(url, {
|
2836
|
-
method: "
|
2837
|
-
headers: getAuthHeaders(token, "application/json")
|
2869
|
+
method: "DELETE",
|
2870
|
+
headers: getAuthHeaders(token, "application/json"),
|
2871
|
+
body: JSON.stringify({
|
2872
|
+
patches: patchIds
|
2873
|
+
})
|
2838
2874
|
});
|
2839
2875
|
if (fetchRes.status === 200) {
|
2840
2876
|
return {
|
@@ -2842,13 +2878,7 @@ class ProxyValServer extends ValServer {
|
|
2842
2878
|
json: await fetchRes.json()
|
2843
2879
|
};
|
2844
2880
|
} else {
|
2845
|
-
|
2846
|
-
return {
|
2847
|
-
status: fetchRes.status,
|
2848
|
-
json: {
|
2849
|
-
message: "Failed to delete patches"
|
2850
|
-
}
|
2851
|
-
};
|
2881
|
+
return createJsonError(fetchRes);
|
2852
2882
|
}
|
2853
2883
|
});
|
2854
2884
|
}
|
@@ -2879,13 +2909,7 @@ class ProxyValServer extends ValServer {
|
|
2879
2909
|
json: await fetchRes.json()
|
2880
2910
|
};
|
2881
2911
|
} else {
|
2882
|
-
|
2883
|
-
return {
|
2884
|
-
status: fetchRes.status,
|
2885
|
-
json: {
|
2886
|
-
message: "Failed to get patches"
|
2887
|
-
}
|
2888
|
-
};
|
2912
|
+
return createJsonError(fetchRes);
|
2889
2913
|
}
|
2890
2914
|
});
|
2891
2915
|
}
|
@@ -2930,9 +2954,7 @@ class ProxyValServer extends ValServer {
|
|
2930
2954
|
json: await fetchRes.json()
|
2931
2955
|
};
|
2932
2956
|
} else {
|
2933
|
-
return
|
2934
|
-
status: fetchRes.status
|
2935
|
-
};
|
2957
|
+
return createJsonError(fetchRes);
|
2936
2958
|
}
|
2937
2959
|
});
|
2938
2960
|
}
|
@@ -3093,6 +3115,22 @@ function getStateFromCookie(stateCookie) {
|
|
3093
3115
|
};
|
3094
3116
|
}
|
3095
3117
|
}
|
3118
|
+
async function createJsonError(fetchRes) {
|
3119
|
+
var _fetchRes$headers$get;
|
3120
|
+
if ((_fetchRes$headers$get = fetchRes.headers.get("Content-Type")) !== null && _fetchRes$headers$get !== void 0 && _fetchRes$headers$get.includes("application/json")) {
|
3121
|
+
return {
|
3122
|
+
status: fetchRes.status,
|
3123
|
+
json: await fetchRes.json()
|
3124
|
+
};
|
3125
|
+
}
|
3126
|
+
console.error("Unexpected failure (did not get a json) - Val down?", fetchRes.status, await fetchRes.text());
|
3127
|
+
return {
|
3128
|
+
status: fetchRes.status,
|
3129
|
+
json: {
|
3130
|
+
message: "Unexpected failure (did not get a json) - Val down?"
|
3131
|
+
}
|
3132
|
+
};
|
3133
|
+
}
|
3096
3134
|
function createStateCookie(state) {
|
3097
3135
|
return Buffer.from(JSON.stringify(state), "utf8").toString("base64");
|
3098
3136
|
}
|