@servicenow/sdk-build-core 3.0.3 → 4.0.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/app.d.ts +25 -0
- package/dist/app.js +8 -0
- package/dist/app.js.map +1 -0
- package/dist/compiler.d.ts +60 -0
- package/dist/compiler.js +320 -0
- package/dist/compiler.js.map +1 -0
- package/dist/compression.d.ts +7 -0
- package/dist/compression.js +79 -0
- package/dist/compression.js.map +1 -0
- package/dist/crypto.d.ts +1 -0
- package/dist/crypto.js +9 -0
- package/dist/crypto.js.map +1 -0
- package/dist/diagnostic.d.ts +41 -0
- package/dist/diagnostic.js +130 -0
- package/dist/diagnostic.js.map +1 -0
- package/dist/{plugins/Diagnostic.d.ts → fluent-diagnostic.d.ts} +3 -2
- package/dist/fluent-diagnostic.js +23 -0
- package/dist/fluent-diagnostic.js.map +1 -0
- package/dist/fluent-directive.d.ts +8 -0
- package/dist/fluent-directive.js +54 -0
- package/dist/fluent-directive.js.map +1 -0
- package/dist/fluent-file.d.ts +5 -0
- package/dist/fluent-file.js +15 -0
- package/dist/fluent-file.js.map +1 -0
- package/dist/formatter.d.ts +11 -0
- package/dist/formatter.js +77 -0
- package/dist/formatter.js.map +1 -0
- package/dist/fs.d.ts +174 -0
- package/dist/fs.js +313 -0
- package/dist/fs.js.map +1 -0
- package/dist/guid.d.ts +2 -0
- package/dist/{GUID.js → guid.js} +3 -6
- package/dist/guid.js.map +1 -0
- package/dist/index.d.ts +19 -5
- package/dist/index.js +19 -5
- package/dist/index.js.map +1 -1
- package/dist/json.d.ts +5 -0
- package/dist/json.js +43 -0
- package/dist/json.js.map +1 -0
- package/dist/keys-registry.d.ts +64 -0
- package/dist/keys-registry.js +339 -0
- package/dist/keys-registry.js.map +1 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.js +17 -0
- package/dist/logger.js.map +1 -0
- package/dist/now-config.d.ts +348 -0
- package/dist/now-config.js +283 -0
- package/dist/now-config.js.map +1 -0
- package/dist/path.d.ts +3 -0
- package/dist/path.js +12 -0
- package/dist/path.js.map +1 -0
- package/dist/plugins/cache.d.ts +20 -0
- package/dist/plugins/cache.js +46 -0
- package/dist/plugins/cache.js.map +1 -0
- package/dist/plugins/context.d.ts +85 -0
- package/dist/plugins/{Context.js → context.js} +1 -1
- package/dist/plugins/context.js.map +1 -0
- package/dist/plugins/database.d.ts +27 -0
- package/dist/plugins/database.js +102 -0
- package/dist/plugins/database.js.map +1 -0
- package/dist/plugins/file.d.ts +10 -0
- package/dist/plugins/{behaviors/Arranger.js → file.js} +1 -1
- package/dist/plugins/file.js.map +1 -0
- package/dist/plugins/index.d.ts +9 -5
- package/dist/plugins/index.js +9 -6
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/plugin.d.ts +478 -0
- package/dist/plugins/plugin.js +533 -0
- package/dist/plugins/plugin.js.map +1 -0
- package/dist/plugins/product.d.ts +15 -0
- package/dist/plugins/product.js +38 -0
- package/dist/plugins/product.js.map +1 -0
- package/dist/plugins/project.d.ts +25 -0
- package/dist/plugins/{behaviors/Generator.js → project.js} +1 -1
- package/dist/plugins/project.js.map +1 -0
- package/dist/plugins/shape.d.ts +424 -0
- package/dist/plugins/shape.js +1181 -0
- package/dist/plugins/shape.js.map +1 -0
- package/dist/plugins/time.d.ts +12 -0
- package/dist/plugins/time.js +84 -0
- package/dist/plugins/time.js.map +1 -0
- package/dist/plugins/usage.d.ts +11 -0
- package/dist/plugins/usage.js +26 -0
- package/dist/plugins/usage.js.map +1 -0
- package/dist/prettier/config-loader.d.ts +13 -0
- package/dist/prettier/config-loader.js +105 -0
- package/dist/prettier/config-loader.js.map +1 -0
- package/dist/telemetry/index.d.ts +25 -0
- package/dist/telemetry/index.js +18 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/typescript.d.ts +293 -0
- package/dist/typescript.js +454 -0
- package/dist/typescript.js.map +1 -0
- package/dist/util/get-file-type.d.ts +2 -0
- package/dist/util/get-file-type.js +13 -0
- package/dist/util/get-file-type.js.map +1 -0
- package/dist/util/index.d.ts +2 -6
- package/dist/util/index.js +2 -6
- package/dist/util/index.js.map +1 -1
- package/dist/util/{Scope.js → is-sn-scope.js} +1 -1
- package/dist/util/is-sn-scope.js.map +1 -0
- package/dist/xml.d.ts +24 -0
- package/dist/xml.js +71 -0
- package/dist/xml.js.map +1 -0
- package/now.config.schema.json +336 -0
- package/package.json +22 -12
- package/src/app.ts +33 -0
- package/src/compiler.ts +384 -0
- package/src/compression.ts +93 -0
- package/src/crypto.ts +5 -0
- package/src/diagnostic.ts +108 -0
- package/src/{plugins/Diagnostic.ts → fluent-diagnostic.ts} +3 -10
- package/src/fluent-directive.ts +63 -0
- package/src/fluent-file.ts +13 -0
- package/src/formatter.ts +58 -0
- package/src/fs.ts +438 -0
- package/src/{GUID.ts → guid.ts} +2 -6
- package/src/index.ts +19 -5
- package/src/json.ts +20 -0
- package/src/keys-registry.ts +384 -0
- package/src/logger.ts +20 -0
- package/src/now-config.ts +337 -0
- package/src/path.ts +9 -0
- package/src/plugins/cache.ts +45 -0
- package/src/plugins/context.ts +93 -0
- package/src/plugins/database.ts +121 -0
- package/src/plugins/file.ts +19 -0
- package/src/plugins/index.ts +9 -5
- package/src/plugins/plugin.ts +995 -0
- package/src/plugins/product.ts +44 -0
- package/src/plugins/project.ts +39 -0
- package/src/plugins/shape.ts +1532 -0
- package/src/plugins/time.ts +108 -0
- package/src/plugins/usage.ts +26 -0
- package/src/prettier/config-loader.ts +130 -0
- package/src/telemetry/index.ts +27 -0
- package/src/typescript.ts +502 -0
- package/src/util/get-file-type.ts +11 -0
- package/src/util/index.ts +2 -6
- package/src/xml.ts +86 -0
- package/dist/GUID.d.ts +0 -2
- package/dist/GUID.js.map +0 -1
- package/dist/IncludePaths.d.ts +0 -25
- package/dist/IncludePaths.js +0 -97
- package/dist/IncludePaths.js.map +0 -1
- package/dist/Keys.d.ts +0 -32
- package/dist/Keys.js +0 -245
- package/dist/Keys.js.map +0 -1
- package/dist/TypeScript.d.ts +0 -5
- package/dist/TypeScript.js +0 -58
- package/dist/TypeScript.js.map +0 -1
- package/dist/XML.d.ts +0 -32
- package/dist/XML.js +0 -83
- package/dist/XML.js.map +0 -1
- package/dist/plugins/Context.d.ts +0 -190
- package/dist/plugins/Context.js.map +0 -1
- package/dist/plugins/Diagnostic.js +0 -28
- package/dist/plugins/Diagnostic.js.map +0 -1
- package/dist/plugins/Plugin.d.ts +0 -175
- package/dist/plugins/Plugin.js +0 -15
- package/dist/plugins/Plugin.js.map +0 -1
- package/dist/plugins/behaviors/Arranger.d.ts +0 -26
- package/dist/plugins/behaviors/Arranger.js.map +0 -1
- package/dist/plugins/behaviors/Composer.d.ts +0 -102
- package/dist/plugins/behaviors/Composer.js +0 -15
- package/dist/plugins/behaviors/Composer.js.map +0 -1
- package/dist/plugins/behaviors/Diagnostics.d.ts +0 -7
- package/dist/plugins/behaviors/Diagnostics.js +0 -3
- package/dist/plugins/behaviors/Diagnostics.js.map +0 -1
- package/dist/plugins/behaviors/Generator.d.ts +0 -21
- package/dist/plugins/behaviors/Generator.js.map +0 -1
- package/dist/plugins/behaviors/OwnedTables.d.ts +0 -6
- package/dist/plugins/behaviors/OwnedTables.js +0 -3
- package/dist/plugins/behaviors/OwnedTables.js.map +0 -1
- package/dist/plugins/behaviors/PostProcessor.d.ts +0 -5
- package/dist/plugins/behaviors/PostProcessor.js +0 -3
- package/dist/plugins/behaviors/PostProcessor.js.map +0 -1
- package/dist/plugins/behaviors/Serializer.d.ts +0 -30
- package/dist/plugins/behaviors/Serializer.js +0 -3
- package/dist/plugins/behaviors/Serializer.js.map +0 -1
- package/dist/plugins/behaviors/Transformer.d.ts +0 -23
- package/dist/plugins/behaviors/Transformer.js +0 -3
- package/dist/plugins/behaviors/Transformer.js.map +0 -1
- package/dist/plugins/behaviors/extractors/Data.d.ts +0 -119
- package/dist/plugins/behaviors/extractors/Data.js +0 -244
- package/dist/plugins/behaviors/extractors/Data.js.map +0 -1
- package/dist/plugins/behaviors/extractors/Extractors.d.ts +0 -63
- package/dist/plugins/behaviors/extractors/Extractors.js +0 -3
- package/dist/plugins/behaviors/extractors/Extractors.js.map +0 -1
- package/dist/plugins/behaviors/extractors/index.d.ts +0 -2
- package/dist/plugins/behaviors/extractors/index.js +0 -19
- package/dist/plugins/behaviors/extractors/index.js.map +0 -1
- package/dist/plugins/behaviors/index.d.ts +0 -9
- package/dist/plugins/behaviors/index.js +0 -26
- package/dist/plugins/behaviors/index.js.map +0 -1
- package/dist/plugins/util/CallExpression.d.ts +0 -5
- package/dist/plugins/util/CallExpression.js +0 -88
- package/dist/plugins/util/CallExpression.js.map +0 -1
- package/dist/plugins/util/CodeTransformation.d.ts +0 -95
- package/dist/plugins/util/CodeTransformation.js +0 -624
- package/dist/plugins/util/CodeTransformation.js.map +0 -1
- package/dist/plugins/util/ObjectLiteral.d.ts +0 -9
- package/dist/plugins/util/ObjectLiteral.js +0 -37
- package/dist/plugins/util/ObjectLiteral.js.map +0 -1
- package/dist/plugins/util/index.d.ts +0 -3
- package/dist/plugins/util/index.js +0 -20
- package/dist/plugins/util/index.js.map +0 -1
- package/dist/util/Debug.d.ts +0 -4
- package/dist/util/Debug.js +0 -20
- package/dist/util/Debug.js.map +0 -1
- package/dist/util/Directive.d.ts +0 -16
- package/dist/util/Directive.js +0 -107
- package/dist/util/Directive.js.map +0 -1
- package/dist/util/RuntimeTableSchema.d.ts +0 -5
- package/dist/util/RuntimeTableSchema.js +0 -58
- package/dist/util/RuntimeTableSchema.js.map +0 -1
- package/dist/util/Scope.js.map +0 -1
- package/dist/util/Util.d.ts +0 -1
- package/dist/util/Util.js +0 -12
- package/dist/util/Util.js.map +0 -1
- package/dist/util/XMLUploadParser.d.ts +0 -22
- package/dist/util/XMLUploadParser.js +0 -67
- package/dist/util/XMLUploadParser.js.map +0 -1
- package/src/IncludePaths.ts +0 -122
- package/src/Keys.ts +0 -274
- package/src/TypeScript.ts +0 -65
- package/src/XML.ts +0 -98
- package/src/plugins/Context.ts +0 -239
- package/src/plugins/Plugin.ts +0 -278
- package/src/plugins/behaviors/Arranger.ts +0 -42
- package/src/plugins/behaviors/Composer.ts +0 -125
- package/src/plugins/behaviors/Diagnostics.ts +0 -12
- package/src/plugins/behaviors/Generator.ts +0 -31
- package/src/plugins/behaviors/OwnedTables.ts +0 -5
- package/src/plugins/behaviors/PostProcessor.ts +0 -6
- package/src/plugins/behaviors/Serializer.ts +0 -40
- package/src/plugins/behaviors/Transformer.ts +0 -32
- package/src/plugins/behaviors/extractors/Data.ts +0 -332
- package/src/plugins/behaviors/extractors/Extractors.ts +0 -73
- package/src/plugins/behaviors/extractors/index.ts +0 -2
- package/src/plugins/behaviors/index.ts +0 -9
- package/src/plugins/util/CallExpression.ts +0 -110
- package/src/plugins/util/CodeTransformation.ts +0 -731
- package/src/plugins/util/ObjectLiteral.ts +0 -37
- package/src/plugins/util/index.ts +0 -3
- package/src/util/Debug.ts +0 -24
- package/src/util/Directive.ts +0 -123
- package/src/util/RuntimeTableSchema.ts +0 -44
- package/src/util/Util.ts +0 -7
- package/src/util/XMLUploadParser.ts +0 -90
- /package/dist/util/{Scope.d.ts → is-sn-scope.d.ts} +0 -0
- /package/src/util/{Scope.ts → is-sn-scope.ts} +0 -0
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
import { type SupportedKindName, type SupportedNode, type SupportedNodeByKindName, ts } from '../typescript';
|
|
2
|
+
import { type ObjectShape, type Record, type Shape, type ShapeClass, type StringShape } from './shape';
|
|
3
|
+
import type { File, OutputFile } from './file';
|
|
4
|
+
import { Database } from './database';
|
|
5
|
+
import type { Context as BaseContext } from './context';
|
|
6
|
+
type Context = Omit<BaseContext, 'keys'>;
|
|
7
|
+
export type Result<Value = unknown> = {
|
|
8
|
+
success: false;
|
|
9
|
+
} | {
|
|
10
|
+
success: true;
|
|
11
|
+
value: Value;
|
|
12
|
+
};
|
|
13
|
+
export type CommitResult = {
|
|
14
|
+
success: boolean;
|
|
15
|
+
};
|
|
16
|
+
export type CommitFunction = (shape: Shape, target: ts.Node, ...plugins: Plugin[]) => Promise<void>;
|
|
17
|
+
export type CommitContext = Context & {
|
|
18
|
+
commit: CommitFunction;
|
|
19
|
+
};
|
|
20
|
+
export type RecordContext = Context & {
|
|
21
|
+
readonly database: Database;
|
|
22
|
+
readonly descendants: Database;
|
|
23
|
+
};
|
|
24
|
+
export type Relationships = {
|
|
25
|
+
[table: string]: Relationship;
|
|
26
|
+
};
|
|
27
|
+
export type Relationship = {
|
|
28
|
+
/**
|
|
29
|
+
* Specifies how the tables are related:
|
|
30
|
+
*
|
|
31
|
+
* - String: Name of the reference field on the child table pointing to the parent (or
|
|
32
|
+
* vice versa for inverse relationships)
|
|
33
|
+
* - Object: Key-value pairs where keys are column names on the child table and values
|
|
34
|
+
* are the matching column names on the parent table (or vice versa for inverse
|
|
35
|
+
* relationships)
|
|
36
|
+
* - Function: Takes the parent and child records as arguments and returns a boolean to
|
|
37
|
+
* indicate whether the records are related or not (WARNING: Do not use this
|
|
38
|
+
* unless absolutely necessary as it can negatively impact performance)
|
|
39
|
+
*/
|
|
40
|
+
via: string | {
|
|
41
|
+
[column: string]: string;
|
|
42
|
+
} | ((parent: Record, child: Record) => boolean);
|
|
43
|
+
/**
|
|
44
|
+
* When true, the relationship direction is reversed - the parent references the child
|
|
45
|
+
* instead of the child referencing the parent
|
|
46
|
+
*/
|
|
47
|
+
inverse?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* When true, the related record is considered part of the same logical entity as its
|
|
50
|
+
* parent. These records should be processed together as a unit.
|
|
51
|
+
*/
|
|
52
|
+
descendant?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Nested relationships that define how this table relates to other tables
|
|
55
|
+
*/
|
|
56
|
+
relationships?: Relationships;
|
|
57
|
+
};
|
|
58
|
+
export type CoalesceStrategy = [string, ...string[]] | ((properties: ObjectShape) => globalThis.Record<string, string | StringShape> | ObjectShape);
|
|
59
|
+
export type FileType = 'fluent' | 'module' | 'json' | 'unknown';
|
|
60
|
+
export type PluginConfig<Nodes extends SupportedKindName[] = SupportedKindName[], Shapes extends ShapeClass[] = ShapeClass[], Records extends string[] = string[]> = {
|
|
61
|
+
/**
|
|
62
|
+
* The name of the plugin. Must end with "Plugin" suffix. This name is used in metrics
|
|
63
|
+
* and error messages.
|
|
64
|
+
*/
|
|
65
|
+
name: `${string}Plugin`;
|
|
66
|
+
/**
|
|
67
|
+
* The TypeScript AST nodes this plugin handles. Plugins that do not introduce new
|
|
68
|
+
* syntax should not need to define any handlers here.
|
|
69
|
+
*/
|
|
70
|
+
nodes?: {
|
|
71
|
+
[I in keyof Nodes]: {
|
|
72
|
+
/**
|
|
73
|
+
* The TypeScript node kind to handle. Must be one of the hard-coded set
|
|
74
|
+
* of supported kinds in the Fluent DSL.
|
|
75
|
+
*/
|
|
76
|
+
node: Nodes[I];
|
|
77
|
+
/**
|
|
78
|
+
* File types this handler should run on. These are based on the file
|
|
79
|
+
* extension. If not specified, it runs on all file types.
|
|
80
|
+
*/
|
|
81
|
+
fileTypes?: FileType[];
|
|
82
|
+
/**
|
|
83
|
+
* Indicates whether this node should be parsed as an entry point during
|
|
84
|
+
* the top-level AST traversal to produce output. (Default: false)
|
|
85
|
+
*/
|
|
86
|
+
entryPoint?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Converts a TypeScript node to a shape.
|
|
89
|
+
*
|
|
90
|
+
* This is the initial transformation step when processing source code.
|
|
91
|
+
* The function receives a TypeScript node of the specified kind and
|
|
92
|
+
* returns a shape derived from it. That shape can then be handled later
|
|
93
|
+
* by shape transforms defined in this plugin or some other plugin.
|
|
94
|
+
*
|
|
95
|
+
* @param node - The TypeScript node to transform
|
|
96
|
+
* @param context - Context object with useful services and information
|
|
97
|
+
* @returns A result indicating whether the transformation was successful
|
|
98
|
+
* and, if so, the resulting shape
|
|
99
|
+
*/
|
|
100
|
+
toShape?(node: SupportedNodeByKindName<Nodes[I]>, context: Context): Result<Shape> | Promise<Result<Shape>>;
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* The shapes this plugin handles. Each shape handler can implement the following:
|
|
105
|
+
*
|
|
106
|
+
* - Transform functions that turn shapes into records (toRecord)
|
|
107
|
+
* - Transform functions that turn shapes into more specialized subclasses of those shapes (toSubclass)
|
|
108
|
+
* - Commit functions that mutate TypeScript nodes to match shapes (commit)
|
|
109
|
+
* - Inspect functions that can examine shapes for diagnostic purposes (inspect)
|
|
110
|
+
*/
|
|
111
|
+
shapes?: {
|
|
112
|
+
[I in keyof Shapes]: Shapes[I] extends ShapeClass<infer S> ? {
|
|
113
|
+
/**
|
|
114
|
+
* The shape class to handle.
|
|
115
|
+
*/
|
|
116
|
+
shape: Shapes[I];
|
|
117
|
+
/**
|
|
118
|
+
* File types this handler should run on. These are based on the file
|
|
119
|
+
* extension. If not specified, it runs on all file types.
|
|
120
|
+
*/
|
|
121
|
+
fileTypes?: FileType[];
|
|
122
|
+
/**
|
|
123
|
+
* Inspects a shape. Useful for validating the details of a shape created
|
|
124
|
+
* by another plugin and producing diagnostics.
|
|
125
|
+
*
|
|
126
|
+
* @param shape - The shape to inspect
|
|
127
|
+
* @param context - Context object with useful services and information
|
|
128
|
+
*/
|
|
129
|
+
inspect?(shape: S, context: Context): void;
|
|
130
|
+
/**
|
|
131
|
+
* Transforms a shape into a more specific subclass. Plugins that introduce
|
|
132
|
+
* a shape which extends another shape should implement this. For example,
|
|
133
|
+
* many plugins implement support for entities based on call expressions,
|
|
134
|
+
* and therefore handle CallExpressionShape. Creating a subclass of that
|
|
135
|
+
* shape allows plugins to more easily handle their use case.
|
|
136
|
+
*
|
|
137
|
+
* NOTE: The shape returned by this function MUST be a subclass of the input
|
|
138
|
+
* shape. If it is not, an error will be thrown at runtime.
|
|
139
|
+
*
|
|
140
|
+
* @param shape - The shape to transform
|
|
141
|
+
* @param context - Context object with useful services and information
|
|
142
|
+
* @returns A result indicating whether the transformation was successful
|
|
143
|
+
* and, if so, an instance of the subclass
|
|
144
|
+
*/
|
|
145
|
+
toSubclass?(shape: S, context: Context): Result<S>;
|
|
146
|
+
/**
|
|
147
|
+
* Transforms a shape into a record. Almost all plugins should implement
|
|
148
|
+
* this, as it is the fundamental transformation step in the process of
|
|
149
|
+
* turning Fluent code into ServiceNow records. These records will then
|
|
150
|
+
* be serialized into XML as part of a build, or merged with incoming
|
|
151
|
+
* records as part of bidirectional sync.
|
|
152
|
+
*
|
|
153
|
+
* @param shape - The shape to transform
|
|
154
|
+
* @param context - Context object with useful services and information
|
|
155
|
+
* @returns A result indicating whether the transformation was successful
|
|
156
|
+
* and, if so, the resulting record(s)
|
|
157
|
+
*/
|
|
158
|
+
toRecord?(shape: S, context: Context): Result<Record> | Promise<Result<Record>>;
|
|
159
|
+
/**
|
|
160
|
+
* Mutates a target TypeScript node to match a given shape. Plugins that
|
|
161
|
+
* do not introduce new syntax should not need to implement this.
|
|
162
|
+
*
|
|
163
|
+
* NOTE: It is CRUCIAL that the commit function does not apply any changes
|
|
164
|
+
* to the target node other than what is absolutely necessary to match
|
|
165
|
+
* the shape. They should be "minimally invasive", preserving as much
|
|
166
|
+
* as possible of the original code, including comments and whitespace.
|
|
167
|
+
* Care must be taken to check if parts of the existing code are
|
|
168
|
+
* functionally equivalent to the incoming shape, even if they are not
|
|
169
|
+
* exactly the same.
|
|
170
|
+
*
|
|
171
|
+
* @param shape - The shape to commit
|
|
172
|
+
* @param target - The target TypeScript node to modify
|
|
173
|
+
* @param context - Context with useful services and information
|
|
174
|
+
* @returns A result indicating whether the commit was successful
|
|
175
|
+
*/
|
|
176
|
+
commit?(shape: S, target: ts.Node, context: CommitContext): CommitResult | Promise<CommitResult>;
|
|
177
|
+
} : never;
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* The records this plugin handles. The keys of this object are the names of the tables to be
|
|
181
|
+
* handled, and the values are handlers which can implement the following:
|
|
182
|
+
*
|
|
183
|
+
* - Transform functions that turn records into shapes (toShape)
|
|
184
|
+
* - Transform functions that turn records into files (toFile)
|
|
185
|
+
* - Relationship mappings
|
|
186
|
+
* - Coalesce strategies
|
|
187
|
+
*/
|
|
188
|
+
records?: {
|
|
189
|
+
[T in Records[number]]: {
|
|
190
|
+
/**
|
|
191
|
+
* Columns that compose the coalesce strategy for this table. If there is a strategy defined in
|
|
192
|
+
* the platform for this table, you must make sure this configuration matches it. If there isn't
|
|
193
|
+
* one defined in the platform, you can decide to either create a suitable one here or leave it
|
|
194
|
+
* undefined. Tables without coalesce strategies will rely on their GUIDs to determine identity.
|
|
195
|
+
*
|
|
196
|
+
* For advanced use cases where simple column-based coalesce strategies cannot be used, you may
|
|
197
|
+
* define a dynamic coalesce strategy by supplying a function that accepts the properties of a
|
|
198
|
+
* record and returns an object with the desired coalesce keys.
|
|
199
|
+
*
|
|
200
|
+
* Refer to CoalesceStrategies.java to find platform-defined coalesce strategies:
|
|
201
|
+
* https://code.devsnc.com/dev/glide/blob/master/glide/src/com/glide/script/coalesce/CoalesceStrategies.java
|
|
202
|
+
*/
|
|
203
|
+
coalesce?: CoalesceStrategy;
|
|
204
|
+
/**
|
|
205
|
+
* You can think of the relationship between two tables as a parent-child relationship. Usually,
|
|
206
|
+
* the child references the parent via a foreign key. For example, sys_security_acl_role (child)
|
|
207
|
+
* references sys_security_acl (parent) via a reference column. This is the most basic type of
|
|
208
|
+
* relationship. In this case, the ACL plugin should handle the parent record and the children
|
|
209
|
+
* as part of the same entity. That's because the full definition of an ACL includes both the
|
|
210
|
+
* top-level sys_security_acl record AND the sys_security_acl_role M2M records which link it to
|
|
211
|
+
* its roles. This type of relationship, where a child record is part of a singular entity with
|
|
212
|
+
* its parent, is called a "descendant" relationship.
|
|
213
|
+
*
|
|
214
|
+
* sys_security_acl <- sys_security_acl_role (descendant relationship)
|
|
215
|
+
*
|
|
216
|
+
* Sometimes, relationships are the other way around, where the parent references the child. To
|
|
217
|
+
* continue the ACL example, sys_security_acl_role (parent) references sys_user_role (child) via
|
|
218
|
+
* a reference column. This is called an "inverse" relationship because it goes parent -> child
|
|
219
|
+
* instead of child -> parent. However, this would NOT be considered a "descendant" relationship
|
|
220
|
+
* because the role itself is not part of the ACL definition. The ACL and the role are related,
|
|
221
|
+
* but the role itself is its own separate entity.
|
|
222
|
+
*
|
|
223
|
+
* sys_security_acl_role <- sys_user_role (inverse non-descendant relationship)
|
|
224
|
+
*
|
|
225
|
+
* So far we've only explored relationships based on foreign keys (reference columns). In these
|
|
226
|
+
* cases your "via" would simply be the name of the reference column that connects them, either
|
|
227
|
+
* on the child table (normal relationship) or the parent (inverse relationship). However, it's
|
|
228
|
+
* also possible for two tables to be related by matching the values from one or more columns on
|
|
229
|
+
* both tables. For example, sys_db_object (parent) and sys_dictionary (child) are related by
|
|
230
|
+
* matching the "name" columns from each table. In other words, if a sys_db_object record has a
|
|
231
|
+
* value of "incident" in its "name" column, then any sys_dictionary records that also have the
|
|
232
|
+
* value "incident" in their "name" columns are its children. These children are also considered
|
|
233
|
+
* "descendants" because they are all part of the same table entity. In these cases, your "via"
|
|
234
|
+
* would be represented as key-value pairs instead of a single column name. The keys should be
|
|
235
|
+
* the names of columns on the child table, and the values should be the names of columns that
|
|
236
|
+
* should be matched on the parent table. (For "inverse" relationships, the key-value pairs are
|
|
237
|
+
* flipped.)
|
|
238
|
+
*
|
|
239
|
+
* sys_db_object <- sys_dictionary (descendant relationship by matching "name":"name")
|
|
240
|
+
*/
|
|
241
|
+
relationships?: Relationships;
|
|
242
|
+
/**
|
|
243
|
+
* Transforms a record into a shape. Almost all plugins should implement this, as it is
|
|
244
|
+
* the fundamental transformation step in the process of turning ServiceNow records into
|
|
245
|
+
* Fluent code, or bidirectionally syncing changes to existing Fluent code.
|
|
246
|
+
*
|
|
247
|
+
* @param record - The record to transform
|
|
248
|
+
* @param context - Context with useful services and information
|
|
249
|
+
* @returns A result indicating whether the transformation was successful and, if so, the
|
|
250
|
+
* resulting shape
|
|
251
|
+
*/
|
|
252
|
+
toShape?(record: Record, context: RecordContext): Result<Shape> | Promise<Result<Shape>>;
|
|
253
|
+
/**
|
|
254
|
+
* Transforms a database record into output file(s). Plugins should only implement this
|
|
255
|
+
* if the records they handle must be serialized to some specialized non-standard format.
|
|
256
|
+
* Records that follow the usual ServiceNow format do NOT need to be handled here. This
|
|
257
|
+
* transformation is the last step in the build process.
|
|
258
|
+
*
|
|
259
|
+
* @param record - The record to transform
|
|
260
|
+
* @param context - Context with useful services and information
|
|
261
|
+
* @returns A result indicating whether the transformation was successful and, if so, the
|
|
262
|
+
* resulting output file(s)
|
|
263
|
+
*/
|
|
264
|
+
toFile?(record: Record, context: RecordContext): Result<OutputFile | OutputFile[]> | Promise<Result<OutputFile | OutputFile[]>>;
|
|
265
|
+
};
|
|
266
|
+
};
|
|
267
|
+
/**
|
|
268
|
+
* The files this plugin handles. Plugins that do not introduce new file types should not
|
|
269
|
+
* need to implement anything here.
|
|
270
|
+
*/
|
|
271
|
+
files?: {
|
|
272
|
+
/**
|
|
273
|
+
* A regex pattern or predicate to apply to a file's path to determine if it should be handled by this plugin.
|
|
274
|
+
*/
|
|
275
|
+
matcher?: RegExp | ((path: string, context: Context) => boolean | Promise<boolean>);
|
|
276
|
+
/**
|
|
277
|
+
* Indicates whether this file should be parsed as an entry point when generating output. (Default: false)
|
|
278
|
+
*/
|
|
279
|
+
entryPoint?: boolean;
|
|
280
|
+
/**
|
|
281
|
+
* Transforms a file into record(s).
|
|
282
|
+
*
|
|
283
|
+
* @param file - The file to transform
|
|
284
|
+
* @param context - Context object with useful services and information
|
|
285
|
+
* @returns A result indicating whether the transformation was successful and, if so, the
|
|
286
|
+
* resulting record(s)
|
|
287
|
+
*/
|
|
288
|
+
toRecord?(file: File, context: Context): Result<Record> | Promise<Result<Record>>;
|
|
289
|
+
}[];
|
|
290
|
+
};
|
|
291
|
+
type SearchableRelationships = {
|
|
292
|
+
[table: string]: Relationships;
|
|
293
|
+
};
|
|
294
|
+
export declare class Plugin {
|
|
295
|
+
private readonly config;
|
|
296
|
+
private readonly nodeToShapeCache;
|
|
297
|
+
private readonly shapeToSubclassCache;
|
|
298
|
+
private readonly shapeToRecordCache;
|
|
299
|
+
private readonly relationships;
|
|
300
|
+
private readonly references;
|
|
301
|
+
private constructor();
|
|
302
|
+
private parseRelationships;
|
|
303
|
+
/**
|
|
304
|
+
* Creates a new Fluent plugin from the provided configuration.
|
|
305
|
+
*
|
|
306
|
+
* Plugins are the primary mechanism for extending the Fluent DSL and providing support for
|
|
307
|
+
* new types of ServiceNow entities. Plugins implement handlers responsible for parsing and
|
|
308
|
+
* transforming Fluent code, ServiceNow records, and any other files that exist within a
|
|
309
|
+
* Fluent project.
|
|
310
|
+
*
|
|
311
|
+
* The build system orchestrates the plugins together to carry a project through all the
|
|
312
|
+
* stages of building and bidirectionally syncing a Fluent project, invoking each plugin's
|
|
313
|
+
* handlers at the appropriate points in the process, and providing the relevant inputs and
|
|
314
|
+
* context.
|
|
315
|
+
*
|
|
316
|
+
* During a regular build, the stages are:
|
|
317
|
+
*
|
|
318
|
+
* 1. Traverse the full AST of all the Fluent code, transforming each node into a shape
|
|
319
|
+
* 2. Transform each shape into a more specific subclass of that shape
|
|
320
|
+
* 3. Transform each subclassed shape into one or more ServiceNow records
|
|
321
|
+
* 4. Serialize each record into an output file
|
|
322
|
+
*
|
|
323
|
+
* During bidirectional sync, the stages are:
|
|
324
|
+
*
|
|
325
|
+
* 1. Perform stage 1 from the regular build process to get the existing shapes
|
|
326
|
+
* 2. Perform stage 2 from the regular build process to subclass those existing shapes
|
|
327
|
+
* 3. Perform stage 3 from the regular build process to get the existing records
|
|
328
|
+
* 4. Parse input files (usually XML from a ServiceNow instance) to get the incoming records
|
|
329
|
+
* 5. Merge the incoming records into the existing records so that all changes are reflected
|
|
330
|
+
* 6. Transform each merged record into a shape
|
|
331
|
+
* 7. Commit each shape to the Fluent AST, generating new nodes as needed
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* // Stages of a regular build
|
|
335
|
+
* const CoolPlugin = Plugin.create({
|
|
336
|
+
* name: 'CoolPlugin',
|
|
337
|
+
* nodes: [
|
|
338
|
+
* {
|
|
339
|
+
* node: 'CallExpression',
|
|
340
|
+
* toShape(node) {
|
|
341
|
+
* // BUILD STAGE 1: A CallExpression node is transformed into a CallExpressionShape.
|
|
342
|
+
* }
|
|
343
|
+
* }
|
|
344
|
+
* ],
|
|
345
|
+
* shapes: [
|
|
346
|
+
* {
|
|
347
|
+
* shape: CallExpressionShape,
|
|
348
|
+
* toSubclass(shape) {
|
|
349
|
+
* // BUILD STAGE 2: The CallExpressionShape from stage 1 is transformed into a CoolShape.
|
|
350
|
+
* }
|
|
351
|
+
* },
|
|
352
|
+
* {
|
|
353
|
+
* shape: CoolShape,
|
|
354
|
+
* toRecord(shape) {
|
|
355
|
+
* // BUILD STAGE 3: The CoolShape from stage 2 is transformed into a cool_table record.
|
|
356
|
+
* }
|
|
357
|
+
* }
|
|
358
|
+
* ],
|
|
359
|
+
* records: {
|
|
360
|
+
* cool_table: {
|
|
361
|
+
* toFile(record) {
|
|
362
|
+
* // BUILD STAGE 4: The cool_table record from stage 3 is serialized into an output file.
|
|
363
|
+
* }
|
|
364
|
+
* }
|
|
365
|
+
* },
|
|
366
|
+
* })
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* // Stages of bidirectional sync
|
|
370
|
+
* const CoolPlugin = Plugin.create({
|
|
371
|
+
* name: 'CoolPlugin',
|
|
372
|
+
* nodes: [
|
|
373
|
+
* {
|
|
374
|
+
* node: 'CallExpression',
|
|
375
|
+
* toShape(node) {
|
|
376
|
+
* // SYNC STAGE 1: An existing CallExpression node is transformed into a CallExpressionShape.
|
|
377
|
+
* }
|
|
378
|
+
* }
|
|
379
|
+
* ],
|
|
380
|
+
* shapes: [
|
|
381
|
+
* {
|
|
382
|
+
* shape: CallExpressionShape,
|
|
383
|
+
* toSubclass(shape) {
|
|
384
|
+
* // SYNC STAGE 2: The existing CallExpressionShape from stage 1 is transformed into a CoolShape
|
|
385
|
+
* },
|
|
386
|
+
* commit(shape, target) {
|
|
387
|
+
* // SYNC STAGE 7: The new CoolShape from stage 6, which now contains the changes from the
|
|
388
|
+
* // incoming cool_table record, is committed to the original CallExpression node.
|
|
389
|
+
* //
|
|
390
|
+
* // NOTES:
|
|
391
|
+
* // - Since CoolShape extends CallExpressionShape, and there is no commit function
|
|
392
|
+
* // for CoolShape, this commit function is used. If, for some reason, CoolShape
|
|
393
|
+
* // needed to be committed differently than other CallExpressionShapes, then this
|
|
394
|
+
* // plugin would need to implement a commit function for CoolShape.
|
|
395
|
+
* // - If the incoming cool_table record didn't already exist in the code, then the
|
|
396
|
+
* // build system would generate an arbitrary new node before passing it into this
|
|
397
|
+
* // commit function as the target. So the implementation should never assume that
|
|
398
|
+
* // the target is a CallExpression node.
|
|
399
|
+
* }
|
|
400
|
+
* },
|
|
401
|
+
* {
|
|
402
|
+
* shape: CoolShape,
|
|
403
|
+
* toRecord(shape) {
|
|
404
|
+
* // SYNC STAGE 3: The existing CoolShape from stage 2 is transformed into a cool_table record.
|
|
405
|
+
* }
|
|
406
|
+
* }
|
|
407
|
+
* ],
|
|
408
|
+
* files: [
|
|
409
|
+
* {
|
|
410
|
+
* extension: 'xml',
|
|
411
|
+
* toRecord(file) {
|
|
412
|
+
* // SYNC STAGE 4: An incoming XML file with changes is parsed into a cool_table record.
|
|
413
|
+
* }
|
|
414
|
+
* }
|
|
415
|
+
* ],
|
|
416
|
+
* records: {
|
|
417
|
+
* cool_table: {
|
|
418
|
+
* toShape(record) {
|
|
419
|
+
* // SYNC STAGE 6: After the incoming cool_table record from stage 4 is merged into the
|
|
420
|
+
* // existing one from stage 3, the merged record is transformed back into a CoolShape.
|
|
421
|
+
* }
|
|
422
|
+
* }
|
|
423
|
+
* },
|
|
424
|
+
* })
|
|
425
|
+
*/
|
|
426
|
+
static create<const N extends SupportedKindName[], const S extends ShapeClass[]>(config: PluginConfig<N, S>): Plugin;
|
|
427
|
+
getName(): string;
|
|
428
|
+
getDescendants(parent: Record, database: Database): Record[];
|
|
429
|
+
getCoalesceStrategy(table: string): CoalesceStrategy | undefined;
|
|
430
|
+
getCoalesceTables(): string[];
|
|
431
|
+
getTables(relationships?: Relationships, tables?: string[]): Set<string>;
|
|
432
|
+
getReferenceColumns(table: string): {
|
|
433
|
+
[column: string]: string;
|
|
434
|
+
};
|
|
435
|
+
getRelationships(): SearchableRelationships;
|
|
436
|
+
flushCache(): void;
|
|
437
|
+
nodeToShape(node: SupportedNode, context: Omit<Context, 'self'>): Promise<Result<Shape>>;
|
|
438
|
+
commit(shape: Shape, target: ts.Node, context: Omit<CommitContext, 'self'>): Promise<CommitResult>;
|
|
439
|
+
shapeToSubclass<const S extends Shape>(shape: S, context: Omit<Context, 'self'>): Result<S>;
|
|
440
|
+
shapeToRecord(shape: Shape, context: Omit<Context, 'self'>): Promise<Result<Record>>;
|
|
441
|
+
private recordToShape0;
|
|
442
|
+
recordToShape({ record, database, context, }: {
|
|
443
|
+
record: Record;
|
|
444
|
+
database: Database;
|
|
445
|
+
context: Omit<Context, 'self'>;
|
|
446
|
+
}): Promise<Result<Shape>>;
|
|
447
|
+
recordsToShapes({ database, creatorOnly, changedOnly, mode, handledRecords, context, }: {
|
|
448
|
+
database: Database;
|
|
449
|
+
creatorOnly: boolean;
|
|
450
|
+
changedOnly?: boolean;
|
|
451
|
+
mode: 'explicit' | 'catch-all';
|
|
452
|
+
handledRecords: Database;
|
|
453
|
+
context: Omit<Context, 'self'>;
|
|
454
|
+
}): Promise<Result<Shape[]>>;
|
|
455
|
+
recordToFile(record: Record, context: Omit<RecordContext, 'self'>): Promise<Result<OutputFile | OutputFile[]>>;
|
|
456
|
+
recordsToFiles({ database, mode, handledGuids, context, }: {
|
|
457
|
+
database: Database;
|
|
458
|
+
mode: 'explicit' | 'catch-all';
|
|
459
|
+
handledGuids: Set<string>;
|
|
460
|
+
context: Omit<Context, 'self'>;
|
|
461
|
+
}): Promise<Result<OutputFile[]>>;
|
|
462
|
+
isEntryPoint(pathOrNode: string | SupportedNode, context: Omit<Context, 'self'>): Promise<boolean>;
|
|
463
|
+
fileToRecord(file: File, context: Omit<Context, 'self'>): Promise<Result<Record>>;
|
|
464
|
+
inspect(shape: Shape, context: Context): void;
|
|
465
|
+
}
|
|
466
|
+
export declare class Plugins {
|
|
467
|
+
private readonly plugins;
|
|
468
|
+
constructor(plugins: Plugin[]);
|
|
469
|
+
toArray(): Plugin[];
|
|
470
|
+
add(plugin: Plugin): void;
|
|
471
|
+
getCoalesceStrategy(table: string): CoalesceStrategy | undefined;
|
|
472
|
+
getCoalesceTables(): Set<string>;
|
|
473
|
+
getReferenceColumns(table: string): {
|
|
474
|
+
[column: string]: string;
|
|
475
|
+
};
|
|
476
|
+
isEntryPoint(pathOrNode: string | SupportedNode, context: Omit<Context, 'self'>): Promise<boolean>;
|
|
477
|
+
}
|
|
478
|
+
export {};
|