@servicenow/sdk-build-core 4.2.0 → 4.4.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 +14 -2
- package/dist/compiler.js +120 -8
- package/dist/compiler.js.map +1 -1
- package/dist/compression.d.ts +2 -2
- package/dist/compression.js +4 -1
- package/dist/compression.js.map +1 -1
- package/dist/now-config-dependencies.d.ts +2 -1
- package/dist/now-config.d.ts +10 -5
- package/dist/now-config.js +6 -5
- package/dist/now-config.js.map +1 -1
- package/dist/plugins/cache.d.ts +8 -13
- package/dist/plugins/cache.js +2 -26
- package/dist/plugins/cache.js.map +1 -1
- package/dist/plugins/data-shape.d.ts +24 -33
- package/dist/plugins/data-shape.js +83 -73
- package/dist/plugins/data-shape.js.map +1 -1
- package/dist/plugins/plugin.d.ts +43 -1
- package/dist/plugins/plugin.js +49 -5
- package/dist/plugins/plugin.js.map +1 -1
- package/dist/plugins/shape.d.ts +19 -11
- package/dist/plugins/shape.js +61 -23
- package/dist/plugins/shape.js.map +1 -1
- package/dist/taxonomy.js +53 -1
- package/dist/taxonomy.js.map +1 -1
- package/dist/telemetry/clients/abstract-client.d.ts +25 -0
- package/dist/telemetry/clients/abstract-client.js +55 -0
- package/dist/telemetry/clients/abstract-client.js.map +1 -0
- package/dist/telemetry/clients/browser-client.d.ts +20 -0
- package/dist/telemetry/clients/browser-client.js +136 -0
- package/dist/telemetry/clients/browser-client.js.map +1 -0
- package/dist/telemetry/clients/node-client.d.ts +15 -0
- package/dist/telemetry/clients/node-client.js +159 -0
- package/dist/telemetry/clients/node-client.js.map +1 -0
- package/dist/telemetry/clients/noop-client.d.ts +10 -0
- package/dist/telemetry/clients/noop-client.js +18 -0
- package/dist/telemetry/clients/noop-client.js.map +1 -0
- package/dist/telemetry/clients/util.d.ts +11 -0
- package/dist/telemetry/clients/util.js +34 -0
- package/dist/telemetry/clients/util.js.map +1 -0
- package/dist/telemetry/config.d.ts +2 -0
- package/dist/telemetry/config.js +28 -0
- package/dist/telemetry/config.js.map +1 -0
- package/dist/telemetry/factory.d.ts +13 -0
- package/dist/telemetry/factory.js +29 -0
- package/dist/telemetry/factory.js.map +1 -0
- package/dist/telemetry/index.d.ts +2 -25
- package/dist/telemetry/index.js +3 -15
- package/dist/telemetry/index.js.map +1 -1
- package/dist/telemetry/types.d.ts +55 -0
- package/dist/telemetry/types.js +12 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/typescript.d.ts +10 -0
- package/dist/typescript.js +18 -0
- package/dist/typescript.js.map +1 -1
- package/dist/util/delete-multiple.d.ts +5 -0
- package/dist/util/delete-multiple.js +30 -0
- package/dist/util/delete-multiple.js.map +1 -0
- package/dist/util/index.d.ts +1 -0
- package/dist/util/index.js +1 -0
- package/dist/util/index.js.map +1 -1
- package/now.config.schema.json +40 -5
- package/package.json +13 -9
- package/src/compiler.ts +140 -7
- package/src/compression.ts +2 -2
- package/src/now-config-dependencies.ts +2 -1
- package/src/now-config.ts +8 -6
- package/src/plugins/cache.ts +5 -27
- package/src/plugins/data-shape.ts +95 -84
- package/src/plugins/plugin.ts +116 -9
- package/src/plugins/shape.ts +64 -30
- package/src/taxonomy.ts +53 -1
- package/src/telemetry/clients/abstract-client.ts +63 -0
- package/src/telemetry/clients/browser-client.ts +160 -0
- package/src/telemetry/clients/node-client.ts +151 -0
- package/src/telemetry/clients/noop-client.ts +15 -0
- package/src/telemetry/clients/util.ts +33 -0
- package/src/telemetry/config.ts +12 -0
- package/src/telemetry/factory.ts +34 -0
- package/src/telemetry/index.ts +2 -27
- package/src/telemetry/types.ts +61 -0
- package/src/typescript.ts +17 -0
- package/src/util/delete-multiple.ts +35 -0
- package/src/util/index.ts +1 -0
package/src/plugins/plugin.ts
CHANGED
|
@@ -25,6 +25,11 @@ export type Result<Value = unknown> =
|
|
|
25
25
|
success: true
|
|
26
26
|
value: Value
|
|
27
27
|
}
|
|
28
|
+
| {
|
|
29
|
+
success: 'partial'
|
|
30
|
+
value: Value
|
|
31
|
+
unhandledRecords: Record[]
|
|
32
|
+
}
|
|
28
33
|
|
|
29
34
|
export type CommitResult = { success: boolean }
|
|
30
35
|
|
|
@@ -92,6 +97,36 @@ export type CoalesceStrategy =
|
|
|
92
97
|
|
|
93
98
|
export type FileType = 'fluent' | 'module' | 'json' | 'unknown'
|
|
94
99
|
|
|
100
|
+
export type PluginApiDoc = {
|
|
101
|
+
/**
|
|
102
|
+
* The name of the API (e.g., 'BusinessRule', 'Acl', 'Table')
|
|
103
|
+
* This is the callee name used in fluent code.
|
|
104
|
+
*/
|
|
105
|
+
apiName: string
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Uses module-specifier path to the markdown documentation file for this API relative to the SDK root.
|
|
109
|
+
* For example, @servicenow/sdk/docs/BusinessRule/BusinessRule.md
|
|
110
|
+
*/
|
|
111
|
+
docPath: string
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Tags for categorizing and organizing the API documentation
|
|
115
|
+
*/
|
|
116
|
+
tags: string[]
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Manifest structure for API documentation.
|
|
121
|
+
* This is the opinionated format returned by getDocsMetadata().
|
|
122
|
+
*/
|
|
123
|
+
export type DocsManifest = {
|
|
124
|
+
[apiName: string]: {
|
|
125
|
+
docPath: string
|
|
126
|
+
tags: string[]
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
95
130
|
export type PluginConfig<
|
|
96
131
|
Nodes extends SupportedKindName[] = SupportedKindName[],
|
|
97
132
|
Shapes extends ShapeClass[] = ShapeClass[],
|
|
@@ -103,6 +138,12 @@ export type PluginConfig<
|
|
|
103
138
|
*/
|
|
104
139
|
name: `${string}Plugin`
|
|
105
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Documentation for the APIs provided by this plugin. This is used to automatically
|
|
143
|
+
* generate documentation that can be retrieved via the getDocsMetadata() method.
|
|
144
|
+
*/
|
|
145
|
+
docs?: PluginApiDoc[]
|
|
146
|
+
|
|
106
147
|
/**
|
|
107
148
|
* The TypeScript AST nodes this plugin handles. Plugins that do not introduce new
|
|
108
149
|
* syntax should not need to define any handlers here.
|
|
@@ -380,7 +421,12 @@ export type PluginConfig<
|
|
|
380
421
|
* @returns A result indicating whether diffing was successful and, if so, a database
|
|
381
422
|
* containing only the changed records
|
|
382
423
|
*/
|
|
383
|
-
diff?: (
|
|
424
|
+
diff?: (
|
|
425
|
+
existing: Database,
|
|
426
|
+
incoming: Database,
|
|
427
|
+
descendants: Database,
|
|
428
|
+
context: Context
|
|
429
|
+
) => Promise<Result<Database>>
|
|
384
430
|
}
|
|
385
431
|
}
|
|
386
432
|
|
|
@@ -595,6 +641,28 @@ export class Plugin {
|
|
|
595
641
|
return this.config.name
|
|
596
642
|
}
|
|
597
643
|
|
|
644
|
+
/**
|
|
645
|
+
* Get documentation metadata for APIs provided by this plugin.
|
|
646
|
+
* Returns a manifest object with raw (unresolved) documentation paths.
|
|
647
|
+
* Path resolution is handled by PluginRegistry.getDocsMetadata() using the isomorphic resolver.
|
|
648
|
+
*/
|
|
649
|
+
getDocsMetadata(): DocsManifest | undefined {
|
|
650
|
+
if (!this.config.docs) {
|
|
651
|
+
return undefined
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
const manifest: DocsManifest = {}
|
|
655
|
+
|
|
656
|
+
for (const doc of this.config.docs) {
|
|
657
|
+
manifest[doc.apiName] = {
|
|
658
|
+
docPath: doc.docPath,
|
|
659
|
+
tags: doc.tags,
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
return manifest
|
|
664
|
+
}
|
|
665
|
+
|
|
598
666
|
getDescendants(parent: Record, database: Database): Record[] {
|
|
599
667
|
const descendantRelationships = Object.entries(this.relationships[parent.getTable()] ?? {}).filter(
|
|
600
668
|
([, { descendant }]) => descendant
|
|
@@ -720,7 +788,7 @@ export class Plugin {
|
|
|
720
788
|
async nodeToShape(node: SupportedNode, context: Omit<Context, 'self'>): Promise<Result<Shape>> {
|
|
721
789
|
const entry = this.nodeToShapeCache.get(node.compilerNode)
|
|
722
790
|
if (entry) {
|
|
723
|
-
return entry.
|
|
791
|
+
return entry.success ? entry.value : { success: false }
|
|
724
792
|
}
|
|
725
793
|
|
|
726
794
|
try {
|
|
@@ -773,7 +841,7 @@ export class Plugin {
|
|
|
773
841
|
async shapeToSubclass<const S extends Shape>(shape: S, context: Omit<Context, 'self'>): Promise<Result<S>> {
|
|
774
842
|
const entry = this.shapeToSubclassCache.get(shape)
|
|
775
843
|
if (entry) {
|
|
776
|
-
return entry.
|
|
844
|
+
return entry.success ? (entry.value as Result<S>) : { success: false }
|
|
777
845
|
}
|
|
778
846
|
|
|
779
847
|
try {
|
|
@@ -813,7 +881,7 @@ export class Plugin {
|
|
|
813
881
|
async shapeToRecord(shape: Shape, context: Omit<Context, 'self'>): Promise<Result<Record>> {
|
|
814
882
|
const entry = this.shapeToRecordCache.get(shape)
|
|
815
883
|
if (entry) {
|
|
816
|
-
return entry.
|
|
884
|
+
return entry.success ? entry.value : { success: false }
|
|
817
885
|
}
|
|
818
886
|
|
|
819
887
|
try {
|
|
@@ -910,6 +978,8 @@ export class Plugin {
|
|
|
910
978
|
continue
|
|
911
979
|
}
|
|
912
980
|
|
|
981
|
+
context.logger.debug(`Database contains ${database.query().length} records for transformation.`)
|
|
982
|
+
|
|
913
983
|
context.logger.debug(
|
|
914
984
|
`Transforming record into shape: ${record.getTable()}.${record.getId().getValue()}`
|
|
915
985
|
)
|
|
@@ -943,12 +1013,34 @@ export class Plugin {
|
|
|
943
1013
|
descendants: nonDeletedDescendants,
|
|
944
1014
|
})
|
|
945
1015
|
|
|
1016
|
+
// Track unhandled records to avoid marking them as handled
|
|
1017
|
+
const unhandledRecords: Record[] = []
|
|
1018
|
+
const unhandledRecordIds: string[] = []
|
|
1019
|
+
|
|
1020
|
+
if (result.success === 'partial') {
|
|
1021
|
+
for (const unhandledRecord of result.unhandledRecords) {
|
|
1022
|
+
unhandledRecords.push(unhandledRecord)
|
|
1023
|
+
unhandledRecordIds.push(unhandledRecord.getId().getValue())
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
|
|
946
1027
|
if (result.success) {
|
|
947
1028
|
success = true
|
|
948
1029
|
handledRecords.insert(record)
|
|
949
1030
|
shapes.push(...[result.value].flat())
|
|
1031
|
+
|
|
1032
|
+
// Mark all descendants as handled
|
|
950
1033
|
for (const descendant of [...deletedDescendants, ...nonDeletedDescendants]) {
|
|
951
|
-
|
|
1034
|
+
if (!unhandledRecordIds.includes(descendant.getId().getValue())) {
|
|
1035
|
+
handledRecords.insert(descendant)
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
context.logger.debug(
|
|
1039
|
+
`Plugin ${this.getName()} deferred handling of records: ${unhandledRecords.map((r) => r.getTable() + '_' + r.getId().getValue()).join(', ')}`
|
|
1040
|
+
)
|
|
1041
|
+
|
|
1042
|
+
if (unhandledRecords.length > 0) {
|
|
1043
|
+
return { success: 'partial', value: shapes, unhandledRecords }
|
|
952
1044
|
}
|
|
953
1045
|
}
|
|
954
1046
|
}
|
|
@@ -998,10 +1090,15 @@ export class Plugin {
|
|
|
998
1090
|
...[incoming.resolve(record.getId())].filter((r) => r !== undefined),
|
|
999
1091
|
...incoming.query().filter((r) => descendantsDatabase.resolve(r.getId()) !== undefined),
|
|
1000
1092
|
]
|
|
1001
|
-
const result = await diff.bind(this)(
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1093
|
+
const result = await diff.bind(this)(
|
|
1094
|
+
new Database(existingTree),
|
|
1095
|
+
new Database(incomingTree),
|
|
1096
|
+
new Database(descendants),
|
|
1097
|
+
{
|
|
1098
|
+
...context,
|
|
1099
|
+
self: this,
|
|
1100
|
+
}
|
|
1101
|
+
)
|
|
1005
1102
|
|
|
1006
1103
|
if (result.success) {
|
|
1007
1104
|
changedRecords.push(...result.value.query())
|
|
@@ -1245,4 +1342,14 @@ export class Plugins {
|
|
|
1245
1342
|
|
|
1246
1343
|
return false
|
|
1247
1344
|
}
|
|
1345
|
+
|
|
1346
|
+
getDocsMetadata(): DocsManifest {
|
|
1347
|
+
return this.plugins.reduce((aggregated, plugin) => {
|
|
1348
|
+
const pluginManifest = plugin.getDocsMetadata()
|
|
1349
|
+
if (pluginManifest) {
|
|
1350
|
+
Object.assign(aggregated, pluginManifest)
|
|
1351
|
+
}
|
|
1352
|
+
return aggregated
|
|
1353
|
+
}, {} as DocsManifest)
|
|
1354
|
+
}
|
|
1248
1355
|
}
|
package/src/plugins/shape.ts
CHANGED
|
@@ -366,6 +366,10 @@ export class UndefinedShape extends Shape<undefined> {
|
|
|
366
366
|
override toString(): StringShape {
|
|
367
367
|
return Shape.from(this, '').asString()
|
|
368
368
|
}
|
|
369
|
+
|
|
370
|
+
override getCode(): string {
|
|
371
|
+
return 'undefined'
|
|
372
|
+
}
|
|
369
373
|
}
|
|
370
374
|
|
|
371
375
|
export class DeletedShape extends UndefinedShape {}
|
|
@@ -473,6 +477,25 @@ export class PropertyAccessShape extends ResolvableShape {
|
|
|
473
477
|
override getCode(): string {
|
|
474
478
|
return this.elements.map((e) => e.getCode()).join('.')
|
|
475
479
|
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Override equals to compare property access paths instead of resolved values.
|
|
483
|
+
* This is important for datapill references where we need to compare the actual
|
|
484
|
+
* property paths (e.g., params.trigger.table_name vs params.trigger.current.user_name)
|
|
485
|
+
* rather than their resolved values (which would both be UnresolvedShape).
|
|
486
|
+
*/
|
|
487
|
+
override equals(other: unknown): boolean {
|
|
488
|
+
if (other instanceof PropertyAccessShape) {
|
|
489
|
+
// Compare the property access paths element by element
|
|
490
|
+
const otherElements = other.getElements()
|
|
491
|
+
if (this.elements.length !== otherElements.length) {
|
|
492
|
+
return false
|
|
493
|
+
}
|
|
494
|
+
return this.elements.every((el, i) => el.getName() === otherElements[i]?.getName())
|
|
495
|
+
}
|
|
496
|
+
// Fall back to default behavior for non-PropertyAccessShape comparisons
|
|
497
|
+
return super.equals(other)
|
|
498
|
+
}
|
|
476
499
|
}
|
|
477
500
|
|
|
478
501
|
type StringContentType = 'plain' | 'cdata'
|
|
@@ -800,7 +823,7 @@ const coerceTo = (coerceToType: 'string' | 'number' | 'boolean' | 'cdata', value
|
|
|
800
823
|
}
|
|
801
824
|
}
|
|
802
825
|
|
|
803
|
-
class
|
|
826
|
+
export class ShapeTransform {
|
|
804
827
|
constructor(
|
|
805
828
|
private readonly shape: ObjectShape,
|
|
806
829
|
private readonly resolve = true,
|
|
@@ -844,35 +867,35 @@ class Transform {
|
|
|
844
867
|
}
|
|
845
868
|
|
|
846
869
|
from(...properties: [string, ...string[]]) {
|
|
847
|
-
return new
|
|
870
|
+
return new ShapeTransform(this.shape, this.resolve, properties, this._map, this._def, this._coerce)
|
|
848
871
|
}
|
|
849
872
|
|
|
850
873
|
map(mapFunction: (...from: Shape[]) => unknown) {
|
|
851
|
-
return new
|
|
874
|
+
return new ShapeTransform(this.shape, this.resolve, this._from, mapFunction, this._def, this._coerce)
|
|
852
875
|
}
|
|
853
876
|
|
|
854
877
|
val(value: unknown) {
|
|
855
|
-
return new
|
|
878
|
+
return new ShapeTransform(this.shape, this.resolve, this._from, () => value, this._def, this._coerce)
|
|
856
879
|
}
|
|
857
880
|
|
|
858
881
|
def(value: unknown) {
|
|
859
|
-
return new
|
|
882
|
+
return new ShapeTransform(this.shape, this.resolve, this._from, this._map, value, this._coerce)
|
|
860
883
|
}
|
|
861
884
|
|
|
862
885
|
toCdata() {
|
|
863
|
-
return new
|
|
886
|
+
return new ShapeTransform(this.shape, this.resolve, this._from, this._map, this._def, 'cdata')
|
|
864
887
|
}
|
|
865
888
|
|
|
866
889
|
toString() {
|
|
867
|
-
return new
|
|
890
|
+
return new ShapeTransform(this.shape, this.resolve, this._from, this._map, this._def, 'string')
|
|
868
891
|
}
|
|
869
892
|
|
|
870
893
|
toNumber() {
|
|
871
|
-
return new
|
|
894
|
+
return new ShapeTransform(this.shape, this.resolve, this._from, this._map, this._def, 'number')
|
|
872
895
|
}
|
|
873
896
|
|
|
874
897
|
toBoolean() {
|
|
875
|
-
return new
|
|
898
|
+
return new ShapeTransform(this.shape, this.resolve, this._from, this._map, this._def, 'boolean')
|
|
876
899
|
}
|
|
877
900
|
}
|
|
878
901
|
|
|
@@ -936,26 +959,37 @@ export class ObjectShape extends Shape<globalThis.Record<string, unknown>> {
|
|
|
936
959
|
nonDefaultsOnly = false,
|
|
937
960
|
resolve = true,
|
|
938
961
|
}: ObjectPropertyOptions = {}): globalThis.Record<string, Shape> {
|
|
962
|
+
const result: globalThis.Record<string, Shape> = {}
|
|
963
|
+
|
|
939
964
|
if (nonDefaultsOnly) {
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
965
|
+
// Only include properties that differ from defaults
|
|
966
|
+
for (const k in this.setProperties) {
|
|
967
|
+
const v = this.setProperties[k]
|
|
968
|
+
if (v && v.isDefined() && !v.equals(this.getDefault(k))) {
|
|
969
|
+
result[k] = resolve && v.isResolvable() ? v.resolve() : v
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
return result
|
|
973
|
+
}
|
|
943
974
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
975
|
+
// Iterate set properties first to preserve ordering
|
|
976
|
+
for (const k in this.setProperties) {
|
|
977
|
+
const v = this.setProperties[k]
|
|
978
|
+
if (v) {
|
|
979
|
+
result[k] = resolve && v.isResolvable() ? v.resolve() : v
|
|
980
|
+
}
|
|
947
981
|
}
|
|
948
982
|
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
983
|
+
for (const k in this.defaultProperties) {
|
|
984
|
+
if (!this.setProperties[k] || this.setProperties[k].isUndefined()) {
|
|
985
|
+
const v = this.defaultProperties[k]
|
|
986
|
+
if (v) {
|
|
987
|
+
result[k] = resolve && v.isResolvable() ? v.resolve() : v
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
}
|
|
957
991
|
|
|
958
|
-
return
|
|
992
|
+
return result
|
|
959
993
|
}
|
|
960
994
|
|
|
961
995
|
override getValue(nonDefaultsOnly = false): globalThis.Record<string, unknown> {
|
|
@@ -966,8 +1000,8 @@ export class ObjectShape extends Shape<globalThis.Record<string, unknown>> {
|
|
|
966
1000
|
const [property, next, ...rest] = typeof propertyOrPath === 'string' ? [propertyOrPath] : propertyOrPath
|
|
967
1001
|
const propertyAliases = [property, ...this.getAliases(property)]
|
|
968
1002
|
const properties = this.properties({ resolve })
|
|
969
|
-
const match = propertyAliases.find((p) => properties
|
|
970
|
-
const value = match ? properties[match] : undefined
|
|
1003
|
+
const match = propertyAliases.find((p) => p in properties)
|
|
1004
|
+
const value = match !== undefined ? properties[match] : undefined
|
|
971
1005
|
return (
|
|
972
1006
|
(next ? value?.ifObject()?.get([next, ...rest], resolve) : value) ??
|
|
973
1007
|
new UndefinedShape({ source: this.getSource() })
|
|
@@ -1035,15 +1069,15 @@ export class ObjectShape extends Shape<globalThis.Record<string, unknown>> {
|
|
|
1035
1069
|
}
|
|
1036
1070
|
|
|
1037
1071
|
transform(
|
|
1038
|
-
schema: (utils: { $:
|
|
1039
|
-
[P in string | typeof MERGE]?:
|
|
1072
|
+
schema: (utils: { $: ShapeTransform; merge: typeof MERGE }) => {
|
|
1073
|
+
[P in string | typeof MERGE]?: ShapeTransform
|
|
1040
1074
|
},
|
|
1041
1075
|
resolve = true
|
|
1042
1076
|
) {
|
|
1043
1077
|
const properties = {}
|
|
1044
1078
|
const defaults = {}
|
|
1045
1079
|
|
|
1046
|
-
const definedSchema = schema({ merge: MERGE, $: new
|
|
1080
|
+
const definedSchema = schema({ merge: MERGE, $: new ShapeTransform(this, resolve) })
|
|
1047
1081
|
for (const to of [...Object.keys(definedSchema), MERGE] as const) {
|
|
1048
1082
|
if (definedSchema[to]) {
|
|
1049
1083
|
const result = definedSchema[to]._(to)
|
|
@@ -1099,7 +1133,7 @@ export class ObjectShape extends Shape<globalThis.Record<string, unknown>> {
|
|
|
1099
1133
|
} else if (a[key]?.equals(value)) {
|
|
1100
1134
|
// Don't overwrite properties that are equal
|
|
1101
1135
|
} else if (a[key]?.isObject() && value.isObject()) {
|
|
1102
|
-
a[key].merge(value) // Merge objects recursively
|
|
1136
|
+
a[key] = a[key].merge(value) // Merge objects recursively
|
|
1103
1137
|
} else {
|
|
1104
1138
|
a[key] = value
|
|
1105
1139
|
}
|
package/src/taxonomy.ts
CHANGED
|
@@ -13,6 +13,31 @@ const TableNames = {
|
|
|
13
13
|
SYSEVENT_EMAIL_ACTION: 'sysevent_email_action',
|
|
14
14
|
SYS_PD_PROCESS_DEFINITION: 'sys_pd_process_definition',
|
|
15
15
|
SYS_HUB_TRIGGER_TEMPLATE: 'sys_hub_trigger_template',
|
|
16
|
+
SYS_VARIABLE_VALUE: 'sys_variable_value',
|
|
17
|
+
SYS_ELEMENT_MAPPING: 'sys_element_mapping',
|
|
18
|
+
SYS_HUB_FLOW_INPUT: 'sys_hub_flow_input',
|
|
19
|
+
SYS_HUB_FLOW_OUTPUT: 'sys_hub_flow_output',
|
|
20
|
+
SYS_HUB_ACTION_INPUT_ACTION_INSTANCE: 'sys_hub_action_input_action_instance',
|
|
21
|
+
SYS_HUB_FLOW_VARIABLE: 'sys_hub_flow_variable',
|
|
22
|
+
SYS_HUB_ACTION_INSTANCE: 'sys_hub_action_instance',
|
|
23
|
+
SYS_HUB_SUB_FLOW_INSTANCE: 'sys_hub_sub_flow_instance',
|
|
24
|
+
SYS_HUB_TRIGGER_INSTANCE: 'sys_hub_trigger_instance',
|
|
25
|
+
SYS_HUB_FLOW_LOGIC: 'sys_hub_flow_logic',
|
|
26
|
+
SYS_HUB_PILL_COMPOUND: 'sys_hub_pill_compound',
|
|
27
|
+
SYS_FLOW_CAT_VARIABLE_MODEL: 'sys_flow_cat_variable_model',
|
|
28
|
+
SYS_HUB_TRIGGER_INSTANCE_V2: 'sys_hub_trigger_instance_v2',
|
|
29
|
+
SYS_HUB_ACTION_INSTANCE_V2: 'sys_hub_action_instance_v2',
|
|
30
|
+
SYS_HUB_FLOW_LOGIC_INSTANCE_V2: 'sys_hub_flow_logic_instance_v2',
|
|
31
|
+
SYS_HUB_SUB_FLOW_INSTANCE_V2: 'sys_hub_sub_flow_instance_v2',
|
|
32
|
+
SYS_FLOW_RECORD_TRIGGER: 'sys_flow_record_trigger',
|
|
33
|
+
SYS_TRIGGER_RUNNER_MAPPING: 'sys_trigger_runner_mapping',
|
|
34
|
+
SYS_FLOW_TRIGGER_PLAN: 'sys_flow_trigger_plan',
|
|
35
|
+
SYS_HUB_FLOW_SNAPSHOT: 'sys_hub_flow_snapshot',
|
|
36
|
+
SYS_FLOW_SUBFLOW_PLAN: 'sys_flow_subflow_plan',
|
|
37
|
+
SYS_FLOW_EMAIL_TRIGGER: 'sys_flow_email_trigger',
|
|
38
|
+
SYS_FLOW_KNOWLEDGE_TRIGGER: 'sys_flow_knowledge_trigger',
|
|
39
|
+
SYS_FLOW_RT_QUERY_TRIGGER: 'sys_flow_rt_query_trigger',
|
|
40
|
+
SYS_FLOW_TRIGGER: 'sys_flow_trigger',
|
|
16
41
|
|
|
17
42
|
// Client Development tables
|
|
18
43
|
DL_U_ASSIGNMENT: 'dl_u_assignment',
|
|
@@ -156,6 +181,7 @@ const TableNames = {
|
|
|
156
181
|
|
|
157
182
|
// String format: one or more path segments separated by '/' (e.g., 'server-development/business-rule' or 'integration/outbound/rest-api')
|
|
158
183
|
const taxonomyItem = z.string().regex(/^[a-z0-9_-]+(\/[a-z0-9_-]+)*$/)
|
|
184
|
+
const flowTaxonomyItem = taxonomyItem.default('automation/flow')
|
|
159
185
|
|
|
160
186
|
const taxonomyMapping = z
|
|
161
187
|
.object({
|
|
@@ -164,12 +190,38 @@ const taxonomyMapping = z
|
|
|
164
190
|
[TableNames.SYS_HUB_TRIGGER_DEFINITION]: taxonomyItem.default('automation/trigger'),
|
|
165
191
|
[TableNames.SYS_PD_ACTIVITY_DEFINITION]: taxonomyItem.default('automation/activity-definition'),
|
|
166
192
|
[TableNames.SYS_ALIAS]: taxonomyItem.default('automation/workflow-activity'),
|
|
167
|
-
[TableNames.SYS_HUB_FLOW]: taxonomyItem.default('automation/flow'),
|
|
168
193
|
[TableNames.SYS_DECISION]: taxonomyItem.default('automation/decision-table'),
|
|
169
194
|
[TableNames.SYSEVENT_EMAIL_TEMPLATE]: taxonomyItem.default('automation/email-template'),
|
|
170
195
|
[TableNames.SYSEVENT_EMAIL_ACTION]: taxonomyItem.default('automation/notification'),
|
|
171
196
|
[TableNames.SYS_PD_PROCESS_DEFINITION]: taxonomyItem.default('automation/playbook'),
|
|
172
197
|
[TableNames.SYS_HUB_TRIGGER_TEMPLATE]: taxonomyItem.default('automation/trigger'),
|
|
198
|
+
[TableNames.SYS_FLOW_EMAIL_TRIGGER]: taxonomyItem.default('automation/trigger'),
|
|
199
|
+
[TableNames.SYS_FLOW_TRIGGER_PLAN]: taxonomyItem.default('automation/trigger'),
|
|
200
|
+
[TableNames.SYS_FLOW_KNOWLEDGE_TRIGGER]: taxonomyItem.default('automation/trigger'),
|
|
201
|
+
[TableNames.SYS_FLOW_RT_QUERY_TRIGGER]: taxonomyItem.default('automation/trigger'),
|
|
202
|
+
[TableNames.SYS_FLOW_TRIGGER]: taxonomyItem.default('automation/trigger'),
|
|
203
|
+
[TableNames.SYS_HUB_FLOW]: flowTaxonomyItem,
|
|
204
|
+
[TableNames.SYS_HUB_ACTION_TYPE_DEFINITION]: flowTaxonomyItem,
|
|
205
|
+
[TableNames.SYS_ELEMENT_MAPPING]: flowTaxonomyItem,
|
|
206
|
+
[TableNames.SYS_HUB_FLOW_INPUT]: flowTaxonomyItem,
|
|
207
|
+
[TableNames.SYS_HUB_FLOW_OUTPUT]: flowTaxonomyItem,
|
|
208
|
+
[TableNames.SYS_HUB_ACTION_INPUT_ACTION_INSTANCE]: flowTaxonomyItem,
|
|
209
|
+
[TableNames.SYS_HUB_FLOW_VARIABLE]: flowTaxonomyItem,
|
|
210
|
+
[TableNames.SYS_HUB_ACTION_INSTANCE]: flowTaxonomyItem,
|
|
211
|
+
[TableNames.SYS_HUB_SUB_FLOW_INSTANCE]: flowTaxonomyItem,
|
|
212
|
+
[TableNames.SYS_HUB_FLOW_LOGIC]: flowTaxonomyItem,
|
|
213
|
+
[TableNames.SYS_HUB_PILL_COMPOUND]: flowTaxonomyItem,
|
|
214
|
+
[TableNames.SYS_FLOW_CAT_VARIABLE_MODEL]: flowTaxonomyItem,
|
|
215
|
+
[TableNames.SYS_HUB_TRIGGER_INSTANCE_V2]: flowTaxonomyItem,
|
|
216
|
+
[TableNames.SYS_HUB_TRIGGER_INSTANCE]: flowTaxonomyItem,
|
|
217
|
+
[TableNames.SYS_HUB_ACTION_INSTANCE_V2]: flowTaxonomyItem,
|
|
218
|
+
[TableNames.SYS_HUB_FLOW_LOGIC_INSTANCE_V2]: flowTaxonomyItem,
|
|
219
|
+
[TableNames.SYS_HUB_SUB_FLOW_INSTANCE_V2]: flowTaxonomyItem,
|
|
220
|
+
[TableNames.SYS_FLOW_RECORD_TRIGGER]: flowTaxonomyItem,
|
|
221
|
+
[TableNames.SYS_TRIGGER_RUNNER_MAPPING]: flowTaxonomyItem,
|
|
222
|
+
[TableNames.SYS_FLOW_TRIGGER_PLAN]: flowTaxonomyItem,
|
|
223
|
+
[TableNames.SYS_HUB_FLOW_SNAPSHOT]: flowTaxonomyItem,
|
|
224
|
+
[TableNames.SYS_FLOW_SUBFLOW_PLAN]: flowTaxonomyItem,
|
|
173
225
|
|
|
174
226
|
// Client Development tables
|
|
175
227
|
[TableNames.DL_U_ASSIGNMENT]: taxonomyItem.default('client-development/assignment-data-lookup'),
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Telemetry, TelemetryEvent, TelemetryEventData, TimerMetric, InstanceSettings, Session } from '../types'
|
|
2
|
+
import { AppSeeTimerMetric } from './util'
|
|
3
|
+
|
|
4
|
+
export abstract class AbstractAppSeeClient implements Telemetry {
|
|
5
|
+
protected readonly sdkVersion?: string | undefined
|
|
6
|
+
protected readonly clientName: 'cli' | 'ide' | string
|
|
7
|
+
protected readonly hostname?: string | undefined
|
|
8
|
+
protected session?: Session
|
|
9
|
+
protected startPromise?: Promise<void>
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
protected readonly config: InstanceSettings,
|
|
13
|
+
protected telemetryAttributes: {
|
|
14
|
+
sdkVersion?: string
|
|
15
|
+
clientName: 'cli' | 'ide' | string
|
|
16
|
+
hostname?: string
|
|
17
|
+
}
|
|
18
|
+
) {
|
|
19
|
+
this.sdkVersion = telemetryAttributes.sdkVersion
|
|
20
|
+
this.clientName = telemetryAttributes.clientName
|
|
21
|
+
this.hostname = telemetryAttributes.hostname
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
startTimerEvent(name: TelemetryEvent['name']): TimerMetric {
|
|
25
|
+
return new AppSeeTimerMetric(name)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public start(): Promise<void> {
|
|
29
|
+
if (!this.startPromise) {
|
|
30
|
+
this.startPromise = this.doStart()
|
|
31
|
+
}
|
|
32
|
+
return this.startPromise
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public sendEvent(events: TelemetryEvent | TelemetryEvent[]): void {
|
|
36
|
+
//we fire and forget the telemetry events
|
|
37
|
+
this.start()
|
|
38
|
+
.then(() => this.doSendEvent(events))
|
|
39
|
+
.catch(() => {})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public error(event: string, error: unknown, data?: TelemetryEventData) {
|
|
43
|
+
this.sendEvent([
|
|
44
|
+
{
|
|
45
|
+
name: 'error',
|
|
46
|
+
data: {
|
|
47
|
+
event,
|
|
48
|
+
...(error instanceof Error
|
|
49
|
+
? {
|
|
50
|
+
name: error.name,
|
|
51
|
+
message: error.message,
|
|
52
|
+
stack: error.stack,
|
|
53
|
+
}
|
|
54
|
+
: { message: error?.toString() }),
|
|
55
|
+
...data,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
])
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
protected abstract doStart(): Promise<void>
|
|
62
|
+
protected abstract doSendEvent(events: TelemetryEvent | TelemetryEvent[]): void
|
|
63
|
+
}
|