@servicenow/sdk-build-plugins 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.
Files changed (286) hide show
  1. package/dist/acl-plugin.js +3 -4
  2. package/dist/acl-plugin.js.map +1 -1
  3. package/dist/applicability-plugin.js +0 -2
  4. package/dist/applicability-plugin.js.map +1 -1
  5. package/dist/application-menu-plugin.js +0 -2
  6. package/dist/application-menu-plugin.js.map +1 -1
  7. package/dist/arrow-function-plugin.js +0 -1
  8. package/dist/arrow-function-plugin.js.map +1 -1
  9. package/dist/atf/test-plugin.js +6 -10
  10. package/dist/atf/test-plugin.js.map +1 -1
  11. package/dist/basic-syntax-plugin.js +10 -4
  12. package/dist/basic-syntax-plugin.js.map +1 -1
  13. package/dist/business-rule-plugin.js +0 -1
  14. package/dist/business-rule-plugin.js.map +1 -1
  15. package/dist/call-expression-plugin.js +0 -1
  16. package/dist/call-expression-plugin.js.map +1 -1
  17. package/dist/claims-plugin.js +0 -1
  18. package/dist/claims-plugin.js.map +1 -1
  19. package/dist/client-script-plugin.js +0 -1
  20. package/dist/client-script-plugin.js.map +1 -1
  21. package/dist/column-plugin.js +120 -49
  22. package/dist/column-plugin.js.map +1 -1
  23. package/dist/cross-scope-privilege-plugin.js +0 -1
  24. package/dist/cross-scope-privilege-plugin.js.map +1 -1
  25. package/dist/dashboard/dashboard-plugin.js +0 -2
  26. package/dist/dashboard/dashboard-plugin.js.map +1 -1
  27. package/dist/data-plugin.js +0 -1
  28. package/dist/data-plugin.js.map +1 -1
  29. package/dist/data-policy-plugin.d.ts +2 -0
  30. package/dist/data-policy-plugin.js +276 -0
  31. package/dist/data-policy-plugin.js.map +1 -0
  32. package/dist/email-notification-plugin.js +2 -3
  33. package/dist/email-notification-plugin.js.map +1 -1
  34. package/dist/flow/flow-logic/flow-logic-constants.d.ts +2 -0
  35. package/dist/flow/flow-logic/flow-logic-constants.js +6 -1
  36. package/dist/flow/flow-logic/flow-logic-constants.js.map +1 -1
  37. package/dist/flow/flow-logic/flow-logic-diagnostics.js +192 -56
  38. package/dist/flow/flow-logic/flow-logic-diagnostics.js.map +1 -1
  39. package/dist/flow/flow-logic/flow-logic-plugin-helpers.d.ts +2 -1
  40. package/dist/flow/flow-logic/flow-logic-plugin-helpers.js +44 -5
  41. package/dist/flow/flow-logic/flow-logic-plugin-helpers.js.map +1 -1
  42. package/dist/flow/flow-logic/flow-logic-plugin.js +279 -29
  43. package/dist/flow/flow-logic/flow-logic-plugin.js.map +1 -1
  44. package/dist/flow/flow-logic/flow-logic-shapes.d.ts +15 -0
  45. package/dist/flow/flow-logic/flow-logic-shapes.js +25 -1
  46. package/dist/flow/flow-logic/flow-logic-shapes.js.map +1 -1
  47. package/dist/flow/plugins/approval-rules-plugin.js +0 -1
  48. package/dist/flow/plugins/approval-rules-plugin.js.map +1 -1
  49. package/dist/flow/plugins/flow-action-definition-plugin.js +804 -205
  50. package/dist/flow/plugins/flow-action-definition-plugin.js.map +1 -1
  51. package/dist/flow/plugins/flow-data-pill-plugin.js +3 -5
  52. package/dist/flow/plugins/flow-data-pill-plugin.js.map +1 -1
  53. package/dist/flow/plugins/flow-definition-plugin.js +84 -17
  54. package/dist/flow/plugins/flow-definition-plugin.js.map +1 -1
  55. package/dist/flow/plugins/flow-diagnostics-plugin.js +65 -3
  56. package/dist/flow/plugins/flow-diagnostics-plugin.js.map +1 -1
  57. package/dist/flow/plugins/flow-instance-plugin.js +13 -5
  58. package/dist/flow/plugins/flow-instance-plugin.js.map +1 -1
  59. package/dist/flow/plugins/flow-trigger-instance-plugin.js +0 -1
  60. package/dist/flow/plugins/flow-trigger-instance-plugin.js.map +1 -1
  61. package/dist/flow/plugins/inline-script-plugin.js +0 -1
  62. package/dist/flow/plugins/inline-script-plugin.js.map +1 -1
  63. package/dist/flow/plugins/step-definition-plugin.js +0 -2
  64. package/dist/flow/plugins/step-definition-plugin.js.map +1 -1
  65. package/dist/flow/plugins/step-instance-plugin.js +216 -77
  66. package/dist/flow/plugins/step-instance-plugin.js.map +1 -1
  67. package/dist/flow/plugins/trigger-plugin.js +0 -2
  68. package/dist/flow/plugins/trigger-plugin.js.map +1 -1
  69. package/dist/flow/plugins/wfa-datapill-plugin.js +0 -1
  70. package/dist/flow/plugins/wfa-datapill-plugin.js.map +1 -1
  71. package/dist/flow/utils/datapill-transformer.js +9 -5
  72. package/dist/flow/utils/datapill-transformer.js.map +1 -1
  73. package/dist/flow/utils/flow-constants.d.ts +12 -0
  74. package/dist/flow/utils/flow-constants.js +17 -3
  75. package/dist/flow/utils/flow-constants.js.map +1 -1
  76. package/dist/flow/utils/flow-io-to-record.d.ts +1 -1
  77. package/dist/flow/utils/flow-io-to-record.js +21 -13
  78. package/dist/flow/utils/flow-io-to-record.js.map +1 -1
  79. package/dist/flow/utils/flow-pill-utils.d.ts +26 -0
  80. package/dist/flow/utils/flow-pill-utils.js +50 -0
  81. package/dist/flow/utils/flow-pill-utils.js.map +1 -0
  82. package/dist/flow/utils/flow-stage-processor.d.ts +138 -0
  83. package/dist/flow/utils/flow-stage-processor.js +665 -0
  84. package/dist/flow/utils/flow-stage-processor.js.map +1 -0
  85. package/dist/flow/utils/pill-string-parser.js +28 -43
  86. package/dist/flow/utils/pill-string-parser.js.map +1 -1
  87. package/dist/flow/utils/utils.d.ts +11 -6
  88. package/dist/flow/utils/utils.js +37 -28
  89. package/dist/flow/utils/utils.js.map +1 -1
  90. package/dist/form-plugin.js +4 -14
  91. package/dist/form-plugin.js.map +1 -1
  92. package/dist/html-import-plugin.js +0 -1
  93. package/dist/html-import-plugin.js.map +1 -1
  94. package/dist/import-sets-plugin.js +0 -2
  95. package/dist/import-sets-plugin.js.map +1 -1
  96. package/dist/inbound-email-action-plugin.js +0 -1
  97. package/dist/inbound-email-action-plugin.js.map +1 -1
  98. package/dist/index.d.ts +2 -1
  99. package/dist/index.js +5 -1
  100. package/dist/index.js.map +1 -1
  101. package/dist/instance-scan-plugin.js +0 -7
  102. package/dist/instance-scan-plugin.js.map +1 -1
  103. package/dist/json-plugin.js +0 -1
  104. package/dist/json-plugin.js.map +1 -1
  105. package/dist/list-plugin.js +4 -1
  106. package/dist/list-plugin.js.map +1 -1
  107. package/dist/now-attach-plugin.js +0 -1
  108. package/dist/now-attach-plugin.js.map +1 -1
  109. package/dist/now-config-plugin.js +1 -1
  110. package/dist/now-config-plugin.js.map +1 -1
  111. package/dist/now-id-plugin.js +0 -1
  112. package/dist/now-id-plugin.js.map +1 -1
  113. package/dist/now-include-plugin.js +0 -1
  114. package/dist/now-include-plugin.js.map +1 -1
  115. package/dist/now-ref-plugin.js +0 -1
  116. package/dist/now-ref-plugin.js.map +1 -1
  117. package/dist/now-unresolved-plugin.js +0 -1
  118. package/dist/now-unresolved-plugin.js.map +1 -1
  119. package/dist/package-json-plugin.js +3 -2
  120. package/dist/package-json-plugin.js.map +1 -1
  121. package/dist/property-plugin.js +0 -2
  122. package/dist/property-plugin.js.map +1 -1
  123. package/dist/record-plugin.d.ts +2 -0
  124. package/dist/record-plugin.js +5 -4
  125. package/dist/record-plugin.js.map +1 -1
  126. package/dist/repack/lint/Rules.d.ts +1 -2
  127. package/dist/rest-api-plugin.js +6 -5
  128. package/dist/rest-api-plugin.js.map +1 -1
  129. package/dist/role-plugin.js +0 -1
  130. package/dist/role-plugin.js.map +1 -1
  131. package/dist/schedule-script/scheduled-script-plugin.js +5 -4
  132. package/dist/schedule-script/scheduled-script-plugin.js.map +1 -1
  133. package/dist/script-action-plugin.js +0 -2
  134. package/dist/script-action-plugin.js.map +1 -1
  135. package/dist/script-include-plugin.js +4 -4
  136. package/dist/script-include-plugin.js.map +1 -1
  137. package/dist/server-module-plugin/index.js +2 -3
  138. package/dist/server-module-plugin/index.js.map +1 -1
  139. package/dist/service-catalog/catalog-clientscript-plugin.js +2 -4
  140. package/dist/service-catalog/catalog-clientscript-plugin.js.map +1 -1
  141. package/dist/service-catalog/catalog-item-plugin.js +0 -2
  142. package/dist/service-catalog/catalog-item-plugin.js.map +1 -1
  143. package/dist/service-catalog/catalog-ui-policy-plugin.js +2 -4
  144. package/dist/service-catalog/catalog-ui-policy-plugin.js.map +1 -1
  145. package/dist/service-catalog/sc-record-producer-plugin.js +0 -2
  146. package/dist/service-catalog/sc-record-producer-plugin.js.map +1 -1
  147. package/dist/service-catalog/service-catalog-base.d.ts +2 -2
  148. package/dist/service-catalog/service-catalog-base.js +2 -2
  149. package/dist/service-catalog/service-catalog-base.js.map +1 -1
  150. package/dist/service-catalog/utils.js +1 -1
  151. package/dist/service-catalog/utils.js.map +1 -1
  152. package/dist/service-catalog/variable-set-plugin.js +0 -2
  153. package/dist/service-catalog/variable-set-plugin.js.map +1 -1
  154. package/dist/service-portal/angular-provider-plugin.js +0 -2
  155. package/dist/service-portal/angular-provider-plugin.js.map +1 -1
  156. package/dist/service-portal/dependency-plugin.js +3 -5
  157. package/dist/service-portal/dependency-plugin.js.map +1 -1
  158. package/dist/service-portal/header-footer-plugin.js +3 -5
  159. package/dist/service-portal/header-footer-plugin.js.map +1 -1
  160. package/dist/service-portal/menu-plugin.js +0 -1
  161. package/dist/service-portal/menu-plugin.js.map +1 -1
  162. package/dist/service-portal/page-plugin.js +0 -1
  163. package/dist/service-portal/page-plugin.js.map +1 -1
  164. package/dist/service-portal/page-route-map-plugin.js +0 -1
  165. package/dist/service-portal/page-route-map-plugin.js.map +1 -1
  166. package/dist/service-portal/portal-plugin.js +0 -2
  167. package/dist/service-portal/portal-plugin.js.map +1 -1
  168. package/dist/service-portal/theme-plugin.js +0 -2
  169. package/dist/service-portal/theme-plugin.js.map +1 -1
  170. package/dist/service-portal/widget-plugin.js +3 -5
  171. package/dist/service-portal/widget-plugin.js.map +1 -1
  172. package/dist/sla-plugin.js +0 -2
  173. package/dist/sla-plugin.js.map +1 -1
  174. package/dist/static-content-plugin.js +32 -3
  175. package/dist/static-content-plugin.js.map +1 -1
  176. package/dist/table-plugin.js +303 -66
  177. package/dist/table-plugin.js.map +1 -1
  178. package/dist/ui-action-plugin.js +26 -17
  179. package/dist/ui-action-plugin.js.map +1 -1
  180. package/dist/ui-page-plugin.js +159 -17
  181. package/dist/ui-page-plugin.js.map +1 -1
  182. package/dist/ui-policy-plugin.js +28 -97
  183. package/dist/ui-policy-plugin.js.map +1 -1
  184. package/dist/user-preference-plugin.js +0 -2
  185. package/dist/user-preference-plugin.js.map +1 -1
  186. package/dist/utils.d.ts +5 -9
  187. package/dist/utils.js +38 -11
  188. package/dist/utils.js.map +1 -1
  189. package/dist/ux-list-menu-config-plugin.js +0 -2
  190. package/dist/ux-list-menu-config-plugin.js.map +1 -1
  191. package/dist/view-plugin.js +0 -1
  192. package/dist/view-plugin.js.map +1 -1
  193. package/dist/workspace-plugin.js +0 -2
  194. package/dist/workspace-plugin.js.map +1 -1
  195. package/package.json +6 -6
  196. package/src/acl-plugin.ts +4 -5
  197. package/src/applicability-plugin.ts +0 -2
  198. package/src/application-menu-plugin.ts +0 -2
  199. package/src/arrow-function-plugin.ts +0 -1
  200. package/src/atf/test-plugin.ts +6 -11
  201. package/src/basic-syntax-plugin.ts +11 -4
  202. package/src/business-rule-plugin.ts +1 -2
  203. package/src/call-expression-plugin.ts +0 -1
  204. package/src/claims-plugin.ts +0 -1
  205. package/src/client-script-plugin.ts +1 -2
  206. package/src/column-plugin.ts +163 -76
  207. package/src/cross-scope-privilege-plugin.ts +1 -2
  208. package/src/dashboard/dashboard-plugin.ts +0 -2
  209. package/src/data-plugin.ts +0 -1
  210. package/src/data-policy-plugin.ts +333 -0
  211. package/src/email-notification-plugin.ts +8 -4
  212. package/src/flow/flow-logic/flow-logic-constants.ts +6 -0
  213. package/src/flow/flow-logic/flow-logic-diagnostics.ts +236 -58
  214. package/src/flow/flow-logic/flow-logic-plugin-helpers.ts +59 -6
  215. package/src/flow/flow-logic/flow-logic-plugin.ts +368 -38
  216. package/src/flow/flow-logic/flow-logic-shapes.ts +25 -0
  217. package/src/flow/plugins/approval-rules-plugin.ts +0 -1
  218. package/src/flow/plugins/flow-action-definition-plugin.ts +940 -208
  219. package/src/flow/plugins/flow-data-pill-plugin.ts +3 -5
  220. package/src/flow/plugins/flow-definition-plugin.ts +159 -26
  221. package/src/flow/plugins/flow-diagnostics-plugin.ts +89 -3
  222. package/src/flow/plugins/flow-instance-plugin.ts +26 -12
  223. package/src/flow/plugins/flow-trigger-instance-plugin.ts +0 -1
  224. package/src/flow/plugins/inline-script-plugin.ts +0 -1
  225. package/src/flow/plugins/step-definition-plugin.ts +0 -2
  226. package/src/flow/plugins/step-instance-plugin.ts +259 -65
  227. package/src/flow/plugins/trigger-plugin.ts +0 -2
  228. package/src/flow/plugins/wfa-datapill-plugin.ts +0 -1
  229. package/src/flow/utils/datapill-transformer.ts +13 -5
  230. package/src/flow/utils/flow-constants.ts +19 -1
  231. package/src/flow/utils/flow-io-to-record.ts +29 -19
  232. package/src/flow/utils/flow-pill-utils.ts +48 -0
  233. package/src/flow/utils/flow-stage-processor.ts +831 -0
  234. package/src/flow/utils/pill-string-parser.ts +29 -47
  235. package/src/flow/utils/utils.ts +39 -35
  236. package/src/form-plugin.ts +5 -15
  237. package/src/html-import-plugin.ts +0 -1
  238. package/src/import-sets-plugin.ts +0 -2
  239. package/src/inbound-email-action-plugin.ts +1 -2
  240. package/src/index.ts +7 -1
  241. package/src/instance-scan-plugin.ts +0 -7
  242. package/src/json-plugin.ts +0 -1
  243. package/src/list-plugin.ts +6 -2
  244. package/src/now-attach-plugin.ts +0 -1
  245. package/src/now-config-plugin.ts +1 -1
  246. package/src/now-id-plugin.ts +0 -1
  247. package/src/now-include-plugin.ts +0 -1
  248. package/src/now-ref-plugin.ts +0 -1
  249. package/src/now-unresolved-plugin.ts +0 -1
  250. package/src/package-json-plugin.ts +8 -3
  251. package/src/property-plugin.ts +0 -2
  252. package/src/record-plugin.ts +14 -6
  253. package/src/repack/lint/Rules.ts +1 -1
  254. package/src/rest-api-plugin.ts +7 -6
  255. package/src/role-plugin.ts +1 -2
  256. package/src/schedule-script/scheduled-script-plugin.ts +11 -5
  257. package/src/script-action-plugin.ts +0 -2
  258. package/src/script-include-plugin.ts +8 -4
  259. package/src/server-module-plugin/index.ts +2 -3
  260. package/src/service-catalog/catalog-clientscript-plugin.ts +2 -4
  261. package/src/service-catalog/catalog-item-plugin.ts +0 -2
  262. package/src/service-catalog/catalog-ui-policy-plugin.ts +2 -4
  263. package/src/service-catalog/sc-record-producer-plugin.ts +0 -2
  264. package/src/service-catalog/service-catalog-base.ts +2 -2
  265. package/src/service-catalog/utils.ts +1 -1
  266. package/src/service-catalog/variable-set-plugin.ts +0 -2
  267. package/src/service-portal/angular-provider-plugin.ts +0 -2
  268. package/src/service-portal/dependency-plugin.ts +0 -2
  269. package/src/service-portal/header-footer-plugin.ts +0 -2
  270. package/src/service-portal/menu-plugin.ts +1 -2
  271. package/src/service-portal/page-plugin.ts +1 -2
  272. package/src/service-portal/page-route-map-plugin.ts +1 -2
  273. package/src/service-portal/portal-plugin.ts +0 -2
  274. package/src/service-portal/theme-plugin.ts +0 -2
  275. package/src/service-portal/widget-plugin.ts +0 -2
  276. package/src/sla-plugin.ts +0 -2
  277. package/src/static-content-plugin.ts +37 -4
  278. package/src/table-plugin.ts +371 -92
  279. package/src/ui-action-plugin.ts +30 -17
  280. package/src/ui-page-plugin.ts +188 -20
  281. package/src/ui-policy-plugin.ts +33 -130
  282. package/src/user-preference-plugin.ts +0 -2
  283. package/src/utils.ts +48 -11
  284. package/src/ux-list-menu-config-plugin.ts +0 -2
  285. package/src/view-plugin.ts +0 -1
  286. package/src/workspace-plugin.ts +0 -2
