@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.
Files changed (83) hide show
  1. package/dist/compiler.d.ts +14 -2
  2. package/dist/compiler.js +120 -8
  3. package/dist/compiler.js.map +1 -1
  4. package/dist/compression.d.ts +2 -2
  5. package/dist/compression.js +4 -1
  6. package/dist/compression.js.map +1 -1
  7. package/dist/now-config-dependencies.d.ts +2 -1
  8. package/dist/now-config.d.ts +10 -5
  9. package/dist/now-config.js +6 -5
  10. package/dist/now-config.js.map +1 -1
  11. package/dist/plugins/cache.d.ts +8 -13
  12. package/dist/plugins/cache.js +2 -26
  13. package/dist/plugins/cache.js.map +1 -1
  14. package/dist/plugins/data-shape.d.ts +24 -33
  15. package/dist/plugins/data-shape.js +83 -73
  16. package/dist/plugins/data-shape.js.map +1 -1
  17. package/dist/plugins/plugin.d.ts +43 -1
  18. package/dist/plugins/plugin.js +49 -5
  19. package/dist/plugins/plugin.js.map +1 -1
  20. package/dist/plugins/shape.d.ts +19 -11
  21. package/dist/plugins/shape.js +61 -23
  22. package/dist/plugins/shape.js.map +1 -1
  23. package/dist/taxonomy.js +53 -1
  24. package/dist/taxonomy.js.map +1 -1
  25. package/dist/telemetry/clients/abstract-client.d.ts +25 -0
  26. package/dist/telemetry/clients/abstract-client.js +55 -0
  27. package/dist/telemetry/clients/abstract-client.js.map +1 -0
  28. package/dist/telemetry/clients/browser-client.d.ts +20 -0
  29. package/dist/telemetry/clients/browser-client.js +136 -0
  30. package/dist/telemetry/clients/browser-client.js.map +1 -0
  31. package/dist/telemetry/clients/node-client.d.ts +15 -0
  32. package/dist/telemetry/clients/node-client.js +159 -0
  33. package/dist/telemetry/clients/node-client.js.map +1 -0
  34. package/dist/telemetry/clients/noop-client.d.ts +10 -0
  35. package/dist/telemetry/clients/noop-client.js +18 -0
  36. package/dist/telemetry/clients/noop-client.js.map +1 -0
  37. package/dist/telemetry/clients/util.d.ts +11 -0
  38. package/dist/telemetry/clients/util.js +34 -0
  39. package/dist/telemetry/clients/util.js.map +1 -0
  40. package/dist/telemetry/config.d.ts +2 -0
  41. package/dist/telemetry/config.js +28 -0
  42. package/dist/telemetry/config.js.map +1 -0
  43. package/dist/telemetry/factory.d.ts +13 -0
  44. package/dist/telemetry/factory.js +29 -0
  45. package/dist/telemetry/factory.js.map +1 -0
  46. package/dist/telemetry/index.d.ts +2 -25
  47. package/dist/telemetry/index.js +3 -15
  48. package/dist/telemetry/index.js.map +1 -1
  49. package/dist/telemetry/types.d.ts +55 -0
  50. package/dist/telemetry/types.js +12 -0
  51. package/dist/telemetry/types.js.map +1 -0
  52. package/dist/typescript.d.ts +10 -0
  53. package/dist/typescript.js +18 -0
  54. package/dist/typescript.js.map +1 -1
  55. package/dist/util/delete-multiple.d.ts +5 -0
  56. package/dist/util/delete-multiple.js +30 -0
  57. package/dist/util/delete-multiple.js.map +1 -0
  58. package/dist/util/index.d.ts +1 -0
  59. package/dist/util/index.js +1 -0
  60. package/dist/util/index.js.map +1 -1
  61. package/now.config.schema.json +40 -5
  62. package/package.json +13 -9
  63. package/src/compiler.ts +140 -7
  64. package/src/compression.ts +2 -2
  65. package/src/now-config-dependencies.ts +2 -1
  66. package/src/now-config.ts +8 -6
  67. package/src/plugins/cache.ts +5 -27
  68. package/src/plugins/data-shape.ts +95 -84
  69. package/src/plugins/plugin.ts +116 -9
  70. package/src/plugins/shape.ts +64 -30
  71. package/src/taxonomy.ts +53 -1
  72. package/src/telemetry/clients/abstract-client.ts +63 -0
  73. package/src/telemetry/clients/browser-client.ts +160 -0
  74. package/src/telemetry/clients/node-client.ts +151 -0
  75. package/src/telemetry/clients/noop-client.ts +15 -0
  76. package/src/telemetry/clients/util.ts +33 -0
  77. package/src/telemetry/config.ts +12 -0
  78. package/src/telemetry/factory.ts +34 -0
  79. package/src/telemetry/index.ts +2 -27
  80. package/src/telemetry/types.ts +61 -0
  81. package/src/typescript.ts +17 -0
  82. package/src/util/delete-multiple.ts +35 -0
  83. package/src/util/index.ts +1 -0
@@ -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?: (existing: Database, incoming: Database, context: Context) => Promise<Result<Database>>
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.isError() ? { success: false } : entry.unwrap()
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.isError() ? { success: false } : (entry.unwrap() as Result<S>)
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.isError() ? { success: false } : entry.unwrap()
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
- handledRecords.insert(descendant)
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)(new Database(existingTree), new Database(incomingTree), {
1002
- ...context,
1003
- self: this,
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
  }
@@ -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 Transform {
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 Transform(this.shape, this.resolve, properties, this._map, this._def, this._coerce)
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 Transform(this.shape, this.resolve, this._from, mapFunction, this._def, this._coerce)
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 Transform(this.shape, this.resolve, this._from, () => value, this._def, this._coerce)
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 Transform(this.shape, this.resolve, this._from, this._map, value, this._coerce)
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 Transform(this.shape, this.resolve, this._from, this._map, this._def, 'cdata')
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 Transform(this.shape, this.resolve, this._from, this._map, this._def, 'string')
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 Transform(this.shape, this.resolve, this._from, this._map, this._def, 'number')
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 Transform(this.shape, this.resolve, this._from, this._map, this._def, 'boolean')
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
- const entries = Object.entries(this.setProperties).filter(
941
- ([k, v]) => v.isDefined() && !v.equals(this.getDefault(k))
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
- return Object.fromEntries(
945
- resolve ? entries.map(([k, v]) => [k, v.isResolvable() ? v.resolve() : v]) : entries
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
- // This logic may seem odd, but it's written this way to preserve the ordering of
950
- // the set properties instead of using the ordering of the defaults.
951
- const entries = [
952
- ...Object.entries(this.setProperties),
953
- ...Object.entries(this.defaultProperties).filter(
954
- ([k]) => !this.setProperties[k] || this.setProperties[k].isUndefined()
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 Object.fromEntries(resolve ? entries.map(([k, v]) => [k, v.isResolvable() ? v.resolve() : v]) : entries)
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[p])
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: { $: Transform; merge: typeof MERGE }) => {
1039
- [P in string | typeof MERGE]?: Transform
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 Transform(this, resolve) })
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
+ }