@servicenow/sdk-build-core 4.6.0 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compiler.d.ts +2 -0
- package/dist/compiler.js +13 -7
- package/dist/compiler.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/now-config.d.ts +51 -3
- package/dist/now-config.js +44 -1
- package/dist/now-config.js.map +1 -1
- package/dist/package-inventory.d.ts +15 -0
- package/dist/package-inventory.js +59 -0
- package/dist/package-inventory.js.map +1 -0
- package/dist/plugins/context.d.ts +2 -2
- package/dist/plugins/file.d.ts +1 -0
- package/dist/plugins/index.d.ts +0 -1
- package/dist/plugins/index.js +0 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/plugin.d.ts +41 -53
- package/dist/plugins/plugin.js +517 -162
- package/dist/plugins/plugin.js.map +1 -1
- package/dist/plugins/shape.d.ts +13 -2
- package/dist/plugins/shape.js +96 -15
- package/dist/plugins/shape.js.map +1 -1
- package/dist/taxonomy.js +7 -2
- package/dist/taxonomy.js.map +1 -1
- package/dist/telemetry/clients/detect-agent.d.ts +4 -0
- package/dist/telemetry/clients/detect-agent.js +84 -0
- package/dist/telemetry/clients/detect-agent.js.map +1 -0
- package/dist/telemetry/clients/node-client.d.ts +2 -0
- package/dist/telemetry/clients/node-client.js +10 -9
- package/dist/telemetry/clients/node-client.js.map +1 -1
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/xml.d.ts +2 -2
- package/dist/xml.js +2 -2
- package/dist/xml.js.map +1 -1
- package/now.config.schema.json +54 -0
- package/package.json +9 -5
- package/src/compiler.ts +14 -7
- package/src/index.ts +1 -0
- package/src/now-config.ts +56 -1
- package/src/package-inventory.ts +75 -0
- package/src/plugins/context.ts +2 -2
- package/src/plugins/file.ts +1 -0
- package/src/plugins/index.ts +0 -1
- package/src/plugins/plugin.ts +704 -231
- package/src/plugins/shape.ts +115 -24
- package/src/taxonomy.ts +8 -2
- package/src/telemetry/clients/detect-agent.ts +88 -0
- package/src/telemetry/clients/node-client.ts +12 -8
- package/src/telemetry/index.ts +1 -1
- package/src/xml.ts +11 -2
- package/dist/plugins/cache.d.ts +0 -15
- package/dist/plugins/cache.js +0 -22
- package/dist/plugins/cache.js.map +0 -1
- package/dist/plugins/usage.d.ts +0 -11
- package/dist/plugins/usage.js +0 -26
- package/dist/plugins/usage.js.map +0 -1
- package/src/plugins/cache.ts +0 -23
- package/src/plugins/usage.ts +0 -26
package/dist/plugins/plugin.js
CHANGED
|
@@ -5,9 +5,9 @@ const typescript_1 = require("../typescript");
|
|
|
5
5
|
const shape_1 = require("./shape");
|
|
6
6
|
const database_1 = require("./database");
|
|
7
7
|
const util_1 = require("../util");
|
|
8
|
-
const cache_1 = require("./cache");
|
|
9
8
|
const __1 = require("..");
|
|
10
9
|
const sdk_build_core_1 = require("@servicenow/sdk-build-core");
|
|
10
|
+
const FAILURE = { success: false };
|
|
11
11
|
function setCreator(creator, result) {
|
|
12
12
|
if (result.success) {
|
|
13
13
|
result.value = Array.isArray(result.value)
|
|
@@ -16,11 +16,190 @@ function setCreator(creator, result) {
|
|
|
16
16
|
}
|
|
17
17
|
return result;
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Recursively sets `sys_policy` on a record and all its descendants,
|
|
21
|
+
* skipping any record that already has `sys_policy` set by the plugin.
|
|
22
|
+
*/
|
|
23
|
+
function propagateSysPolicyToDescendants(record, sysPolicyShape) {
|
|
24
|
+
const patched = record.get('sys_policy').isUndefined() ? record.merge({ sys_policy: sysPolicyShape }) : record;
|
|
25
|
+
// flat() cannot substitute here: it collapses the entire descendant tree into a single array,
|
|
26
|
+
// discarding which records are direct children of which parent. This function rebuilds the
|
|
27
|
+
// hierarchy bottom-up via .with(), so it must operate one level at a time using getRelated().
|
|
28
|
+
const children = patched.getRelated();
|
|
29
|
+
if (children.length === 0) {
|
|
30
|
+
return patched;
|
|
31
|
+
}
|
|
32
|
+
return patched.with(...children.map((child) => propagateSysPolicyToDescendants(child, sysPolicyShape)));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Auto-injects `sys_policy` into the record and all its descendants from the shape's
|
|
36
|
+
* `protectionPolicy` property, so that plugins don't need to explicitly map it.
|
|
37
|
+
* Only injects if `sys_policy` is not already set by the plugin, and only propagates
|
|
38
|
+
* if the root record's plugin did not already handle `sys_policy` itself.
|
|
39
|
+
*/
|
|
40
|
+
function mergeSysPolicyFromShape(shape, record) {
|
|
41
|
+
if (!(shape instanceof shape_1.CallExpressionShape)) {
|
|
42
|
+
return record;
|
|
43
|
+
}
|
|
44
|
+
const source = shape.getArgument(0).ifObject();
|
|
45
|
+
if (!source) {
|
|
46
|
+
return record;
|
|
47
|
+
}
|
|
48
|
+
const protectionPolicy = source.get('protectionPolicy');
|
|
49
|
+
if (protectionPolicy.isUndefined()) {
|
|
50
|
+
return record;
|
|
51
|
+
}
|
|
52
|
+
// If the plugin already mapped sys_policy on the root record, skip propagation entirely.
|
|
53
|
+
// The plugin owns the protectionPolicy handling in this case.
|
|
54
|
+
if (record.get('sys_policy').isDefined()) {
|
|
55
|
+
return record;
|
|
56
|
+
}
|
|
57
|
+
return propagateSysPolicyToDescendants(record, protectionPolicy);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Auto-injects `protectionPolicy` into the shape from the record's `sys_policy` field,
|
|
61
|
+
* so that plugins don't need to explicitly map it. Only injects if `protectionPolicy` is
|
|
62
|
+
* not already set by the plugin.
|
|
63
|
+
*/
|
|
64
|
+
function mergeProtectionPolicyFromRecord(record, shape) {
|
|
65
|
+
if (!(shape instanceof shape_1.CallExpressionShape)) {
|
|
66
|
+
return shape;
|
|
67
|
+
}
|
|
68
|
+
const firstArg = shape.getArgument(0).ifObject();
|
|
69
|
+
if (!firstArg || firstArg.get('protectionPolicy').isDefined()) {
|
|
70
|
+
return shape;
|
|
71
|
+
}
|
|
72
|
+
const sysPolicy = record.get('sys_policy').ifString()?.getValue();
|
|
73
|
+
if (!sysPolicy) {
|
|
74
|
+
return shape;
|
|
75
|
+
}
|
|
76
|
+
return new shape_1.CallExpressionShape({
|
|
77
|
+
source: shape.getSource(),
|
|
78
|
+
callee: shape.getCallee(),
|
|
79
|
+
args: [firstArg.merge({ protectionPolicy: sysPolicy }), ...shape.getArguments().slice(1)],
|
|
80
|
+
exportName: shape.getExportName(),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Auto-injects `$meta.installMethod` into the shape based on the record's install category.
|
|
85
|
+
* When transforming from `unload.demo/`, `unload/`, or `apply_once/` directories, the generated
|
|
86
|
+
* Fluent code should include `$meta: { installMethod: 'demo' | 'first install' | 'once' }`.
|
|
87
|
+
* Only injects if `$meta.installMethod` is not already set by the plugin.
|
|
88
|
+
*/
|
|
89
|
+
function mergeMetaFromRecord(record, shape) {
|
|
90
|
+
if (!(shape instanceof shape_1.CallExpressionShape)) {
|
|
91
|
+
return shape;
|
|
92
|
+
}
|
|
93
|
+
const firstArg = shape.getArgument(0).ifObject();
|
|
94
|
+
const existingMeta = firstArg?.get('$meta').ifObject();
|
|
95
|
+
if (!firstArg || existingMeta?.get('installMethod').isDefined()) {
|
|
96
|
+
return shape;
|
|
97
|
+
}
|
|
98
|
+
const installCategory = record.getInstallCategory();
|
|
99
|
+
let installMethod;
|
|
100
|
+
if (installCategory === 'unload.demo') {
|
|
101
|
+
installMethod = 'demo';
|
|
102
|
+
}
|
|
103
|
+
else if (installCategory === 'unload') {
|
|
104
|
+
installMethod = 'first install';
|
|
105
|
+
}
|
|
106
|
+
else if (installCategory === 'apply_once') {
|
|
107
|
+
installMethod = 'once';
|
|
108
|
+
}
|
|
109
|
+
if (!installMethod) {
|
|
110
|
+
return shape;
|
|
111
|
+
}
|
|
112
|
+
return new shape_1.CallExpressionShape({
|
|
113
|
+
source: shape.getSource(),
|
|
114
|
+
callee: shape.getCallee(),
|
|
115
|
+
args: [firstArg.merge({ $meta: { installMethod } }), ...shape.getArguments().slice(1)],
|
|
116
|
+
exportName: shape.getExportName(),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Injects `$override` properties from the Fluent shape into the record, so plugins don't
|
|
121
|
+
* need to explicitly map them. Only injects fields not already set by the plugin.
|
|
122
|
+
*/
|
|
123
|
+
function mergeOverrideFromShape(shape, record, diagnostics) {
|
|
124
|
+
if (!(shape instanceof shape_1.CallExpressionShape)) {
|
|
125
|
+
return record;
|
|
126
|
+
}
|
|
127
|
+
const override = shape.getArgument(0).ifObject()?.get('$override').ifObject();
|
|
128
|
+
if (!override) {
|
|
129
|
+
return record;
|
|
130
|
+
}
|
|
131
|
+
const extra = {};
|
|
132
|
+
const overrideKeys = new Set();
|
|
133
|
+
for (const [key, value] of override.entries()) {
|
|
134
|
+
if (key.startsWith('sys_')) {
|
|
135
|
+
diagnostics.warn(value, `$override: '${key}' starts with 'sys_' and will not be restored on transform — remove it or use a supported API property instead.`);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (record.get(key).isDefined()) {
|
|
139
|
+
diagnostics.warn(value, `$override: '${key}' is already set by the plugin and will be ignored — use the corresponding API property instead.`);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
overrideKeys.add(key);
|
|
143
|
+
extra[key] = value;
|
|
144
|
+
}
|
|
145
|
+
const result = overrideKeys.size > 0 ? record.merge(extra) : record;
|
|
146
|
+
return result.withOverrideKeys(overrideKeys);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Injects `$override` into the shape. Includes:
|
|
150
|
+
* - Custom fields (`u_*` / `x_*`) with non-empty values.
|
|
151
|
+
* - Any field that was explicitly in the existing record's `$override` — re-emitted with the
|
|
152
|
+
* fresh DB value.
|
|
153
|
+
*/
|
|
154
|
+
function mergeOverrideFromRecord(record, shape, accessed, existingRecord) {
|
|
155
|
+
const inner = shape instanceof shape_1.VariableStatementShape ? shape.getInitializer() : shape;
|
|
156
|
+
const ce = inner instanceof shape_1.CallExpressionShape ? inner : null;
|
|
157
|
+
if (!ce) {
|
|
158
|
+
return shape;
|
|
159
|
+
}
|
|
160
|
+
const firstArg = ce.getArgument(0).ifObject();
|
|
161
|
+
if (!firstArg || firstArg.get('$override').isDefined()) {
|
|
162
|
+
return shape;
|
|
163
|
+
}
|
|
164
|
+
const existingOverrideKeys = existingRecord?.getOverrideKeys();
|
|
165
|
+
const override = {};
|
|
166
|
+
for (const [key, value] of record.entries()) {
|
|
167
|
+
if (key.startsWith('sys_') || accessed.has(key)) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const isCustomField = key.startsWith('u_') || key.startsWith('x_');
|
|
171
|
+
if (!isCustomField && !existingOverrideKeys?.has(key)) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
// Preserve empty strings when the key was explicitly put in $override previously —
|
|
175
|
+
// that's how users clear a field. Only skip empty strings for newly-discovered fields.
|
|
176
|
+
const wasExplicitlyOverridden = existingOverrideKeys?.has(key);
|
|
177
|
+
if (!value.isDefined() || (!wasExplicitlyOverridden && value.ifString()?.isEmpty())) {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
override[key] = value;
|
|
181
|
+
}
|
|
182
|
+
if (Object.keys(override).length === 0) {
|
|
183
|
+
return shape;
|
|
184
|
+
}
|
|
185
|
+
const modified = new shape_1.CallExpressionShape({
|
|
186
|
+
source: ce.getSource(),
|
|
187
|
+
callee: ce.getCallee(),
|
|
188
|
+
args: [firstArg.merge({ $override: override }), ...ce.getArguments().slice(1)],
|
|
189
|
+
exportName: ce.getExportName(),
|
|
190
|
+
});
|
|
191
|
+
if (!(shape instanceof shape_1.VariableStatementShape)) {
|
|
192
|
+
return modified;
|
|
193
|
+
}
|
|
194
|
+
return new shape_1.VariableStatementShape({
|
|
195
|
+
source: shape.getSource(),
|
|
196
|
+
variableName: shape.getVariableName(),
|
|
197
|
+
initializer: modified,
|
|
198
|
+
isExported: shape.isExported(),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
19
201
|
class Plugin {
|
|
20
202
|
config;
|
|
21
|
-
nodeToShapeCache = new cache_1.Cache();
|
|
22
|
-
shapeToSubclassCache = new cache_1.Cache();
|
|
23
|
-
shapeToRecordCache = new cache_1.Cache();
|
|
24
203
|
relationships = {};
|
|
25
204
|
references = {};
|
|
26
205
|
constructor(config) {
|
|
@@ -174,19 +353,6 @@ class Plugin {
|
|
|
174
353
|
getName() {
|
|
175
354
|
return this.config.name;
|
|
176
355
|
}
|
|
177
|
-
/**
|
|
178
|
-
* Get documentation metadata for APIs provided by this plugin.
|
|
179
|
-
*/
|
|
180
|
-
getDocsMetadata() {
|
|
181
|
-
if (!this.config.docs) {
|
|
182
|
-
return undefined;
|
|
183
|
-
}
|
|
184
|
-
const manifest = {};
|
|
185
|
-
for (const doc of this.config.docs) {
|
|
186
|
-
manifest[doc.apiName] = { tags: doc.tags };
|
|
187
|
-
}
|
|
188
|
-
return manifest;
|
|
189
|
-
}
|
|
190
356
|
getDescendants(parent, database) {
|
|
191
357
|
return this.traverseDescendants(parent, database);
|
|
192
358
|
}
|
|
@@ -286,33 +452,6 @@ class Plugin {
|
|
|
286
452
|
getRelationships() {
|
|
287
453
|
return this.relationships;
|
|
288
454
|
}
|
|
289
|
-
flushCache() {
|
|
290
|
-
this.nodeToShapeCache.clear();
|
|
291
|
-
this.shapeToRecordCache.clear();
|
|
292
|
-
}
|
|
293
|
-
async nodeToShape(node, context) {
|
|
294
|
-
const entry = this.nodeToShapeCache.get(node.compilerNode);
|
|
295
|
-
if (entry) {
|
|
296
|
-
return entry.success ? entry.value : { success: false };
|
|
297
|
-
}
|
|
298
|
-
try {
|
|
299
|
-
for (const config of this.config.nodes ?? []) {
|
|
300
|
-
if (config.toShape &&
|
|
301
|
-
(0, typescript_1.getKindName)(node) === config.node &&
|
|
302
|
-
(!config.fileTypes ||
|
|
303
|
-
config.fileTypes.includes((0, util_1.getFileType)(node.getSourceFile().getFilePath(), context.project)))) {
|
|
304
|
-
const result = setCreator(this, await config.toShape.bind(this)(node, { ...context, self: this }));
|
|
305
|
-
if (result.success) {
|
|
306
|
-
return this.nodeToShapeCache.put(node.compilerNode, result);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
return this.nodeToShapeCache.put(node.compilerNode, { success: false });
|
|
311
|
-
}
|
|
312
|
-
catch (e) {
|
|
313
|
-
throw this.nodeToShapeCache.error(node.compilerNode, e);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
455
|
async commit(shape, target, context) {
|
|
317
456
|
for (const { shape: shapeClass, commit } of this.config.shapes ?? []) {
|
|
318
457
|
if (shape.is(shapeClass) && commit) {
|
|
@@ -322,7 +461,7 @@ class Plugin {
|
|
|
322
461
|
}
|
|
323
462
|
}
|
|
324
463
|
}
|
|
325
|
-
return
|
|
464
|
+
return FAILURE;
|
|
326
465
|
}
|
|
327
466
|
async getTarget(shape, context) {
|
|
328
467
|
for (const { shape: shapeClass, getTarget } of this.config.shapes ?? []) {
|
|
@@ -333,85 +472,43 @@ class Plugin {
|
|
|
333
472
|
}
|
|
334
473
|
}
|
|
335
474
|
}
|
|
336
|
-
return
|
|
337
|
-
}
|
|
338
|
-
async shapeToSubclass(shape, context) {
|
|
339
|
-
const entry = this.shapeToSubclassCache.get(shape);
|
|
340
|
-
if (entry) {
|
|
341
|
-
return entry.success ? entry.value : { success: false };
|
|
342
|
-
}
|
|
343
|
-
try {
|
|
344
|
-
for (const config of this.config.shapes ?? []) {
|
|
345
|
-
if (config.toSubclass &&
|
|
346
|
-
shape.constructor === config.shape &&
|
|
347
|
-
(!config.fileTypes ||
|
|
348
|
-
config.fileTypes.includes((0, util_1.getFileType)(shape.getOriginalFilePath(), context.project)))) {
|
|
349
|
-
const result = setCreator(this, await config.toSubclass.bind(this)(shape, {
|
|
350
|
-
...context,
|
|
351
|
-
self: this,
|
|
352
|
-
}));
|
|
353
|
-
if (result.success) {
|
|
354
|
-
if (result.value.constructor === config.shape) {
|
|
355
|
-
throw new Error(`Result of subclassing "${config.shape.name}" is an instance of the same class. The result MUST be a subclass.`);
|
|
356
|
-
}
|
|
357
|
-
return this.shapeToSubclassCache.put(shape, result);
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
return this.shapeToSubclassCache.put(shape, { success: false });
|
|
362
|
-
}
|
|
363
|
-
catch (e) {
|
|
364
|
-
throw this.shapeToSubclassCache.error(shape, e);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
async shapeToRecord(shape, context) {
|
|
368
|
-
const entry = this.shapeToRecordCache.get(shape);
|
|
369
|
-
if (entry) {
|
|
370
|
-
return entry.success ? entry.value : { success: false };
|
|
371
|
-
}
|
|
372
|
-
try {
|
|
373
|
-
for (const config of this.config.shapes ?? []) {
|
|
374
|
-
if (config.toRecord &&
|
|
375
|
-
shape.is(config.shape) &&
|
|
376
|
-
(!config.fileTypes ||
|
|
377
|
-
config.fileTypes.includes((0, util_1.getFileType)(shape.getOriginalFilePath(), context.project)))) {
|
|
378
|
-
const result = setCreator(this, await config.toRecord.bind(this)(shape, { ...context, self: this }));
|
|
379
|
-
if (result.success) {
|
|
380
|
-
return this.shapeToRecordCache.put(shape, result);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
return this.shapeToRecordCache.put(shape, { success: false });
|
|
385
|
-
}
|
|
386
|
-
catch (e) {
|
|
387
|
-
throw this.shapeToRecordCache.error(shape, e);
|
|
388
|
-
}
|
|
475
|
+
return FAILURE;
|
|
389
476
|
}
|
|
390
|
-
async recordToShape0(record, context) {
|
|
477
|
+
async recordToShape0(record, context, existingRecord) {
|
|
391
478
|
if (record.getAction() !== 'INSERT_OR_UPDATE') {
|
|
392
479
|
return { success: true, value: new shape_1.DeletedShape({ source: record }) };
|
|
393
480
|
}
|
|
394
481
|
const table = record.getTable();
|
|
395
|
-
for (const [configTable,
|
|
396
|
-
if (
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
482
|
+
for (const [configTable, recordConfig] of Object.entries(this.config.records ?? {})) {
|
|
483
|
+
if (configTable !== '*' && configTable !== table) {
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
if (!recordConfig.toShape) {
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
record.startTracking();
|
|
490
|
+
const result = setCreator(this, await recordConfig.toShape.bind(this)(record, { ...context, self: this }));
|
|
491
|
+
if (result.success) {
|
|
492
|
+
const accessed = record.getTrackedFields();
|
|
493
|
+
let value = mergeOverrideFromRecord(record, result.value, accessed, existingRecord);
|
|
494
|
+
value = mergeProtectionPolicyFromRecord(record, value);
|
|
495
|
+
value = mergeMetaFromRecord(record, value);
|
|
496
|
+
return { ...result, value };
|
|
401
497
|
}
|
|
402
498
|
}
|
|
403
|
-
return
|
|
499
|
+
return FAILURE;
|
|
404
500
|
}
|
|
405
|
-
async recordToShape({ record, database, context, }) {
|
|
501
|
+
async recordToShape({ record, database, existingDatabase, context, }) {
|
|
406
502
|
context.logger.debug(`Transforming record into shape: ${record.getTable()}.${record.getId().getValue()}`);
|
|
407
503
|
const descendants = this.getDescendants(record, database);
|
|
504
|
+
const existingRecord = existingDatabase?.resolve(record.getId());
|
|
408
505
|
return this.recordToShape0(record, {
|
|
409
506
|
...context,
|
|
410
507
|
database,
|
|
411
508
|
descendants: new database_1.Database(descendants.filter((r) => r.getAction() === 'INSERT_OR_UPDATE')),
|
|
412
|
-
});
|
|
509
|
+
}, existingRecord);
|
|
413
510
|
}
|
|
414
|
-
async recordsToShapes({ database, creatorOnly, changedOnly = false, mode, handledRecords, context, }) {
|
|
511
|
+
async recordsToShapes({ database, existingDatabase, creatorOnly, changedOnly = false, mode, handledRecords, context, }) {
|
|
415
512
|
let success = false;
|
|
416
513
|
const shapes = [];
|
|
417
514
|
const unhandledRecords = [];
|
|
@@ -454,11 +551,12 @@ class Plugin {
|
|
|
454
551
|
nonDeletedDescendants.insert(descendant);
|
|
455
552
|
}
|
|
456
553
|
}
|
|
554
|
+
const existingRecord = existingDatabase?.resolve(record.getId());
|
|
457
555
|
const result = await this.recordToShape0(record, {
|
|
458
556
|
...context,
|
|
459
557
|
database,
|
|
460
558
|
descendants: nonDeletedDescendants,
|
|
461
|
-
});
|
|
559
|
+
}, existingRecord);
|
|
462
560
|
if (result.success === 'partial') {
|
|
463
561
|
for (const unhandledRecord of result.unhandledRecords) {
|
|
464
562
|
unhandledRecords.push(unhandledRecord);
|
|
@@ -484,7 +582,7 @@ class Plugin {
|
|
|
484
582
|
}
|
|
485
583
|
else if (!descendant.getCreator() ||
|
|
486
584
|
!record.getCreator() ||
|
|
487
|
-
descendant.getCreator()
|
|
585
|
+
descendant.getCreator()?.getName() === record.getCreator()?.getName()) {
|
|
488
586
|
// This descendant is handled by the same plugin that handled the root record
|
|
489
587
|
handledRecords.insert(descendant);
|
|
490
588
|
}
|
|
@@ -494,7 +592,7 @@ class Plugin {
|
|
|
494
592
|
}
|
|
495
593
|
}
|
|
496
594
|
if (unhandledRecords.length > 0) {
|
|
497
|
-
context.logger.debug(`Plugin ${this.getName()} deferred handling of records: ${unhandledRecords.map((r) => r.getTable()
|
|
595
|
+
context.logger.debug(`Plugin ${this.getName()} deferred handling of records: ${unhandledRecords.map((r) => `${r.getTable()}_${r.getId().getValue()}`).join(', ')}`);
|
|
498
596
|
return { success: 'partial', value: shapes, unhandledRecords };
|
|
499
597
|
}
|
|
500
598
|
return { success, value: shapes };
|
|
@@ -548,12 +646,25 @@ class Plugin {
|
|
|
548
646
|
const filePath = sdk_build_core_1.path.normalize(record.getOriginalFilePath());
|
|
549
647
|
if ((0, util_1.isSNScope)(context.config.scope) && filePath.endsWith(__1.NOW_FILE_EXTENSION)) {
|
|
550
648
|
const relativePath = sdk_build_core_1.path.relative(sdk_build_core_1.path.join(context.config.fluentDir, 'if'), filePath);
|
|
551
|
-
|
|
649
|
+
const relativePathGenerated = sdk_build_core_1.path.relative(sdk_build_core_1.path.join(context.config.generatedDir, 'if'), filePath);
|
|
650
|
+
if (!relativePath.startsWith('..') ||
|
|
651
|
+
(!relativePathGenerated.startsWith('..') && sdk_build_core_1.path.dirname(relativePath) !== '.')) {
|
|
652
|
+
const subPath = relativePath.startsWith('..') ? relativePathGenerated : relativePath;
|
|
552
653
|
return {
|
|
553
654
|
success: true,
|
|
554
655
|
value: outputFiles.map((f) => ({
|
|
555
656
|
...f,
|
|
556
|
-
ifDirectoryPackage: sdk_build_core_1.path.join('if', sdk_build_core_1.path.
|
|
657
|
+
ifDirectoryPackage: sdk_build_core_1.path.join('if', subPath.split(sdk_build_core_1.path.sep)[0]),
|
|
658
|
+
})),
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
const hosted = __1.NowConfig.getHostedDirectory(context.config, filePath);
|
|
662
|
+
if (hosted) {
|
|
663
|
+
return {
|
|
664
|
+
success: true,
|
|
665
|
+
value: outputFiles.map((f) => ({
|
|
666
|
+
...f,
|
|
667
|
+
hostedPluginDir: hosted,
|
|
557
668
|
})),
|
|
558
669
|
};
|
|
559
670
|
}
|
|
@@ -562,7 +673,7 @@ class Plugin {
|
|
|
562
673
|
}
|
|
563
674
|
}
|
|
564
675
|
}
|
|
565
|
-
return
|
|
676
|
+
return FAILURE;
|
|
566
677
|
}
|
|
567
678
|
async recordsToFiles({ database, mode, handledGuids, context, }) {
|
|
568
679
|
let success = false;
|
|
@@ -605,32 +716,36 @@ class Plugin {
|
|
|
605
716
|
}
|
|
606
717
|
return { success, value: files };
|
|
607
718
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
continue;
|
|
617
|
-
}
|
|
618
|
-
return !!config.entryPoint;
|
|
719
|
+
getEntryPoints() {
|
|
720
|
+
const entryPoints = {
|
|
721
|
+
nodes: new Map(),
|
|
722
|
+
files: [],
|
|
723
|
+
};
|
|
724
|
+
for (const config of this.config.nodes ?? []) {
|
|
725
|
+
if (!config.entryPoint) {
|
|
726
|
+
continue;
|
|
619
727
|
}
|
|
728
|
+
const fileTypes = entryPoints.nodes.get(config.node) ?? new Set();
|
|
729
|
+
if (config.fileTypes) {
|
|
730
|
+
// Plugin only accepts the node from certain file types
|
|
731
|
+
config.fileTypes.forEach((t) => fileTypes.add(t));
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
// Plugin accepts the node from any file type
|
|
735
|
+
fileTypes.add('*');
|
|
736
|
+
}
|
|
737
|
+
entryPoints.nodes.set(config.node, fileTypes);
|
|
620
738
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
!(await config.matcher(pathOrNode, { ...context, self: this }))) {
|
|
628
|
-
continue;
|
|
629
|
-
}
|
|
630
|
-
return !!config.entryPoint;
|
|
739
|
+
for (const config of this.config.files ?? []) {
|
|
740
|
+
if (!config.entryPoint) {
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
if (!config.matcher) {
|
|
744
|
+
throw new Error(`Plugin "${this.getName()}" defines a file entry point with no matcher. This would cause all files to be treated as entry points.`);
|
|
631
745
|
}
|
|
746
|
+
entryPoints.files.push({ plugin: this, matcher: config.matcher });
|
|
632
747
|
}
|
|
633
|
-
return
|
|
748
|
+
return entryPoints;
|
|
634
749
|
}
|
|
635
750
|
async fileToRecord(file, context) {
|
|
636
751
|
for (const config of this.config.files ?? []) {
|
|
@@ -648,7 +763,7 @@ class Plugin {
|
|
|
648
763
|
return result;
|
|
649
764
|
}
|
|
650
765
|
}
|
|
651
|
-
return
|
|
766
|
+
return FAILURE;
|
|
652
767
|
}
|
|
653
768
|
inspect(shape, context) {
|
|
654
769
|
for (const config of this.config.shapes ?? []) {
|
|
@@ -667,32 +782,110 @@ class Plugin {
|
|
|
667
782
|
}
|
|
668
783
|
}
|
|
669
784
|
}
|
|
670
|
-
return
|
|
785
|
+
return FAILURE;
|
|
786
|
+
}
|
|
787
|
+
getConfig() {
|
|
788
|
+
return this.config;
|
|
671
789
|
}
|
|
672
790
|
}
|
|
673
791
|
exports.Plugin = Plugin;
|
|
674
792
|
class Plugins {
|
|
675
|
-
plugins;
|
|
793
|
+
plugins = new Map();
|
|
794
|
+
nodeToShapeCache = new WeakMap();
|
|
795
|
+
shapeToSubclassCache = new WeakMap();
|
|
796
|
+
shapeToRecordCache = new WeakMap();
|
|
797
|
+
entryPoints = {
|
|
798
|
+
nodes: new Map(),
|
|
799
|
+
files: [],
|
|
800
|
+
};
|
|
676
801
|
constructor(plugins) {
|
|
677
|
-
|
|
802
|
+
for (const plugin of plugins) {
|
|
803
|
+
this.plugins.set(plugin.getName(), Plugins.createEntry(plugin));
|
|
804
|
+
}
|
|
805
|
+
this.reload();
|
|
678
806
|
}
|
|
679
|
-
|
|
680
|
-
return
|
|
807
|
+
static createEntry(plugin) {
|
|
808
|
+
return {
|
|
809
|
+
plugin,
|
|
810
|
+
shapeCount: 0,
|
|
811
|
+
nodeToShapeCache: new WeakMap(),
|
|
812
|
+
shapeToSubclassCache: new WeakMap(),
|
|
813
|
+
shapeToRecordCache: new WeakMap(),
|
|
814
|
+
};
|
|
681
815
|
}
|
|
682
|
-
|
|
683
|
-
const
|
|
684
|
-
|
|
685
|
-
|
|
816
|
+
get(plugin) {
|
|
817
|
+
const name = plugin instanceof Plugin ? plugin.getName() : plugin;
|
|
818
|
+
const entry = this.plugins.get(name);
|
|
819
|
+
if (entry) {
|
|
820
|
+
return entry;
|
|
821
|
+
}
|
|
822
|
+
if (plugin instanceof Plugin) {
|
|
823
|
+
// Some plugins (mainly Flows) use "helper" plugins that are not actually registered. This is temporarily supporting that use case until we can get rid of those "helper" plugins.
|
|
824
|
+
return Plugins.createEntry(plugin);
|
|
825
|
+
}
|
|
826
|
+
throw new Error(`No such plugin with name "${name}"`);
|
|
827
|
+
}
|
|
828
|
+
*[Symbol.iterator]() {
|
|
829
|
+
for (const entry of this.plugins.values()) {
|
|
830
|
+
yield entry.plugin;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
reload() {
|
|
834
|
+
this.nodeToShapeCache = new WeakMap();
|
|
835
|
+
this.shapeToSubclassCache = new WeakMap();
|
|
836
|
+
this.shapeToRecordCache = new WeakMap();
|
|
837
|
+
this.entryPoints.nodes.clear();
|
|
838
|
+
this.entryPoints.files.length = 0;
|
|
839
|
+
for (const entry of this.plugins.values()) {
|
|
840
|
+
entry.nodeToShapeCache = new WeakMap();
|
|
841
|
+
entry.shapeToSubclassCache = new WeakMap();
|
|
842
|
+
entry.shapeToRecordCache = new WeakMap();
|
|
843
|
+
entry.shapeCount = 0;
|
|
844
|
+
const { nodes, files } = entry.plugin.getEntryPoints();
|
|
845
|
+
for (const [nodeKind, fileTypes] of nodes.entries()) {
|
|
846
|
+
const existing = this.entryPoints.nodes.get(nodeKind) ?? new Set();
|
|
847
|
+
for (const type of fileTypes) {
|
|
848
|
+
existing.add(type);
|
|
849
|
+
}
|
|
850
|
+
this.entryPoints.nodes.set(nodeKind, existing);
|
|
851
|
+
}
|
|
852
|
+
this.entryPoints.files.push(...files);
|
|
686
853
|
}
|
|
687
854
|
}
|
|
688
855
|
prepend(...plugins) {
|
|
689
|
-
|
|
856
|
+
const newMap = new Map();
|
|
857
|
+
for (const plugin of plugins) {
|
|
858
|
+
const name = plugin.getName();
|
|
859
|
+
newMap.set(name, Plugins.createEntry(plugin));
|
|
860
|
+
this.plugins.delete(name);
|
|
861
|
+
}
|
|
862
|
+
for (const [name, entry] of this.plugins.entries()) {
|
|
863
|
+
newMap.set(name, entry);
|
|
864
|
+
}
|
|
865
|
+
this.plugins = newMap;
|
|
866
|
+
this.reload();
|
|
690
867
|
}
|
|
691
868
|
append(...plugins) {
|
|
692
|
-
|
|
869
|
+
for (const plugin of plugins) {
|
|
870
|
+
const name = plugin.getName();
|
|
871
|
+
this.plugins.delete(name);
|
|
872
|
+
this.plugins.set(name, Plugins.createEntry(plugin));
|
|
873
|
+
}
|
|
874
|
+
this.reload();
|
|
875
|
+
}
|
|
876
|
+
getShapeCountPerPlugin() {
|
|
877
|
+
return [...this.plugins.entries()].map(([name, { shapeCount }]) => ({
|
|
878
|
+
plugin: name.replace(/Plugin$/, ''), //Report just the names 'ACL', 'Record', etc for existing metrics compatibility
|
|
879
|
+
count: shapeCount,
|
|
880
|
+
}));
|
|
881
|
+
}
|
|
882
|
+
clearShapeCounts() {
|
|
883
|
+
for (const entry of this.plugins.values()) {
|
|
884
|
+
entry.shapeCount = 0;
|
|
885
|
+
}
|
|
693
886
|
}
|
|
694
887
|
getCoalesceStrategy(table) {
|
|
695
|
-
for (const plugin of this
|
|
888
|
+
for (const plugin of this) {
|
|
696
889
|
const coalesceStrategy = plugin.getCoalesceStrategy(table);
|
|
697
890
|
if (coalesceStrategy) {
|
|
698
891
|
return coalesceStrategy;
|
|
@@ -701,7 +894,7 @@ class Plugins {
|
|
|
701
894
|
return undefined;
|
|
702
895
|
}
|
|
703
896
|
isComposite(table) {
|
|
704
|
-
for (const plugin of this
|
|
897
|
+
for (const plugin of this) {
|
|
705
898
|
if (plugin.isComposite(table)) {
|
|
706
899
|
return true;
|
|
707
900
|
}
|
|
@@ -710,7 +903,7 @@ class Plugins {
|
|
|
710
903
|
}
|
|
711
904
|
getCoalesceTables() {
|
|
712
905
|
const tables = new Set();
|
|
713
|
-
for (const plugin of this
|
|
906
|
+
for (const plugin of this) {
|
|
714
907
|
plugin.getCoalesceTables().forEach((t) => {
|
|
715
908
|
tables.add(t);
|
|
716
909
|
});
|
|
@@ -719,27 +912,189 @@ class Plugins {
|
|
|
719
912
|
}
|
|
720
913
|
getReferenceColumns(table) {
|
|
721
914
|
const refColumnEntries = [];
|
|
722
|
-
for (const plugin of this
|
|
915
|
+
for (const plugin of this) {
|
|
723
916
|
refColumnEntries.push(...Object.entries(plugin.getReferenceColumns(table)));
|
|
724
917
|
}
|
|
725
918
|
return Object.fromEntries(refColumnEntries);
|
|
726
919
|
}
|
|
727
920
|
async isEntryPoint(pathOrNode, context) {
|
|
728
|
-
|
|
729
|
-
|
|
921
|
+
if (typescript_1.ts.Node.isNode(pathOrNode)) {
|
|
922
|
+
const fileTypes = this.entryPoints.nodes.get((0, typescript_1.getKindName)(pathOrNode));
|
|
923
|
+
if (!fileTypes || fileTypes.size <= 0) {
|
|
924
|
+
return false;
|
|
925
|
+
}
|
|
926
|
+
else if (fileTypes.has('*')) {
|
|
730
927
|
return true;
|
|
731
928
|
}
|
|
929
|
+
else {
|
|
930
|
+
return fileTypes.has((0, util_1.getFileType)(pathOrNode.getSourceFile().getFilePath(), context.project));
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
else {
|
|
934
|
+
for (const { plugin, matcher } of this.entryPoints.files) {
|
|
935
|
+
if (matcher instanceof RegExp && matcher.test(pathOrNode)) {
|
|
936
|
+
return true;
|
|
937
|
+
}
|
|
938
|
+
else if (typeof matcher === 'function' && (await matcher(pathOrNode, { ...context, self: plugin }))) {
|
|
939
|
+
return true;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
732
942
|
}
|
|
733
943
|
return false;
|
|
734
944
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
945
|
+
async nodeToShape(node, context, ...plugins) {
|
|
946
|
+
if (plugins.length > 0) {
|
|
947
|
+
// Bypass global cache when requesting specific plugins
|
|
948
|
+
return this.nodeToShape0(node, context, ...plugins);
|
|
949
|
+
}
|
|
950
|
+
// We're not requesting specific plugins, so it's safe to use the global cache
|
|
951
|
+
const cached = this.nodeToShapeCache.get(node.compilerNode);
|
|
952
|
+
if (cached) {
|
|
953
|
+
return cached;
|
|
954
|
+
}
|
|
955
|
+
try {
|
|
956
|
+
const result = await this.nodeToShape0(node, context);
|
|
957
|
+
this.nodeToShapeCache.set(node.compilerNode, result);
|
|
958
|
+
return result;
|
|
959
|
+
}
|
|
960
|
+
catch (e) {
|
|
961
|
+
this.nodeToShapeCache.set(node.compilerNode, FAILURE);
|
|
962
|
+
throw e;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
async nodeToShape0(node, context, ...plugins) {
|
|
966
|
+
for (const entry of plugins.length > 0 ? plugins.map((plugin) => this.get(plugin)) : this.plugins.values()) {
|
|
967
|
+
const cached = entry.nodeToShapeCache.get(node.compilerNode);
|
|
968
|
+
if (cached) {
|
|
969
|
+
if (cached.success) {
|
|
970
|
+
return cached;
|
|
971
|
+
}
|
|
972
|
+
else {
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
for (const config of entry.plugin.getConfig().nodes ?? []) {
|
|
977
|
+
if (config.toShape &&
|
|
978
|
+
(0, typescript_1.getKindName)(node) === config.node &&
|
|
979
|
+
(!config.fileTypes ||
|
|
980
|
+
config.fileTypes.includes((0, util_1.getFileType)(node.getSourceFile().getFilePath(), context.project)))) {
|
|
981
|
+
try {
|
|
982
|
+
const result = setCreator(entry.plugin, await config.toShape.bind(entry.plugin)(node, { ...context, self: entry.plugin }));
|
|
983
|
+
entry.nodeToShapeCache.set(node.compilerNode, result);
|
|
984
|
+
if (result.success) {
|
|
985
|
+
entry.shapeCount++;
|
|
986
|
+
return result;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
catch (error) {
|
|
990
|
+
entry.nodeToShapeCache.set(node.compilerNode, FAILURE);
|
|
991
|
+
context.logger.error(`Plugin "${entry.plugin.getName()}" failed to transform "${node.getKindName()}" node into shape:`, error);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
return FAILURE;
|
|
997
|
+
}
|
|
998
|
+
async shapeToSubclass(shape, context, ...plugins) {
|
|
999
|
+
if (plugins.length > 0) {
|
|
1000
|
+
// Bypass global cache when requesting specific plugins
|
|
1001
|
+
return this.shapeToSubclass0(shape, context, ...plugins);
|
|
1002
|
+
}
|
|
1003
|
+
// We're not requesting specific plugins, so it's safe to use the global cache
|
|
1004
|
+
const cached = this.shapeToSubclassCache.get(shape);
|
|
1005
|
+
if (cached) {
|
|
1006
|
+
return cached;
|
|
1007
|
+
}
|
|
1008
|
+
const subclass = await this.shapeToSubclass0(shape, context);
|
|
1009
|
+
this.shapeToSubclassCache.set(shape, subclass);
|
|
1010
|
+
return subclass;
|
|
1011
|
+
}
|
|
1012
|
+
async shapeToSubclass0(shape, context, ...plugins) {
|
|
1013
|
+
for (const entry of plugins.length > 0 ? plugins.map((plugin) => this.get(plugin)) : this.plugins.values()) {
|
|
1014
|
+
const cached = entry.shapeToSubclassCache.get(shape);
|
|
1015
|
+
if (cached) {
|
|
1016
|
+
if (cached.success) {
|
|
1017
|
+
return cached.value;
|
|
1018
|
+
}
|
|
1019
|
+
else {
|
|
1020
|
+
continue;
|
|
1021
|
+
}
|
|
740
1022
|
}
|
|
741
|
-
|
|
742
|
-
|
|
1023
|
+
for (const config of entry.plugin.getConfig().shapes ?? []) {
|
|
1024
|
+
if (config.toSubclass &&
|
|
1025
|
+
shape.constructor === config.shape &&
|
|
1026
|
+
(!config.fileTypes ||
|
|
1027
|
+
config.fileTypes.includes((0, util_1.getFileType)(shape.getOriginalFilePath(), context.project)))) {
|
|
1028
|
+
try {
|
|
1029
|
+
const result = setCreator(entry.plugin, await config.toSubclass.bind(entry.plugin)(shape, { ...context, self: entry.plugin }));
|
|
1030
|
+
entry.shapeToSubclassCache.set(shape, result);
|
|
1031
|
+
if (result.success) {
|
|
1032
|
+
if (result.value.constructor === config.shape) {
|
|
1033
|
+
throw new Error(`Plugin "${entry.plugin.getName()}" tried to subclass "${config.shape.name}" to an instance of the same class. The result MUST be a subclass.`);
|
|
1034
|
+
}
|
|
1035
|
+
entry.shapeCount++;
|
|
1036
|
+
return await this.shapeToSubclass(result.value, context, ...plugins);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
catch (error) {
|
|
1040
|
+
entry.shapeToSubclassCache.set(shape, FAILURE);
|
|
1041
|
+
context.logger.error(`Plugin "${entry.plugin.getName()}" failed to subclass "${shape.getKind()}" shape:`, error);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
return shape;
|
|
1047
|
+
}
|
|
1048
|
+
async shapeToRecord(shape, context, ...plugins) {
|
|
1049
|
+
if (shape.isRecord()) {
|
|
1050
|
+
return { success: true, value: shape };
|
|
1051
|
+
}
|
|
1052
|
+
if (plugins.length > 0) {
|
|
1053
|
+
// Bypass global cache when requesting specific plugins
|
|
1054
|
+
return this.shapeToRecord0(shape, context, ...plugins);
|
|
1055
|
+
}
|
|
1056
|
+
// We're not requesting specific plugins, so it's safe to use the global cache
|
|
1057
|
+
const cached = this.shapeToRecordCache.get(shape);
|
|
1058
|
+
if (cached) {
|
|
1059
|
+
return cached;
|
|
1060
|
+
}
|
|
1061
|
+
const result = await this.shapeToRecord0(shape, context);
|
|
1062
|
+
this.shapeToRecordCache.set(shape, result);
|
|
1063
|
+
return result;
|
|
1064
|
+
}
|
|
1065
|
+
async shapeToRecord0(shape, context, ...plugins) {
|
|
1066
|
+
for (const entry of plugins.length > 0 ? plugins.map((plugin) => this.get(plugin)) : this.plugins.values()) {
|
|
1067
|
+
const cached = entry.shapeToRecordCache.get(shape);
|
|
1068
|
+
if (cached) {
|
|
1069
|
+
if (cached.success) {
|
|
1070
|
+
return cached;
|
|
1071
|
+
}
|
|
1072
|
+
else {
|
|
1073
|
+
continue;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
for (const config of entry.plugin.getConfig().shapes ?? []) {
|
|
1077
|
+
if (config.toRecord &&
|
|
1078
|
+
shape.is(config.shape) &&
|
|
1079
|
+
(!config.fileTypes ||
|
|
1080
|
+
config.fileTypes.includes((0, util_1.getFileType)(shape.getOriginalFilePath(), context.project)))) {
|
|
1081
|
+
try {
|
|
1082
|
+
const result = setCreator(entry.plugin, await config.toRecord.bind(entry.plugin)(shape, { ...context, self: entry.plugin }));
|
|
1083
|
+
entry.shapeToRecordCache.set(shape, result);
|
|
1084
|
+
if (result.success) {
|
|
1085
|
+
entry.shapeCount++;
|
|
1086
|
+
result.value = mergeOverrideFromShape(shape, mergeSysPolicyFromShape(shape, result.value), context.diagnostics);
|
|
1087
|
+
return result;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
catch (error) {
|
|
1091
|
+
entry.shapeToRecordCache.set(shape, FAILURE);
|
|
1092
|
+
context.logger.error(`Plugin "${entry.plugin.getName()}" failed to transform "${shape.getKind()}" shape into record:`, error);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
return FAILURE;
|
|
743
1098
|
}
|
|
744
1099
|
}
|
|
745
1100
|
exports.Plugins = Plugins;
|