@@ -59,6 +59,10 @@ const ColumnSchema = zod_1.z
59
59
  '@_use_dynamic_default': BooleanFromString.optional(),
60
60
  '@_reference': zod_1.z.string().optional(),
61
61
  '@_virtual': BooleanFromString.optional(),
62
+ '@_formula': zod_1.z.string().optional(),
63
+ '@_virtual_type': zod_1.z.string().optional(),
64
+ '@_use_reference_qualifier': zod_1.z.string().optional(),
65
+ '@_dynamic_ref_qual': zod_1.z.string().optional(),
62
66
  '@_calculation': zod_1.z.string().optional(),
63
67
  '@_choice_field': zod_1.z.string().optional(),
64
68
  '@_function_definition': zod_1.z.string().optional(),
@@ -157,7 +161,6 @@ const licensingAliases = {
157
161
  };
158
162
  exports.TablePlugin = sdk_build_core_1.Plugin.create({
159
163
  name: 'TablePlugin',
160
- docs: [(0, utils_1.createSdkDocEntry)('Table', ['sys_db_object'])],
161
164
  files: [
162
165
  {
163
166
  matcher: /\.xml$/,
@@ -188,7 +191,11 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
188
191
  records.push(await factory.createRecord({
189
192
  source: file,
190
193
  table,
191
- properties: filterUndefinedProperties(rec),
194
+ properties: {
195
+ ...filterUndefinedProperties(rec),
196
+ // Decorate generated sys_db_object
197
+ ...(key === 'sysDbObject' || key === 'sysDictionary' ? { _bootstrap: true } : {}),
198
+ },
192
199
  }));
193
200
  }
194
201
  }
@@ -256,7 +263,7 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
256
263
  via: 'super_class',
257
264
  },
258
265
  },
259
- toShape(record, { descendants, config }) {
266
+ toShape(record, { descendants, config, compiler }) {
260
267
  const schema = {};
261
268
  let displayColumn;
262
269
  const columns = descendants.query('sys_dictionary');
@@ -291,25 +298,37 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
291
298
  override.transform(({ $ }) => ({
292
299
  baseTable: $.from('base_table'),
293
300
  default: $.from('default_value_override', 'default_value').map((flag, value) => {
294
- return flag.toBoolean()?.getValue() ? value.ifString()?.getValue() : undefined;
301
+ return flag.ifDefined() && flag.toBoolean()?.getValue()
302
+ ? value.ifString()?.getValue()
303
+ : undefined;
295
304
  }),
296
305
  calculation: $.from('calculation_override', 'calculation').map((flag, value) => {
297
- return flag.toBoolean()?.getValue() ? value.ifString()?.getValue() : undefined;
306
+ return flag.ifDefined() && flag.toBoolean()?.getValue()
307
+ ? value.ifString()?.getValue()
308
+ : undefined;
298
309
  }),
299
310
  referenceQualifier: $.from('reference_qual_override', 'reference_qual').map((flag, value) => {
300
- return flag.toBoolean()?.getValue() ? value.ifString()?.getValue() : undefined;
311
+ return flag.ifDefined() && flag.toBoolean()?.getValue()
312
+ ? value.ifString()?.getValue()
313
+ : undefined;
301
314
  }),
302
315
  readOnlyOption: $.from('read_only_option_override', 'read_only_option').map((flag, value) => {
303
- return flag.toBoolean()?.getValue() ? value.ifString()?.getValue() : undefined;
316
+ return flag.ifDefined() && flag.toBoolean()?.getValue()
317
+ ? value.ifString()?.getValue()
318
+ : undefined;
304
319
  }),
305
320
  dependent: $.from('dependent_override', 'dependent').map((flag, value) => {
306
- return flag.toBoolean()?.getValue() ? value.ifString()?.getValue() : undefined;
321
+ return flag.ifDefined() && flag.toBoolean()?.getValue()
322
+ ? value.ifString()?.getValue()
323
+ : undefined;
307
324
  }),
308
325
  mandatory: $.from('mandatory_override', 'mandatory').map((flag, value) => {
309
- return flag.toBoolean()?.getValue() ? value.toBoolean()?.getValue() : undefined;
326
+ return flag.ifDefined() && flag.toBoolean()?.getValue()
327
+ ? value.toBoolean()?.getValue()
328
+ : undefined;
310
329
  }),
311
330
  attributes: $.from('attributes_override', 'attributes').map((flag, attrs) => {
312
- if (!flag.toBoolean()?.getValue() || !attrs.isString()) {
331
+ if (!flag.ifDefined() || !flag.toBoolean()?.getValue() || !attrs.isString()) {
313
332
  return undefined;
314
333
  }
315
334
  const result = {};
@@ -362,6 +381,39 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
362
381
  const originalSource = record.getOriginalSource();
363
382
  // Avoid replacing call expressions with variable statements
364
383
  const writeAsCallExpression = sdk_build_core_1.ts.Node.isNode(originalSource) && originalSource.isKind(sdk_build_core_1.ts.SyntaxKind.CallExpression);
384
+ const tableName = record.get('name').asString().getValue();
385
+ const isBootstrapDbObject = record.get('_bootstrap').ifBoolean()?.getValue() === true;
386
+ const nonBootstrapColumns = columns.filter((col) => col.get('_bootstrap').ifBoolean()?.getValue() !== true);
387
+ // Write as augmentation if we have sys_db_object from bootstrap and columns from elsewhere
388
+ const isAugmentation = isBootstrapDbObject && nonBootstrapColumns.length > 0;
389
+ if (isAugmentation) {
390
+ const augmentsExpression = new sdk_build_core_1.CallExpressionShape({
391
+ source: record,
392
+ callee: 'Table',
393
+ exportName: tableName,
394
+ args: [
395
+ record.transform(({ $ }) => ({
396
+ augments: $.val(tableName),
397
+ schema: $.val(schema),
398
+ })),
399
+ ],
400
+ });
401
+ registerBootstrappedTable(augmentsExpression, schema, compiler);
402
+ return {
403
+ success: true,
404
+ value: writeAsCallExpression
405
+ ? augmentsExpression
406
+ : new sdk_build_core_1.VariableStatementShape({
407
+ source: record,
408
+ isExported: true,
409
+ variableName: new sdk_build_core_1.IdentifierShape({
410
+ source: record,
411
+ name: tableName,
412
+ }),
413
+ initializer: augmentsExpression,
414
+ }),
415
+ };
416
+ }
365
417
  const callExpression = new sdk_build_core_1.CallExpressionShape({
366
418
  source: record,
367
419
  callee: 'Table',
@@ -442,18 +494,24 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
442
494
  .withAliasedKeys(autoNumberAliases)),
443
495
  callerAccess: $.from('caller_access')
444
496
  .map((callerAccess) => {
497
+ // An empty <caller_access/> element arrives as '', not 0 — guard before
498
+ // '' and 0 both mean "none" on the platform — omit from generated Fluent.
499
+ if (callerAccess.isString() && callerAccess.getValue() === '') {
500
+ return '';
501
+ }
445
502
  if (callerAccess.isNumber()) {
446
- return callerAccessLevels[callerAccess.getValue()];
503
+ const value = callerAccess.getValue();
504
+ return value === 0 ? '' : callerAccessLevels[value];
447
505
  }
448
506
  if (callerAccess.isString()) {
449
- const callerAccessString = callerAccess.getValue();
450
- if (!isNaN(Number(callerAccessString))) {
451
- return callerAccessLevels[Number(callerAccessString)];
507
+ const parsed = Number(callerAccess.getValue());
508
+ if (!isNaN(parsed)) {
509
+ return parsed === 0 ? '' : callerAccessLevels[parsed];
452
510
  }
453
511
  }
454
- return 'none';
512
+ return '';
455
513
  })
456
- .def('none'),
514
+ .def(''),
457
515
  display: displayColumn ? $.val(displayColumn) : undefined,
458
516
  extends: $.from('super_class').def(''),
459
517
  extensible: $.from('is_extendable').toBoolean().def(false),
@@ -468,7 +526,7 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
468
526
  }),
469
527
  }));
470
528
  })).def([]),
471
- label: $.map((label) => label.ifString() ??
529
+ label: $.map((label) => label.ifString()?.ifNotEmpty() ??
472
530
  (tableDocumentation.length &&
473
531
  !(0, column_plugin_1.isDefaultDocumentation)('', tableDocumentation, config.defaultLanguage)
474
532
  ? tableDocumentation.map((doc) => doc
@@ -520,12 +578,24 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
520
578
  name: $,
521
579
  readOnly: $.val(collectionRecord?.get('read_only')).toBoolean().def(false),
522
580
  schema: $.val(schema),
581
+ // create_access_controls and user_role only ever arrive here from the
582
+ // sys_db_object record. The platform's bootstrap XML pipeline does not
583
+ // touch either field (no references in /glide/db/bootstrap/xml/ or
584
+ // TableDescriptorProvider.createTableLevelMetaData), and the SDK's own
585
+ // bootstrap output is always paired with sys_db_object_<id>.xml that
586
+ // carries the record values. So the bootstrap-only string path through
587
+ // tableDefToRecordProperties is unreachable for these two fields.
588
+ createAccessControls: $.from('create_access_controls').toBoolean().def(false),
589
+ userRole: $.from('user_role')
590
+ .map((v) => v.ifRecordId()?.getPrimaryKey())
591
+ .def(''),
523
592
  scriptableTable: $.from('scriptable_table').toBoolean().def(false),
524
593
  textIndex: $.val(collectionRecord?.get('text_index')).toBoolean().def(false),
525
594
  }))
526
595
  .withAliasedKeys(tableAliases),
527
596
  ],
528
597
  });
598
+ registerBootstrappedTable(callExpression, schema, compiler);
529
599
  return {
530
600
  success: true,
531
601
  value: writeAsCallExpression
@@ -542,11 +612,12 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
542
612
  };
543
613
  },
544
614
  async toFile(record, { descendants, config, transform }) {
545
- if (config.tableOutputFormat !== 'bootstrap' || config.type === 'configuration' || record.isDeleted()) {
546
- // Defer to record plugin
615
+ if (record.isDeleted()) {
547
616
  return { success: false };
548
617
  }
549
- const tableName = record.get('name').asString().getValue();
618
+ const augmentsValue = record.get('augments').ifString()?.getValue();
619
+ const isAugmentation = augmentsValue !== undefined;
620
+ const tableName = augmentsValue ?? record.get('name').asString().getValue();
550
621
  const columns = descendants.query('sys_dictionary');
551
622
  const choices = descendants.query('sys_choice');
552
623
  const indexes = descendants.query('sys_index');
@@ -554,6 +625,42 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
554
625
  const licensing = descendants.query('ua_table_licensing_config');
555
626
  const autoNumber = descendants.query('sys_number');
556
627
  const overrides = descendants.query('sys_dictionary_override');
628
+ const [documentationFiles, licensingFiles, autoNumberFiles, overrideFiles, sysDictionaryFiles, sysDbObjectFiles,] = await Promise.all([
629
+ generateRecordXml(documentation.filter((doc) => !(0, column_plugin_1.isDefaultDocumentation)(doc.get('element')?.toString().getValue(), [doc], config.defaultLanguage)), config, transform),
630
+ generateRecordXml(licensing.filter((l) => !isDefaultLicenseConfig(tableName, l)), config, transform),
631
+ generateRecordXml(autoNumber, config, transform),
632
+ generateRecordXml(overrides, config, transform),
633
+ generateRecordXml(columns, config, transform, ['_bootstrap']),
634
+ isAugmentation
635
+ ? Promise.resolve([])
636
+ : generateRecordXml([record], config, transform, ['augments', '_bootstrap']),
637
+ ]);
638
+ if (config.type === 'configuration') {
639
+ // No bootstrap XML for configuration projects, just write independent record XML
640
+ const choiceSets = descendants.query('sys_choice_set');
641
+ const [choiceSetFiles, indexFiles] = await Promise.all([
642
+ Promise.all(choiceSets.map((cs) => {
643
+ const csChoices = choices.filter((c) => c.get('name').toString().getValue() === cs.get('name').toString().getValue() &&
644
+ c.get('element').toString().getValue() ===
645
+ cs.get('element').toString().getValue());
646
+ return (0, utils_1.generateChoiceSetFile)(cs, csChoices, config, transform);
647
+ })),
648
+ generateRecordXml(indexes, config, transform),
649
+ ]);
650
+ return {
651
+ success: true,
652
+ value: [
653
+ ...sysDictionaryFiles,
654
+ ...choiceSetFiles,
655
+ ...indexFiles,
656
+ ...sysDbObjectFiles,
657
+ ...documentationFiles,
658
+ ...licensingFiles,
659
+ ...autoNumberFiles,
660
+ ...overrideFiles,
661
+ ],
662
+ };
663
+ }
557
664
  let displayColumn;
558
665
  let collectionRecord;
559
666
  const elements = [];
@@ -595,7 +702,10 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
595
702
  ['read_only_option', column.get('read_only_option').ifString()?.getValue()],
596
703
  ['reference_cascade_rule', column.get('reference_cascade_rule').ifString()?.getValue()],
597
704
  ['calculation', column.get('calculation').ifString()?.getValue()],
598
- ['choice', column.get('choice').ifNumber()?.getValue().toString()],
705
+ // Bootstrap convention: emit `choice="0"` for the platform default ("none").
706
+ // The component (install) path uses an empty `<choice/>` element instead, but
707
+ // bootstrap files conventionally include the literal "0" attribute.
708
+ ['choice', (column.get('choice').ifNumber()?.getValue() ?? 0).toString()],
599
709
  ['choice_table', column.get('choice_table').ifString()?.getValue()],
600
710
  ['choice_field', column.get('choice_field').ifString()?.getValue()],
601
711
  ['display', displayValue?.toString()],
@@ -626,6 +736,23 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
626
736
  ['hint', column.get('hint').ifString()?.getValue()],
627
737
  ['help', column.get('help').ifString()?.getValue()],
628
738
  ['virtual', column.get('virtual').ifBoolean()?.getValue().toString()],
739
+ ['formula', column.get('formula').ifString()?.getValue() || undefined],
740
+ [
741
+ 'virtual_type',
742
+ column.get('virtual_type').ifString()?.getValue() === 'script'
743
+ ? undefined
744
+ : column.get('virtual_type').ifString()?.getValue(),
745
+ ],
746
+ [
747
+ 'use_reference_qualifier',
748
+ column.get('use_reference_qualifier').ifString()?.getValue() === 'simple'
749
+ ? undefined
750
+ : column.get('use_reference_qualifier').ifString()?.getValue(),
751
+ ],
752
+ [
753
+ 'dynamic_ref_qual',
754
+ column.get('dynamic_ref_qual').ifDefined()?.toString().getValue() || undefined,
755
+ ],
629
756
  ['widget', column.get('widget').ifString()?.getValue()],
630
757
  ['reference_qual', column.get('reference_qual').ifString()?.getValue()],
631
758
  ['reference_qual_condition', column.get('reference_qual_condition').ifString()?.getValue()],
@@ -674,7 +801,9 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
674
801
  ['audit', collectionRecord?.get('audit').ifBoolean()?.getValue().toString()],
675
802
  ['display', displayColumn],
676
803
  ['access', record.get('access').ifString()?.getValue()],
677
- ['caller_access', record.get('caller_access').ifNumber()?.getValue().toString()],
804
+ // Bootstrap convention: emit `caller_access="0"` for the platform default ("none").
805
+ // The component (install) path uses an empty `<caller_access/>` element instead.
806
+ ['caller_access', (record.get('caller_access').ifNumber()?.getValue() ?? 0).toString()],
678
807
  ['ws_access', record.get('ws_access').ifBoolean()?.getValue().toString()],
679
808
  ['read_access', record.get('read_access').ifBoolean()?.getValue().toString()],
680
809
  ['alter_access', record.get('alter_access').ifBoolean()?.getValue().toString()],
@@ -683,6 +812,8 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
683
812
  ['delete_access', record.get('delete_access').ifBoolean()?.getValue().toString()],
684
813
  ['actions_access', record.get('actions_access').ifBoolean()?.getValue().toString()],
685
814
  ['client_scripts_access', record.get('client_scripts_access').ifBoolean()?.getValue().toString()],
815
+ // create_access_controls and user_role are omitted: the platform's bootstrap
816
+ // pipeline doesn't read them. They're carried by the paired sys_db_object_<id>.xml.
686
817
  ['scriptable_table', record.get('scriptable_table').ifBoolean()?.getValue().toString()],
687
818
  ['attributes', collectionRecord?.get('attributes').ifString()?.getValue()],
688
819
  ];
@@ -692,10 +823,6 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
692
823
  ...indexElements,
693
824
  ]),
694
825
  ]).end({ prettyPrint: true });
695
- const documentationFiles = await generateRecordXml(documentation.filter((doc) => !(0, column_plugin_1.isDefaultDocumentation)(doc.get('element')?.toString().getValue(), [doc], config.defaultLanguage)), config, transform);
696
- const licensingFiles = await generateRecordXml(licensing.filter((licensing) => !isDefaultLicenseConfig(tableName, licensing)), config, transform);
697
- const autoNumberFiles = await generateRecordXml(autoNumber, config, transform);
698
- const overrideFiles = await generateRecordXml(overrides, config, transform);
699
826
  return {
700
827
  success: true,
701
828
  value: [
@@ -709,6 +836,8 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
709
836
  ...licensingFiles,
710
837
  ...autoNumberFiles,
711
838
  ...overrideFiles,
839
+ ...sysDictionaryFiles,
840
+ ...sysDbObjectFiles,
712
841
  ],
713
842
  };
714
843
  },
@@ -759,20 +888,33 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
759
888
  const table = callExpression.getArgument(0).asObject().withAliasedKeys(tableAliases);
760
889
  (0, utils_1.generateDeprecatedDiagnostics)(table, diagnostics);
761
890
  const relatedRecords = [];
762
- const tableName = table.get('name').asString();
891
+ const augments = table.get('augments').ifString();
892
+ const isAugmentation = augments !== undefined;
893
+ const tableName = isAugmentation ? augments : table.get('name').asString();
763
894
  if (!tableName.getValue().match(tableNameRegex)) {
764
895
  diagnostics.error(table.get('name'), 'Table name must only contain lowercase letters, numbers, and underscores and end with a letter or number');
765
896
  }
766
897
  let ignoreColumnNameCheck = false;
767
898
  const scopeName = config.scope;
768
- const scopeRegex = new RegExp(`^${scopeName}_`);
769
- const globalRegex = /^u_/;
770
- const tableNameMatch = tableName.getValue().match(scopeRegex);
771
- if (!tableNameMatch && !(0, sdk_build_core_1.isSNScope)(scopeName) && scopeName !== 'global') {
899
+ const scopePrefix = scopeName === 'global' ? 'u_' : `${scopeName}_`;
900
+ const prefixRegex = new RegExp(`^${scopePrefix}`);
901
+ const tableNameMatch = tableName.getValue().match(prefixRegex);
902
+ if (isAugmentation) {
903
+ if (tableNameMatch && scopeName !== 'global') {
904
+ const nameNode = tableName.getOriginalNode();
905
+ if (!nameNode?.getParentIfKind(sdk_build_core_1.ts.SyntaxKind.AsExpression)) {
906
+ diagnostics.error(table.get('augments'), `'augments' flag set on in-scope table '${tableName.getValue()}'`);
907
+ }
908
+ else {
909
+ ignoreColumnNameCheck = true;
910
+ }
911
+ }
912
+ }
913
+ else if (!tableNameMatch && !(0, sdk_build_core_1.isSNScope)(scopeName) && scopeName !== 'global') {
772
914
  const nameNode = tableName.getOriginalNode();
773
915
  if (nameNode && !nameNode.getParentIfKind(sdk_build_core_1.ts.SyntaxKind.AsExpression)) {
774
916
  // 'sn' and 'now' scoped apps ignore this validation
775
- diagnostics.error(table.get('name'), `'name' property should start with scope prefix '${scopeName}_'`);
917
+ diagnostics.error(table.get('name'), `'name' property should start with scope prefix '${scopePrefix}'`);
776
918
  }
777
919
  else {
778
920
  ignoreColumnNameCheck = true;
@@ -785,12 +927,11 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
785
927
  if (!exportedByName) {
786
928
  diagnostics.error(callExpression, `Table definition should be exported as a named export with the name '${tableName.getValue()}'`);
787
929
  }
788
- const globalTableNameMatch = tableName.getValue().match(globalRegex);
789
930
  let anyNonPrefixedGlobalColumn = false;
790
- if (scopeName === 'global' && !globalTableNameMatch) {
931
+ if (!isAugmentation && scopeName === 'global' && !tableNameMatch) {
791
932
  const schema = table.get('schema').asObject();
792
933
  for (const [name, _] of schema.entries()) {
793
- if (!name.match(globalRegex)) {
934
+ if (!name.match(prefixRegex)) {
794
935
  anyNonPrefixedGlobalColumn = true;
795
936
  break;
796
937
  }
@@ -799,7 +940,7 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
799
940
  diagnostics.error(table.get('name'), `Global table 'name' property should start with custom prefix 'u_'`);
800
941
  }
801
942
  }
802
- else if (scopeName === 'global') {
943
+ else if (scopeName === 'global' && !isAugmentation) {
803
944
  // Global table starts with custom prefix `u_`, allow any column name prefix
804
945
  ignoreColumnNameCheck = true;
805
946
  }
@@ -880,16 +1021,22 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
880
1021
  }
881
1022
  else {
882
1023
  // Handle regular column - create sys_dictionary record
883
- if (!ignoreColumnNameCheck &&
1024
+ if (isAugmentation && !tableNameMatch) {
1025
+ if (!(0, sdk_build_core_1.isSNScope)(scopeName) && !name.match(prefixRegex)) {
1026
+ diagnostics.error(column.getOriginalNode().getParentIfKind(sdk_build_core_1.ts.SyntaxKind.PropertyAssignment) ??
1027
+ column, `Column name '${name}' must be prefixed with '${scopePrefix}' when augmenting a table`);
1028
+ }
1029
+ }
1030
+ else if (!ignoreColumnNameCheck &&
884
1031
  !tableNameMatch &&
885
1032
  !(0, sdk_build_core_1.isSNScope)(scopeName) &&
886
1033
  scopeName !== 'global' &&
887
- !name.match(scopeRegex)) {
1034
+ !name.match(prefixRegex)) {
888
1035
  // 'sn' and 'now' scoped apps ignore this validation
889
- diagnostics.error(column.getOriginalNode().getParentIfKind(sdk_build_core_1.ts.SyntaxKind.PropertyAssignment) ?? column, `Column name should be prefixed with scope '${scopeName}_' if table name does not contain prefix`);
1036
+ diagnostics.error(column.getOriginalNode().getParentIfKind(sdk_build_core_1.ts.SyntaxKind.PropertyAssignment) ?? column, `Column name should be prefixed with scope '${scopePrefix}' if table name does not contain prefix`);
890
1037
  }
891
- else if (scopeName === 'global' && !globalTableNameMatch && !name.match(globalRegex)) {
892
- diagnostics.error(column.getOriginalNode().getParentIfKind(sdk_build_core_1.ts.SyntaxKind.PropertyAssignment) ?? column, `Column name should be prefixed with 'u_' custom prefix if table name does not contain this prefix, such as when adding columns to an existing global table`);
1038
+ else if (scopeName === 'global' && !tableNameMatch && !name.match(prefixRegex)) {
1039
+ diagnostics.error(column.getOriginalNode().getParentIfKind(sdk_build_core_1.ts.SyntaxKind.PropertyAssignment) ?? column, `Column name should be prefixed with '${scopePrefix}' custom prefix if table name does not contain this prefix, such as when adding columns to an existing global table`);
893
1040
  }
894
1041
  const display = table.get('display').ifString()?.getValue() === name;
895
1042
  const result = await transform.toRecord((0, column_helper_1.addFieldsToColumn)({ name, table: tableName.getValue(), display }, column.as(sdk_build_core_1.CallExpressionShape)));
@@ -1038,27 +1185,30 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
1038
1185
  relatedRecords.push(sysNumberRecord);
1039
1186
  }
1040
1187
  // sys_dictionary (collection)
1041
- relatedRecords.push(await factory.createRecord({
1042
- source: statement ?? callExpression,
1043
- table: 'sys_dictionary',
1044
- properties: table.transform(({ $ }) => ({
1045
- name: $,
1046
- element: $.val(undefined),
1047
- internal_type: $.def('collection'),
1048
- attributes: $.map((attributes) => {
1049
- if (!attributes.isObject()) {
1050
- return undefined;
1051
- }
1052
- const attributesObj = attributes.asObject().getValue();
1053
- return Object.entries(attributesObj)
1054
- .map(([key, value]) => `${key}=${value}`)
1055
- .join(',');
1056
- }).def(''),
1057
- audit: $.def(false),
1058
- read_only: $.from('readOnly').def(false),
1059
- text_index: $.from('textIndex').def(false),
1060
- })),
1061
- }));
1188
+ if (!isAugmentation) {
1189
+ relatedRecords.push(await factory.createRecord({
1190
+ source: statement ?? callExpression,
1191
+ table: 'sys_dictionary',
1192
+ properties: table.transform(({ $ }) => ({
1193
+ name: $,
1194
+ element: $.val(undefined),
1195
+ internal_type: $.def('collection'),
1196
+ active: $.val(true),
1197
+ attributes: $.map((attributes) => {
1198
+ if (!attributes.isObject()) {
1199
+ return undefined;
1200
+ }
1201
+ const attributesObj = attributes.asObject().getValue();
1202
+ return Object.entries(attributesObj)
1203
+ .map(([key, value]) => `${key}=${value}`)
1204
+ .join(',');
1205
+ }).def(''),
1206
+ audit: $.def(false),
1207
+ read_only: $.from('readOnly').def(false),
1208
+ text_index: $.from('textIndex').def(false),
1209
+ })),
1210
+ }));
1211
+ }
1062
1212
  const hasAction = (actionName, actions) => {
1063
1213
  return actions
1064
1214
  .ifArray()
@@ -1073,6 +1223,16 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
1073
1223
  keys: { name: ext },
1074
1224
  })
1075
1225
  : ext.ifDefined()?.toRecordId();
1226
+ const userRoleField = table.get('userRole');
1227
+ const userRoleReference = userRoleField.isString()
1228
+ ? userRoleField.getValue() === ''
1229
+ ? undefined
1230
+ : await factory.createReference({
1231
+ source: userRoleField,
1232
+ table: 'sys_user_role',
1233
+ keys: { name: userRoleField },
1234
+ })
1235
+ : userRoleField.ifDefined()?.toRecordId();
1076
1236
  // sys_db_object
1077
1237
  const tableRecord = await factory.createRecord({
1078
1238
  source: statement ?? callExpression,
@@ -1084,7 +1244,15 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
1084
1244
  ws_access: $.from('allowWebServiceAccess').toBoolean().def(false),
1085
1245
  number_ref: $.val(numberRef),
1086
1246
  access: $.from('accessibleFrom').def('public'),
1087
- caller_access: $.from('callerAccess').map((callerAccess) => callerAccessLevels.indexOf((callerAccess.ifString()?.getValue() ?? 'none'))),
1247
+ caller_access: $.from('callerAccess').map((callerAccess) => {
1248
+ const value = callerAccess.ifString()?.getValue();
1249
+ if (!value) {
1250
+ return undefined;
1251
+ }
1252
+ const index = callerAccessLevels.indexOf(value);
1253
+ // index 0 ('none') is the platform default — emit empty <caller_access/>, matching stock.
1254
+ return index > 0 ? index : undefined;
1255
+ }),
1088
1256
  super_class: $.val(parentReference),
1089
1257
  read_access: $.from('actions')
1090
1258
  .map((actions) => hasAction('read', actions))
@@ -1101,8 +1269,12 @@ exports.TablePlugin = sdk_build_core_1.Plugin.create({
1101
1269
  is_extendable: $.from('extensible').toBoolean().def(false),
1102
1270
  label: $.map((label) => (0, column_to_record_1.getLabelForDefaultLanguage)(label, config.defaultLanguage)),
1103
1271
  live_feed_enabled: $.from('liveFeed').toBoolean().def(false),
1104
- name: $,
1272
+ name: $.from('name', 'augments').map((nameVal, augmentsVal) => augmentsVal.ifString() ?? nameVal),
1273
+ create_access_controls: $.from('createAccessControls').toBoolean().def(false),
1274
+ user_role: $.val(userRoleReference),
1105
1275
  scriptable_table: $.from('scriptableTable').toBoolean().def(false),
1276
+ // Controls toFile output, not written to record XML
1277
+ augments: $.from('augments'),
1106
1278
  })),
1107
1279
  });
1108
1280
  if (exportedByName) {
@@ -1186,6 +1358,16 @@ function parseTableBootstrapXml(xml) {
1186
1358
  useDynamicDefault: column['@_use_dynamic_default'],
1187
1359
  reference: column['@_reference'],
1188
1360
  isVirtual: column['@_virtual'],
1361
+ formula: column['@_formula'],
1362
+ virtualType: column['@_virtual_type'] === 'script' || column['@_virtual_type'] === 'formula'
1363
+ ? column['@_virtual_type']
1364
+ : undefined,
1365
+ useReferenceQualifier: column['@_use_reference_qualifier'] === 'simple' ||
1366
+ column['@_use_reference_qualifier'] === 'dynamic' ||
1367
+ column['@_use_reference_qualifier'] === 'advanced'
1368
+ ? column['@_use_reference_qualifier']
1369
+ : undefined,
1370
+ dynamicRefQual: column['@_dynamic_ref_qual'],
1189
1371
  calculation: column['@_calculation'],
1190
1372
  choiceField: column['@_choice_field'],
1191
1373
  functionDefinition: column['@_function_definition'],
@@ -1257,6 +1439,8 @@ function parseTableBootstrapXml(xml) {
1257
1439
  actionsAccess: table['@_actions_access'],
1258
1440
  readAccess: table['@_read_access'],
1259
1441
  isExtendable: table['@_is_extendable'],
1442
+ createAccessControls: table['@_create_access_controls'],
1443
+ userRole: table['@_user_role'],
1260
1444
  scriptableTable: table['@_scriptable_table'],
1261
1445
  attributes: table['@_attributes'],
1262
1446
  };
@@ -1267,6 +1451,8 @@ function tableDefToRecordProperties(tableDef, tableDefaultLanguage = 'en') {
1267
1451
  label: tableDef.label,
1268
1452
  super_class: tableDef.extends,
1269
1453
  is_extendable: tableDef.isExtendable,
1454
+ create_access_controls: tableDef.createAccessControls,
1455
+ user_role: tableDef.userRole,
1270
1456
  scriptable_table: tableDef.scriptableTable,
1271
1457
  client_scripts_access: tableDef.clientScriptsAccess,
1272
1458
  ws_access: tableDef.wsAccess,
@@ -1313,6 +1499,10 @@ function tableDefToRecordProperties(tableDef, tableDefaultLanguage = 'en') {
1313
1499
  use_dynamic_default: column.useDynamicDefault,
1314
1500
  reference: column.reference,
1315
1501
  virtual: column.isVirtual,
1502
+ formula: column.formula,
1503
+ virtual_type: column.virtualType,
1504
+ use_reference_qualifier: column.useReferenceQualifier,
1505
+ dynamic_ref_qual: column.dynamicRefQual,
1316
1506
  default: column.defaultValue,
1317
1507
  calculation: column.calculation,
1318
1508
  choice_field: column.choiceField,
@@ -1392,6 +1582,10 @@ function tableDefToRecordProperties(tableDef, tableDefaultLanguage = 'en') {
1392
1582
  use_dynamic_default: undefined,
1393
1583
  reference: undefined,
1394
1584
  virtual: undefined,
1585
+ formula: undefined,
1586
+ virtual_type: undefined,
1587
+ use_reference_qualifier: undefined,
1588
+ dynamic_ref_qual: undefined,
1395
1589
  default: undefined,
1396
1590
  calculation: undefined,
1397
1591
  choice_field: undefined,
@@ -1443,7 +1637,7 @@ function addTableToGlobalGeneratedFile(tableArg, sourceFilePath, compiler) {
1443
1637
  namedImports: [],
1444
1638
  };
1445
1639
  const generatedTableFile = compiler.getGeneratedTableFile();
1446
- const tableName = tableArg.get('name').asString().getValue();
1640
+ const tableName = tableArg.get('augments').ifString()?.getValue() ?? tableArg.get('name').asString().getValue();
1447
1641
  if (!(tableName.trim().length > 0 && tableName.match(tableNameRegex))) {
1448
1642
  return;
1449
1643
  }
@@ -1502,6 +1696,48 @@ function addTableToGlobalGeneratedFile(tableArg, sourceFilePath, compiler) {
1502
1696
  });
1503
1697
  }
1504
1698
  }
1699
+ /**
1700
+ * Records a bootstrap-derived Table() shape into $$GENERATED$$_bootstrapped_tables.ts so that other plugins (e.g. RecordPlugin)
1701
+ * can resolve Data<T> column types via TypeScript during the same transform pass — no sys_dictionary query needed.
1702
+ *
1703
+ * The `declare global` augmentation lives inside the bootstrapped file (referencing its LOCAL `typeof tableName` export) rather
1704
+ * than the common table file. That avoids the duplicate-import error when a pre-existing Fluent Table() of the same name was
1705
+ * already wired into the common file, and TypeScript still merges the two TableSchemas interface declarations so both
1706
+ * contribute their columns to the resolved Data<T>.
1707
+ */
1708
+ function registerBootstrappedTable(tableCall, schema, compiler) {
1709
+ const file = compiler.getGeneratedBootstrappedTablesFile();
1710
+ if (!file || Object.keys(schema).length === 0) {
1711
+ return;
1712
+ }
1713
+ const tableArg = tableCall.getArgument(0).asObject();
1714
+ const tableName = tableArg.get('augments').ifString()?.getValue() ?? tableArg.get('name').asString().getValue();
1715
+ const tableSchemas = file.getModule('global')?.getModule('Now')?.getModule('Internal')?.getModule('TableSchemas');
1716
+ const tables = file.getModule('global')?.getModule('Now')?.getModule('Internal')?.getInterface('Tables');
1717
+ if (!tableSchemas || !tables) {
1718
+ return;
1719
+ }
1720
+ const coreImport = file.getImportDeclaration('@servicenow/sdk/core');
1721
+ const existingImports = new Set(coreImport?.getNamedImports().map((n) => n.getName()));
1722
+ for (const callee of new Set(Object.values(schema).map((s) => s.getCallee()))) {
1723
+ if (!existingImports.has(callee)) {
1724
+ coreImport?.addNamedImport(callee);
1725
+ }
1726
+ }
1727
+ // Replace any existing export (re-transform of same XML), then write the shape's rendered code.
1728
+ file.getVariableDeclaration(tableName)?.getVariableStatement()?.remove();
1729
+ file.addVariableStatement({
1730
+ isExported: true,
1731
+ declarationKind: sdk_build_core_1.ts.VariableDeclarationKind.Const,
1732
+ declarations: [{ name: tableName, initializer: tableCall.getCode() }],
1733
+ });
1734
+ if (!tableSchemas.getInterface(tableName)) {
1735
+ tableSchemas.addInterface({ name: tableName, extends: [`Helper<typeof ${tableName}>`] });
1736
+ }
1737
+ if (!tables.getProperty(tableName)) {
1738
+ tables.addProperty({ name: tableName, type: `Table<TableSchemas.${tableName}>` });
1739
+ }
1740
+ }
1505
1741
  function filterUndefinedProperties(obj) {
1506
1742
  return Object.fromEntries(Object.entries(obj).filter(([_, value]) => value !== undefined));
1507
1743
  }
@@ -1519,7 +1755,7 @@ function createElement(name, attributes = [], children = []) {
1519
1755
  }
1520
1756
  return element;
1521
1757
  }
1522
- async function generateRecordXml(records, config, transform) {
1758
+ async function generateRecordXml(records, config, transform, excludeFields = []) {
1523
1759
  const files = [];
1524
1760
  for (const record of records) {
1525
1761
  const recordBuilder = (0, sdk_build_core_1.unloadBuilder)({ scope: config.scope, scopeId: config.scopeId, table: record.getTable() });
@@ -1528,6 +1764,7 @@ async function generateRecordXml(records, config, transform) {
1528
1764
  record
1529
1765
  .entries()
1530
1766
  .sort(([a], [b]) => a.localeCompare(b))
1767
+ .filter(([prop]) => excludeFields.length === 0 || !excludeFields.includes(prop))
1531
1768
  .forEach(([prop, shape]) => builder.field(prop, shape));
1532
1769
  files.push({
1533
1770
  source: record,