@jigx/sdk-tools 1.2.0-next.2 → 1.2.0-next.4

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 (200) hide show
  1. package/README.md +35 -44
  2. package/dist/cli.js +83 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/migrator/converters/app-index.d.ts +53 -0
  9. package/dist/migrator/converters/app-index.d.ts.map +1 -0
  10. package/dist/migrator/converters/app-index.js +206 -0
  11. package/dist/migrator/converters/app-index.js.map +1 -0
  12. package/dist/migrator/converters/assets.d.ts +7 -0
  13. package/dist/migrator/converters/assets.d.ts.map +1 -0
  14. package/dist/migrator/converters/assets.js +58 -0
  15. package/dist/migrator/converters/assets.js.map +1 -0
  16. package/dist/migrator/converters/components.d.ts +4 -0
  17. package/dist/migrator/converters/components.d.ts.map +1 -0
  18. package/dist/migrator/converters/components.js +7 -0
  19. package/dist/migrator/converters/components.js.map +1 -0
  20. package/dist/migrator/converters/databases.d.ts +9 -0
  21. package/dist/migrator/converters/databases.d.ts.map +1 -0
  22. package/dist/migrator/converters/databases.js +45 -0
  23. package/dist/migrator/converters/databases.js.map +1 -0
  24. package/dist/migrator/converters/datasources.d.ts +46 -0
  25. package/dist/migrator/converters/datasources.d.ts.map +1 -0
  26. package/dist/migrator/converters/datasources.js +445 -0
  27. package/dist/migrator/converters/datasources.js.map +1 -0
  28. package/dist/migrator/converters/functions.d.ts +13 -0
  29. package/dist/migrator/converters/functions.d.ts.map +1 -0
  30. package/dist/migrator/converters/functions.js +444 -0
  31. package/dist/migrator/converters/functions.js.map +1 -0
  32. package/dist/migrator/converters/index.d.ts +11 -0
  33. package/dist/migrator/converters/index.d.ts.map +1 -0
  34. package/dist/migrator/converters/index.js +9 -0
  35. package/dist/migrator/converters/index.js.map +1 -0
  36. package/dist/migrator/converters/scripts.d.ts +10 -0
  37. package/dist/migrator/converters/scripts.d.ts.map +1 -0
  38. package/dist/migrator/converters/scripts.js +28 -0
  39. package/dist/migrator/converters/scripts.js.map +1 -0
  40. package/dist/migrator/converters/translations.d.ts +5 -0
  41. package/dist/migrator/converters/translations.d.ts.map +1 -0
  42. package/dist/migrator/converters/translations.js +25 -0
  43. package/dist/migrator/converters/translations.js.map +1 -0
  44. package/dist/migrator/converters/types.d.ts +35 -0
  45. package/dist/migrator/converters/types.d.ts.map +1 -0
  46. package/dist/migrator/converters/types.js +2 -0
  47. package/dist/migrator/converters/types.js.map +1 -0
  48. package/dist/migrator/errors.d.ts +5 -0
  49. package/dist/migrator/errors.d.ts.map +1 -0
  50. package/dist/migrator/errors.js +8 -0
  51. package/dist/migrator/errors.js.map +1 -0
  52. package/dist/migrator/index.d.ts +6 -0
  53. package/dist/migrator/index.d.ts.map +1 -0
  54. package/dist/migrator/index.js +4 -0
  55. package/dist/migrator/index.js.map +1 -0
  56. package/dist/migrator/migrate.d.ts +75 -0
  57. package/dist/migrator/migrate.d.ts.map +1 -0
  58. package/dist/migrator/migrate.js +439 -0
  59. package/dist/migrator/migrate.js.map +1 -0
  60. package/dist/migrator/module-writer.d.ts +26 -0
  61. package/dist/migrator/module-writer.d.ts.map +1 -0
  62. package/dist/migrator/module-writer.js +26 -0
  63. package/dist/migrator/module-writer.js.map +1 -0
  64. package/dist/migrator/nodes/action-definition.d.ts +11 -0
  65. package/dist/migrator/nodes/action-definition.d.ts.map +1 -0
  66. package/dist/migrator/nodes/action-definition.js +75 -0
  67. package/dist/migrator/nodes/action-definition.js.map +1 -0
  68. package/dist/migrator/nodes/app-events.d.ts +29 -0
  69. package/dist/migrator/nodes/app-events.d.ts.map +1 -0
  70. package/dist/migrator/nodes/app-events.js +40 -0
  71. package/dist/migrator/nodes/app-events.js.map +1 -0
  72. package/dist/migrator/nodes/attach.d.ts +61 -0
  73. package/dist/migrator/nodes/attach.d.ts.map +1 -0
  74. package/dist/migrator/nodes/attach.js +174 -0
  75. package/dist/migrator/nodes/attach.js.map +1 -0
  76. package/dist/migrator/nodes/builder-access.d.ts +16 -0
  77. package/dist/migrator/nodes/builder-access.d.ts.map +1 -0
  78. package/dist/migrator/nodes/builder-access.js +81 -0
  79. package/dist/migrator/nodes/builder-access.js.map +1 -0
  80. package/dist/migrator/nodes/codegen.d.ts +33 -0
  81. package/dist/migrator/nodes/codegen.d.ts.map +1 -0
  82. package/dist/migrator/nodes/codegen.js +77 -0
  83. package/dist/migrator/nodes/codegen.js.map +1 -0
  84. package/dist/migrator/nodes/index.d.ts +6 -0
  85. package/dist/migrator/nodes/index.d.ts.map +1 -0
  86. package/dist/migrator/nodes/index.js +6 -0
  87. package/dist/migrator/nodes/index.js.map +1 -0
  88. package/dist/migrator/nodes/node-shape.d.ts +39 -0
  89. package/dist/migrator/nodes/node-shape.d.ts.map +1 -0
  90. package/dist/migrator/nodes/node-shape.js +65 -0
  91. package/dist/migrator/nodes/node-shape.js.map +1 -0
  92. package/dist/migrator/nodes/probe.d.ts +66 -0
  93. package/dist/migrator/nodes/probe.d.ts.map +1 -0
  94. package/dist/migrator/nodes/probe.js +46 -0
  95. package/dist/migrator/nodes/probe.js.map +1 -0
  96. package/dist/migrator/nodes/rules/action-list.d.ts +4 -0
  97. package/dist/migrator/nodes/rules/action-list.d.ts.map +1 -0
  98. package/dist/migrator/nodes/rules/action-list.js +14 -0
  99. package/dist/migrator/nodes/rules/action-list.js.map +1 -0
  100. package/dist/migrator/nodes/rules/action-slots.d.ts +13 -0
  101. package/dist/migrator/nodes/rules/action-slots.d.ts.map +1 -0
  102. package/dist/migrator/nodes/rules/action-slots.js +34 -0
  103. package/dist/migrator/nodes/rules/action-slots.js.map +1 -0
  104. package/dist/migrator/nodes/rules/custom-component.d.ts +7 -0
  105. package/dist/migrator/nodes/rules/custom-component.d.ts.map +1 -0
  106. package/dist/migrator/nodes/rules/custom-component.js +8 -0
  107. package/dist/migrator/nodes/rules/custom-component.js.map +1 -0
  108. package/dist/migrator/nodes/rules/dropdown.d.ts +4 -0
  109. package/dist/migrator/nodes/rules/dropdown.d.ts.map +1 -0
  110. package/dist/migrator/nodes/rules/dropdown.js +3 -0
  111. package/dist/migrator/nodes/rules/dropdown.js.map +1 -0
  112. package/dist/migrator/nodes/rules/execute-entity.d.ts +7 -0
  113. package/dist/migrator/nodes/rules/execute-entity.d.ts.map +1 -0
  114. package/dist/migrator/nodes/rules/execute-entity.js +40 -0
  115. package/dist/migrator/nodes/rules/execute-entity.js.map +1 -0
  116. package/dist/migrator/nodes/rules/field-row.d.ts +4 -0
  117. package/dist/migrator/nodes/rules/field-row.d.ts.map +1 -0
  118. package/dist/migrator/nodes/rules/field-row.js +3 -0
  119. package/dist/migrator/nodes/rules/field-row.js.map +1 -0
  120. package/dist/migrator/nodes/rules/index.d.ts +16 -0
  121. package/dist/migrator/nodes/rules/index.d.ts.map +1 -0
  122. package/dist/migrator/nodes/rules/index.js +42 -0
  123. package/dist/migrator/nodes/rules/index.js.map +1 -0
  124. package/dist/migrator/nodes/rules/list-item.d.ts +7 -0
  125. package/dist/migrator/nodes/rules/list-item.d.ts.map +1 -0
  126. package/dist/migrator/nodes/rules/list-item.js +40 -0
  127. package/dist/migrator/nodes/rules/list-item.js.map +1 -0
  128. package/dist/migrator/nodes/rules/list.d.ts +4 -0
  129. package/dist/migrator/nodes/rules/list.d.ts.map +1 -0
  130. package/dist/migrator/nodes/rules/list.js +7 -0
  131. package/dist/migrator/nodes/rules/list.js.map +1 -0
  132. package/dist/migrator/nodes/rules/method-names.d.ts +10 -0
  133. package/dist/migrator/nodes/rules/method-names.d.ts.map +1 -0
  134. package/dist/migrator/nodes/rules/method-names.js +33 -0
  135. package/dist/migrator/nodes/rules/method-names.js.map +1 -0
  136. package/dist/migrator/nodes/rules/screen-slots.d.ts +10 -0
  137. package/dist/migrator/nodes/rules/screen-slots.d.ts.map +1 -0
  138. package/dist/migrator/nodes/rules/screen-slots.js +9 -0
  139. package/dist/migrator/nodes/rules/screen-slots.js.map +1 -0
  140. package/dist/migrator/nodes/rules/set-jig-state.d.ts +4 -0
  141. package/dist/migrator/nodes/rules/set-jig-state.d.ts.map +1 -0
  142. package/dist/migrator/nodes/rules/set-jig-state.js +9 -0
  143. package/dist/migrator/nodes/rules/set-jig-state.js.map +1 -0
  144. package/dist/migrator/nodes/rules/state-key.d.ts +7 -0
  145. package/dist/migrator/nodes/rules/state-key.d.ts.map +1 -0
  146. package/dist/migrator/nodes/rules/state-key.js +16 -0
  147. package/dist/migrator/nodes/rules/state-key.js.map +1 -0
  148. package/dist/migrator/nodes/rules/summary.d.ts +7 -0
  149. package/dist/migrator/nodes/rules/summary.d.ts.map +1 -0
  150. package/dist/migrator/nodes/rules/summary.js +16 -0
  151. package/dist/migrator/nodes/rules/summary.js.map +1 -0
  152. package/dist/migrator/nodes/rules/sync-entities.d.ts +7 -0
  153. package/dist/migrator/nodes/rules/sync-entities.d.ts.map +1 -0
  154. package/dist/migrator/nodes/rules/sync-entities.js +17 -0
  155. package/dist/migrator/nodes/rules/sync-entities.js.map +1 -0
  156. package/dist/migrator/nodes/rules/types.d.ts +35 -0
  157. package/dist/migrator/nodes/rules/types.d.ts.map +1 -0
  158. package/dist/migrator/nodes/rules/types.js +7 -0
  159. package/dist/migrator/nodes/rules/types.js.map +1 -0
  160. package/dist/migrator/nodes/screen.d.ts +13 -0
  161. package/dist/migrator/nodes/screen.d.ts.map +1 -0
  162. package/dist/migrator/nodes/screen.js +403 -0
  163. package/dist/migrator/nodes/screen.js.map +1 -0
  164. package/dist/migrator/normalize.d.ts +42 -0
  165. package/dist/migrator/normalize.d.ts.map +1 -0
  166. package/dist/migrator/normalize.js +167 -0
  167. package/dist/migrator/normalize.js.map +1 -0
  168. package/dist/migrator/project-writer.d.ts +34 -0
  169. package/dist/migrator/project-writer.d.ts.map +1 -0
  170. package/dist/migrator/project-writer.js +65 -0
  171. package/dist/migrator/project-writer.js.map +1 -0
  172. package/dist/migrator/prune.d.ts +58 -0
  173. package/dist/migrator/prune.d.ts.map +1 -0
  174. package/dist/migrator/prune.js +171 -0
  175. package/dist/migrator/prune.js.map +1 -0
  176. package/dist/migrator/read-solution.d.ts +38 -0
  177. package/dist/migrator/read-solution.d.ts.map +1 -0
  178. package/dist/migrator/read-solution.js +144 -0
  179. package/dist/migrator/read-solution.js.map +1 -0
  180. package/dist/migrator/report.d.ts +76 -0
  181. package/dist/migrator/report.d.ts.map +1 -0
  182. package/dist/migrator/report.js +53 -0
  183. package/dist/migrator/report.js.map +1 -0
  184. package/dist/migrator/ts-printer.d.ts +19 -0
  185. package/dist/migrator/ts-printer.d.ts.map +1 -0
  186. package/dist/migrator/ts-printer.js +70 -0
  187. package/dist/migrator/ts-printer.js.map +1 -0
  188. package/dist/migrator/verify-entity.d.ts +21 -0
  189. package/dist/migrator/verify-entity.d.ts.map +1 -0
  190. package/dist/migrator/verify-entity.js +22 -0
  191. package/dist/migrator/verify-entity.js.map +1 -0
  192. package/dist/scaffolder/index.d.ts +1 -0
  193. package/dist/scaffolder/index.d.ts.map +1 -1
  194. package/dist/scaffolder/index.js +1 -0
  195. package/dist/scaffolder/index.js.map +1 -1
  196. package/dist/scaffolder/templates.d.ts +11 -2
  197. package/dist/scaffolder/templates.d.ts.map +1 -1
  198. package/dist/scaffolder/templates.js +7 -3
  199. package/dist/scaffolder/templates.js.map +1 -1
  200. package/package.json +2 -1
@@ -0,0 +1,58 @@
1
+ import { isPlainObject } from '../normalize.js';
2
+ import { countNodes } from '../report.js';
3
+ import { lit, str } from '../ts-printer.js';
4
+ const UNSUPPORTED = {
5
+ type: 'skip',
6
+ gapId: 'assets:unsupported-shape',
7
+ reason: 'only images, icons and theme.palette assets have typed calls',
8
+ };
9
+ function isStringList(value) {
10
+ return Array.isArray(value) && value.every((item) => typeof item === 'string');
11
+ }
12
+ function listArgs(values) {
13
+ return values.map((value) => ` ${str(value)},\n`).join('');
14
+ }
15
+ function convertValue(options) {
16
+ const { id, value } = options;
17
+ if (id === 'images' && isStringList(value) && value.length > 0) {
18
+ return {
19
+ code: `app.images(\n${listArgs(value)} )`,
20
+ run: (app) => {
21
+ app.images(...value);
22
+ },
23
+ };
24
+ }
25
+ if (id === 'icons' && isStringList(value) && value.length > 0) {
26
+ return {
27
+ code: `app.icons(\n${listArgs(value)} )`,
28
+ run: (app) => {
29
+ app.icons(...value);
30
+ },
31
+ };
32
+ }
33
+ if (id === 'theme' &&
34
+ isPlainObject(value) &&
35
+ Object.keys(value).length === 1 &&
36
+ 'palette' in value &&
37
+ countNodes({ value: value.palette, asRoot: false }) === 0) {
38
+ const palette = value.palette;
39
+ return {
40
+ code: `app.themePalette(${lit(palette, ' ')})`,
41
+ run: (app) => {
42
+ app.themePalette(palette);
43
+ },
44
+ };
45
+ }
46
+ return undefined;
47
+ }
48
+ /**
49
+ * `assets/<id>.jigx` (`{ <id>: value }`) → `app.images(…)`, `app.icons(…)` or `app.themePalette(…)`.
50
+ */
51
+ export function convertAsset(entry) {
52
+ const { id, entity } = entry;
53
+ if (!isPlainObject(entity) || Object.keys(entity).length !== 1 || !(id in entity))
54
+ return UNSUPPORTED;
55
+ const statement = convertValue({ id, value: entity[id] });
56
+ return statement ? { type: 'statements', statements: [statement] } : UNSUPPORTED;
57
+ }
58
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../../src/migrator/converters/assets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { type EntityConverter } from './types.js';
2
+ /** Custom component definitions have no core-sdk builder: an entity-level gap. */
3
+ export declare const convertComponent: EntityConverter;
4
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../../src/migrator/converters/components.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,kFAAkF;AAClF,eAAO,MAAM,gBAAgB,EAAE,eAI7B,CAAA"}
@@ -0,0 +1,7 @@
1
+ /** Custom component definitions have no core-sdk builder: an entity-level gap. */
2
+ export const convertComponent = () => ({
3
+ type: 'skip',
4
+ gapId: 'components:definition-builder',
5
+ reason: 'core-sdk has no builder for custom component definitions',
6
+ });
7
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../../../src/migrator/converters/components.ts"],"names":[],"mappings":"AAEA,kFAAkF;AAClF,MAAM,CAAC,MAAM,gBAAgB,GAAoB,GAAG,EAAE,CAAC,CAAC;IACtD,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,+BAA+B;IACtC,MAAM,EAAE,0DAA0D;CACnE,CAAC,CAAA"}
@@ -0,0 +1,9 @@
1
+ import { type LegacyEntry } from '../read-solution.js';
2
+ import { type EntityConversion } from './types.js';
3
+ /**
4
+ * `databases/default.jigx` → `app.addDatabase.default.table(...)`.
5
+ *
6
+ * Only the `default` database with `null` table definitions has a typed builder.
7
+ */
8
+ export declare function convertDatabase(entry: LegacyEntry): EntityConversion;
9
+ //# sourceMappingURL=databases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"databases.d.ts","sourceRoot":"","sources":["../../../src/migrator/converters/databases.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEtD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,gBAAgB,CAoCpE"}
@@ -0,0 +1,45 @@
1
+ import { isPlainObject } from '../normalize.js';
2
+ import { str } from '../ts-printer.js';
3
+ /**
4
+ * `databases/default.jigx` → `app.addDatabase.default.table(...)`.
5
+ *
6
+ * Only the `default` database with `null` table definitions has a typed builder.
7
+ */
8
+ export function convertDatabase(entry) {
9
+ const { id, entity } = entry;
10
+ if (id !== 'default' || !isPlainObject(entity)) {
11
+ return {
12
+ type: 'skip',
13
+ gapId: 'databases:unsupported-shape',
14
+ reason: 'only the default database is typed',
15
+ };
16
+ }
17
+ const { databaseId, tables, ...rest } = entity;
18
+ const extraKeys = Object.keys(rest);
19
+ const idMatches = databaseId === undefined || databaseId === id;
20
+ const tablesTyped = tables === undefined ||
21
+ (isPlainObject(tables) && Object.values(tables).every((t) => t === null));
22
+ if (extraKeys.length > 0 || !idMatches || !tablesTyped) {
23
+ return {
24
+ type: 'skip',
25
+ gapId: 'databases:unsupported-shape',
26
+ reason: 'database keys other than null tables have no typed builder',
27
+ };
28
+ }
29
+ const names = isPlainObject(tables) ? Object.keys(tables) : [];
30
+ if (names.length === 0)
31
+ return { type: 'statements', statements: [] };
32
+ const args = names.map((name) => ` ${str(name)},\n`).join('');
33
+ return {
34
+ type: 'statements',
35
+ statements: [
36
+ {
37
+ code: `app.addDatabase.default.table(\n${args} )`,
38
+ run: (app) => {
39
+ app.addDatabase.default.table(...names);
40
+ },
41
+ },
42
+ ],
43
+ };
44
+ }
45
+ //# sourceMappingURL=databases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"databases.js","sourceRoot":"","sources":["../../../src/migrator/converters/databases.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE/C,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAGtC;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;IAC5B,IAAI,EAAE,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/C,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,6BAA6B;YACpC,MAAM,EAAE,oCAAoC;SAC7C,CAAA;IACH,CAAC;IACD,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAA;IAC9C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACnC,MAAM,SAAS,GAAG,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,EAAE,CAAA;IAC/D,MAAM,WAAW,GACf,MAAM,KAAK,SAAS;QACpB,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAA;IAC3E,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,WAAW,EAAE,CAAC;QACvD,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,6BAA6B;YACpC,MAAM,EAAE,4DAA4D;SACrE,CAAA;IACH,CAAC;IACD,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC9D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,EAAE,CAAA;IACrE,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChE,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV;gBACE,IAAI,EAAE,mCAAmC,IAAI,KAAK;gBAClD,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;oBACX,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAA;gBACzC,CAAC;aACF;SACF;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { type LegacyEntry } from '../read-solution.js';
2
+ import { type NodePathSegment } from '../report.js';
3
+ import { type EntityConversion } from './types.js';
4
+ /** Where a datasource is declared: `datasources/<id>.jigx` or a jig's `datasources` map. */
5
+ export type DatasourceScope = 'app' | 'screen';
6
+ /** A key skipped inside a verified datasource; `path` is relative to the datasource. */
7
+ interface DatasourceGap {
8
+ /** Reason slug: the gap id is `datasources:<slug>` or `jig:datasource-<slug>`. */
9
+ readonly slug: string;
10
+ readonly reason: string;
11
+ readonly skippedNodes: number;
12
+ readonly path: readonly NodePathSegment[];
13
+ }
14
+ export type DatasourceConversion = {
15
+ readonly type: 'skip';
16
+ readonly slug: string;
17
+ readonly reason: string;
18
+ } | {
19
+ readonly type: 'typed';
20
+ /** The `<parentExpr>.addDatasource.<factory>(…)` statement at the register-body indent. */
21
+ readonly code: (parentExpr: string) => string;
22
+ /** Replays the verified calls on an `ApplicationBuilder` or a screen builder. */
23
+ readonly attach: (host: unknown) => void;
24
+ readonly gaps: readonly DatasourceGap[];
25
+ };
26
+ /**
27
+ * Converts one legacy datasource into a typed `addDatasource.<factory>(…)` call chain.
28
+ *
29
+ * - `datasource.sqlite` (local or dynamic): `entity`/`entityPackaged`, `parameter`,
30
+ * `queryParameter`, `rewriteQuery`, `isDocument`, `jsonProperties`, `query`
31
+ * - `datasource.static`: `data` in the factory input
32
+ * - `datasource.reference` (screen scope only): `descriptor` plus `param` per input
33
+ *
34
+ * Optional keys and options that do not verify are skipped one by one (`key-<key>`,
35
+ * `option-<key>`); the whole datasource is then verified against the pruned legacy.
36
+ * A datasource with no typed constructor, or whose required parts do not verify, is skipped.
37
+ */
38
+ export declare function convertDatasourceDefinition(options: {
39
+ readonly key: string;
40
+ readonly legacy: unknown;
41
+ readonly scope: DatasourceScope;
42
+ }): DatasourceConversion;
43
+ /** `datasources/<id>.jigx` → `app.addDatasource.<factory>(…)`; gaps are `datasources:<slug>`. */
44
+ export declare function convertDatasource(entry: LegacyEntry): EntityConversion;
45
+ export {};
46
+ //# sourceMappingURL=datasources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datasources.d.ts","sourceRoot":"","sources":["../../../src/migrator/converters/datasources.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,cAAc,CAAA;AAE/D,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,4FAA4F;AAC5F,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,CAAA;AAE9C,wFAAwF;AACxF,UAAU,aAAa;IACrB,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,eAAe,EAAE,CAAA;CAC1C;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzE;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,2FAA2F;IAC3F,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAA;IAC7C,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACxC,QAAQ,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,CAAA;CACxC,CAAA;AA6bL;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE;IACnD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;CAChC,GAAG,oBAAoB,CAmBvB;AAED,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,gBAAgB,CAwBtE"}
@@ -0,0 +1,445 @@
1
+ import { isDeepStrictEqual } from 'node:util';
2
+ import { ApplicationBuilder, DATA_PROVIDER, DATASOURCE_TYPE, DatasourceReferenceBuilder, isPrimitiveOrExpression, ParameterValueSchema, ScreenBaseBuilderNew, SqliteDatasourceBuilder, StaticDatasourceBuilder, } from '@jigx/core-sdk';
3
+ import { firstLine, messageSlug, toJsonValue } from '../nodes/index.js';
4
+ import { dropUndefined, isPlainObject, normalizeEntity } from '../normalize.js';
5
+ import { pruneAt } from '../prune.js';
6
+ import { countNodes } from '../report.js';
7
+ import { lit, str } from '../ts-printer.js';
8
+ const INDENT = ' ';
9
+ const CHAIN_INDENT = `${INDENT} `;
10
+ const SQLITE_KEYS = [
11
+ 'type',
12
+ 'options',
13
+ 'parameters',
14
+ 'datasourceId',
15
+ 'instanceId',
16
+ ];
17
+ const SQLITE_PROVIDERS = {
18
+ [DATA_PROVIDER.LOCAL]: 'local',
19
+ [DATA_PROVIDER.DYNAMIC]: 'dynamic',
20
+ };
21
+ function skipped(slug, reason) {
22
+ return { type: 'skip', slug, reason };
23
+ }
24
+ function comparable(value) {
25
+ return dropUndefined(toJsonValue(value));
26
+ }
27
+ function buildWith(factory, steps) {
28
+ try {
29
+ const builder = factory.create();
30
+ for (const step of steps)
31
+ step.apply(builder);
32
+ const built = toJsonValue(builder.build());
33
+ return { type: 'built', value: isPlainObject(built) ? built : {} };
34
+ }
35
+ catch (error) {
36
+ return { type: 'error', message: firstLine(error) };
37
+ }
38
+ }
39
+ function application(host) {
40
+ if (host instanceof ApplicationBuilder || host instanceof ScreenBaseBuilderNew)
41
+ return host;
42
+ throw new Error('A datasource host must be an ApplicationBuilder or a screen builder');
43
+ }
44
+ function screen(host) {
45
+ if (host instanceof ScreenBaseBuilderNew)
46
+ return host;
47
+ throw new Error('A datasource reference needs a screen builder');
48
+ }
49
+ function primitiveRecord(value) {
50
+ if (!isPlainObject(value))
51
+ return undefined;
52
+ const out = {};
53
+ for (const [name, item] of Object.entries(value)) {
54
+ if (!isPrimitiveOrExpression(item))
55
+ return undefined;
56
+ out[name] = item;
57
+ }
58
+ return out;
59
+ }
60
+ function isInlineData(value) {
61
+ return (Array.isArray(value) &&
62
+ value.every((item) => item === null ||
63
+ typeof item === 'string' ||
64
+ typeof item === 'number' ||
65
+ typeof item === 'boolean' ||
66
+ isPlainObject(item)));
67
+ }
68
+ /** Typed `.entity(…)`/`.entityPackaged(…)` call for one legacy sqlite entity. */
69
+ function entityStep(entity) {
70
+ if (typeof entity === 'string') {
71
+ return {
72
+ code: `entity(${str(entity)})`,
73
+ apply: (builder) => {
74
+ builder.entity(entity);
75
+ },
76
+ };
77
+ }
78
+ if (!isPlainObject(entity) || typeof entity.entity !== 'string')
79
+ return undefined;
80
+ const name = entity.entity;
81
+ const keys = Object.keys(entity);
82
+ if (keys.length === 2 && typeof entity.package === 'string') {
83
+ const packageName = entity.package;
84
+ return {
85
+ code: `entityPackaged(${str(name)}, ${str(packageName)})`,
86
+ apply: (builder) => {
87
+ builder.entityPackaged(name, packageName);
88
+ },
89
+ };
90
+ }
91
+ if (!keys.every((key) => ['entity', 'function', 'functionParameters'].includes(key))) {
92
+ return undefined;
93
+ }
94
+ const fn = entity.function;
95
+ if (fn !== undefined && typeof fn !== 'string')
96
+ return undefined;
97
+ const params = entity.functionParameters === undefined ? undefined : primitiveRecord(entity.functionParameters);
98
+ if (entity.functionParameters !== undefined && params === undefined)
99
+ return undefined;
100
+ const input = {
101
+ entity: name,
102
+ ...(fn === undefined ? {} : { fn }),
103
+ ...(params === undefined ? {} : { params }),
104
+ };
105
+ return {
106
+ code: `entity(${lit(input, CHAIN_INDENT)})`,
107
+ apply: (builder) => {
108
+ builder.entity(structuredClone(input));
109
+ },
110
+ };
111
+ }
112
+ /** Typed sqlite calls for one optional legacy option; `undefined` when it has none. */
113
+ function optionSteps(key, value) {
114
+ if (key === 'queryParameters') {
115
+ const params = primitiveRecord(value);
116
+ if (!params || Object.keys(params).length === 0)
117
+ return undefined;
118
+ return Object.entries(params).map(([name, item]) => ({
119
+ code: `queryParameter(${str(name)}, ${lit(item, CHAIN_INDENT)})`,
120
+ apply: (builder) => {
121
+ builder.queryParameter(name, item);
122
+ },
123
+ }));
124
+ }
125
+ if ((key === 'rewriteQuery' || key === 'isDocument') && typeof value === 'boolean') {
126
+ return [
127
+ {
128
+ code: `${key}(${String(value)})`,
129
+ apply: (builder) => {
130
+ if (key === 'rewriteQuery')
131
+ builder.rewriteQuery(value);
132
+ else
133
+ builder.isDocument(value);
134
+ },
135
+ },
136
+ ];
137
+ }
138
+ if (key === 'jsonProperties' &&
139
+ Array.isArray(value) &&
140
+ value.every((item) => typeof item === 'string')) {
141
+ const columns = value;
142
+ return [
143
+ {
144
+ code: `jsonProperties(${columns.map((column) => str(column)).join(', ')})`,
145
+ apply: (builder) => {
146
+ builder.jsonProperties(...columns);
147
+ },
148
+ },
149
+ ];
150
+ }
151
+ return undefined;
152
+ }
153
+ function parameterDefault(value) {
154
+ const parsed = ParameterValueSchema.safeParse(value);
155
+ return parsed.success ? parsed.data : undefined;
156
+ }
157
+ /** Typed `.parameter(…)` calls for the legacy `parameters` map; `undefined` when one has none. */
158
+ function parameterSteps(value) {
159
+ if (!isPlainObject(value) || Object.keys(value).length === 0)
160
+ return undefined;
161
+ const steps = [];
162
+ for (const [name, parameter] of Object.entries(value)) {
163
+ if (!isPlainObject(parameter) || typeof parameter.type !== 'string')
164
+ return undefined;
165
+ if (!Object.keys(parameter).every((key) => ['type', 'required', 'default'].includes(key))) {
166
+ return undefined;
167
+ }
168
+ const { type, required } = parameter;
169
+ if (required !== undefined && typeof required !== 'boolean')
170
+ return undefined;
171
+ const defaultValue = parameterDefault(parameter.default);
172
+ if (parameter.default !== undefined && defaultValue === undefined)
173
+ return undefined;
174
+ const options = {
175
+ ...(required === undefined ? {} : { required }),
176
+ ...(defaultValue === undefined ? {} : { defaultValue }),
177
+ };
178
+ const hasOptions = Object.keys(options).length > 0;
179
+ steps.push({
180
+ code: `parameter(${str(name)}, ${str(type)}${hasOptions ? `, ${lit(options, CHAIN_INDENT)}` : ''})`,
181
+ apply: (builder) => {
182
+ builder.parameter(name, type, hasOptions ? structuredClone(options) : undefined);
183
+ },
184
+ });
185
+ }
186
+ return steps;
187
+ }
188
+ /** Verifies the whole datasource against the pruned legacy and returns the typed conversion. */
189
+ function finish(options) {
190
+ const { key, legacy, factory, steps, gaps } = options;
191
+ const whole = buildWith(factory, steps);
192
+ if (whole.type === 'error') {
193
+ return skipped(`throws-${messageSlug(whole.message)}`, `the typed datasource throws: ${whole.message}`);
194
+ }
195
+ const pruned = pruneAt({ value: legacy, path: [], gaps });
196
+ const equal = isDeepStrictEqual(normalizeEntity({ kind: 'datasources', id: key, entity: whole.value }), normalizeEntity({ kind: 'datasources', id: key, entity: comparable(pruned) }));
197
+ if (!equal) {
198
+ return skipped('output-differs', 'the typed datasource does not reproduce the legacy datasource');
199
+ }
200
+ return {
201
+ type: 'typed',
202
+ gaps,
203
+ code: (parentExpr) => `${parentExpr}.addDatasource.${factory.name}(${lit(factory.input, INDENT)})${steps
204
+ .map((step) => `\n${CHAIN_INDENT}.${step.code}`)
205
+ .join('')}`,
206
+ attach: (host) => {
207
+ const builder = factory.createOn(host);
208
+ for (const step of steps)
209
+ step.apply(builder);
210
+ },
211
+ };
212
+ }
213
+ function keyGap(key, value, reason) {
214
+ return {
215
+ slug: `key-${key}`,
216
+ reason,
217
+ skippedNodes: countNodes({ value, asRoot: false }),
218
+ path: [key],
219
+ };
220
+ }
221
+ function optionGap(key, value, reason) {
222
+ return {
223
+ slug: `option-${key}`,
224
+ reason,
225
+ skippedNodes: countNodes({ value, asRoot: false }),
226
+ path: ['options', key],
227
+ };
228
+ }
229
+ function convertSqlite(key, legacy) {
230
+ const { options, instanceId } = legacy;
231
+ if (!isPlainObject(options))
232
+ return skipped('shape', 'sqlite options must be a mapping');
233
+ const provider = typeof options.provider === 'string' ? SQLITE_PROVIDERS[options.provider] : undefined;
234
+ if (!provider)
235
+ return skipped('option-provider', 'only local and dynamic sqlite providers are typed');
236
+ const gaps = [];
237
+ for (const [name, value] of Object.entries(legacy)) {
238
+ if (!SQLITE_KEYS.includes(name))
239
+ gaps.push(keyGap(name, value, `no typed sqlite call for "${name}"`));
240
+ }
241
+ if (instanceId !== undefined && typeof instanceId !== 'string') {
242
+ gaps.push(keyGap('instanceId', instanceId, 'instanceId is not a string'));
243
+ }
244
+ const input = {
245
+ datasourceId: key,
246
+ provider,
247
+ ...(typeof instanceId === 'string' && instanceId !== key ? { instanceId } : {}),
248
+ };
249
+ const factory = {
250
+ name: 'sqlite',
251
+ input,
252
+ create: () => new SqliteDatasourceBuilder(structuredClone(input)),
253
+ createOn: (host) => application(host).addDatasource.sqlite(structuredClone(input)),
254
+ };
255
+ const entities = Array.isArray(options.entities) ? options.entities : [];
256
+ const entitySteps = entities.map((entity) => entityStep(entity));
257
+ if (!Array.isArray(options.entities) || entitySteps.some((step) => step === undefined)) {
258
+ return skipped('option-entities', 'an entity has no typed .entity() form');
259
+ }
260
+ const { query } = options;
261
+ if (typeof query !== 'string' || query.trim() === '') {
262
+ return skipped('option-query', 'the query is not a non-empty string');
263
+ }
264
+ const queryStep = {
265
+ code: `query(${lit(query, CHAIN_INDENT)})`,
266
+ apply: (builder) => {
267
+ builder.query(query);
268
+ },
269
+ };
270
+ const head = entitySteps.filter((step) => step !== undefined);
271
+ try {
272
+ const builder = factory.create();
273
+ for (const step of head)
274
+ step.apply(builder);
275
+ }
276
+ catch (error) {
277
+ return skipped('option-entities', `.entity() throws: ${firstLine(error)}`);
278
+ }
279
+ const base = buildWith(factory, [...head, queryStep]);
280
+ if (base.type === 'error') {
281
+ return skipped('option-query', `the typed datasource does not build: ${base.message}`);
282
+ }
283
+ const builtOptions = isPlainObject(base.value.options) ? base.value.options : {};
284
+ for (const name of ['provider', 'entities', 'query']) {
285
+ if (!isDeepStrictEqual(comparable(builtOptions[name]), comparable(options[name]))) {
286
+ return skipped(`option-${name}`, `the typed calls do not reproduce "${name}"`);
287
+ }
288
+ }
289
+ const middle = [];
290
+ const verifies = (candidate, read, legacyValue) => {
291
+ const result = buildWith(factory, [...head, ...candidate, queryStep]);
292
+ return (result.type === 'built' &&
293
+ isDeepStrictEqual(comparable(read(result.value)), comparable(legacyValue)));
294
+ };
295
+ if (legacy.parameters !== undefined) {
296
+ const steps = parameterSteps(legacy.parameters);
297
+ if (steps && verifies(steps, (built) => built.parameters, legacy.parameters)) {
298
+ middle.push(...steps);
299
+ }
300
+ else {
301
+ gaps.push(keyGap('parameters', legacy.parameters, 'no typed .parameter() calls reproduce "parameters"'));
302
+ }
303
+ }
304
+ for (const [name, value] of Object.entries(options)) {
305
+ if (name === 'provider' || name === 'entities' || name === 'query')
306
+ continue;
307
+ const steps = optionSteps(name, value);
308
+ const read = (built) => isPlainObject(built.options) ? built.options[name] : undefined;
309
+ if (steps && verifies(steps, read, value))
310
+ middle.push(...steps);
311
+ else
312
+ gaps.push(optionGap(name, value, `no typed sqlite call reproduces "${name}"`));
313
+ }
314
+ return finish({ key, legacy, factory, steps: [...head, ...middle, queryStep], gaps });
315
+ }
316
+ function convertStatic(key, legacy) {
317
+ const { options } = legacy;
318
+ if (!isPlainObject(options))
319
+ return skipped('shape', 'static options must be a mapping');
320
+ const gaps = [];
321
+ for (const [name, value] of Object.entries(legacy)) {
322
+ if (!['type', 'options', 'datasourceId', 'instanceId'].includes(name)) {
323
+ gaps.push(keyGap(name, value, `no typed static datasource input for "${name}"`));
324
+ }
325
+ }
326
+ if (legacy.instanceId !== undefined && legacy.instanceId !== key) {
327
+ gaps.push(keyGap('instanceId', legacy.instanceId, 'the static datasource input has no instanceId'));
328
+ }
329
+ for (const [name, value] of Object.entries(options)) {
330
+ if (name !== 'data')
331
+ gaps.push(optionGap(name, value, `no typed static datasource input for "${name}"`));
332
+ }
333
+ const { data } = options;
334
+ if (!isInlineData(data))
335
+ return skipped('option-data', 'data is not a list of values or objects');
336
+ const input = { datasourceId: key, data };
337
+ const factory = {
338
+ name: 'static',
339
+ input,
340
+ create: () => new StaticDatasourceBuilder(structuredClone(input)),
341
+ createOn: (host) => application(host).addDatasource.static(structuredClone(input)),
342
+ };
343
+ return finish({ key, legacy, factory, steps: [], gaps });
344
+ }
345
+ function convertReference(key, legacy) {
346
+ const { datasourceId, inputs } = legacy;
347
+ if (typeof datasourceId !== 'string')
348
+ return skipped('key-datasourceId', 'a reference needs a datasourceId');
349
+ const packageName = typeof legacy.package === 'string' ? legacy.package : undefined;
350
+ const gaps = [];
351
+ for (const [name, value] of Object.entries(legacy)) {
352
+ if (['type', 'datasourceId', 'inputs'].includes(name))
353
+ continue;
354
+ if (name === 'package' && packageName !== undefined)
355
+ continue;
356
+ if (name === 'instanceId' && value === key)
357
+ continue;
358
+ gaps.push(keyGap(name, value, `no typed reference input for "${name}"`));
359
+ }
360
+ const steps = [];
361
+ if (inputs !== undefined) {
362
+ const params = primitiveRecord(inputs);
363
+ if (params && Object.keys(params).length > 0) {
364
+ for (const [name, value] of Object.entries(params)) {
365
+ steps.push({
366
+ code: `param(${str(name)}, ${lit(value, CHAIN_INDENT)})`,
367
+ apply: (builder) => {
368
+ builder.param(name, value);
369
+ },
370
+ });
371
+ }
372
+ }
373
+ else {
374
+ gaps.push(keyGap('inputs', inputs, 'no typed .param() calls reproduce "inputs"'));
375
+ }
376
+ }
377
+ const input = {
378
+ instanceId: key,
379
+ descriptor: { datasourceId, ...(packageName === undefined ? {} : { packageName }) },
380
+ };
381
+ const factory = {
382
+ name: 'reference',
383
+ input,
384
+ create: () => new DatasourceReferenceBuilder(structuredClone(input)),
385
+ createOn: (host) => screen(host).addDatasource.reference(structuredClone(input)),
386
+ };
387
+ return finish({ key, legacy, factory, steps, gaps });
388
+ }
389
+ /**
390
+ * Converts one legacy datasource into a typed `addDatasource.<factory>(…)` call chain.
391
+ *
392
+ * - `datasource.sqlite` (local or dynamic): `entity`/`entityPackaged`, `parameter`,
393
+ * `queryParameter`, `rewriteQuery`, `isDocument`, `jsonProperties`, `query`
394
+ * - `datasource.static`: `data` in the factory input
395
+ * - `datasource.reference` (screen scope only): `descriptor` plus `param` per input
396
+ *
397
+ * Optional keys and options that do not verify are skipped one by one (`key-<key>`,
398
+ * `option-<key>`); the whole datasource is then verified against the pruned legacy.
399
+ * A datasource with no typed constructor, or whose required parts do not verify, is skipped.
400
+ */
401
+ export function convertDatasourceDefinition(options) {
402
+ const { key, legacy, scope } = options;
403
+ if (!isPlainObject(legacy))
404
+ return skipped('shape', 'a datasource must be a YAML mapping');
405
+ if (legacy.datasourceId !== undefined &&
406
+ legacy.datasourceId !== key &&
407
+ legacy.type !== DATASOURCE_TYPE.REFERENCE) {
408
+ return skipped('key-datasourceId', 'datasourceId differs from its key');
409
+ }
410
+ if (legacy.type === DATASOURCE_TYPE.SQLITE)
411
+ return convertSqlite(key, legacy);
412
+ if (legacy.type === DATASOURCE_TYPE.STATIC)
413
+ return convertStatic(key, legacy);
414
+ if (legacy.type === DATASOURCE_TYPE.REFERENCE && scope === 'screen') {
415
+ return convertReference(key, legacy);
416
+ }
417
+ return skipped(`type-${messageSlug(String(legacy.type))}`, `no typed ${scope === 'app' ? 'app.addDatasource' : 'screen.addDatasource'} factory for ${String(legacy.type)}`);
418
+ }
419
+ /** `datasources/<id>.jigx` → `app.addDatasource.<factory>(…)`; gaps are `datasources:<slug>`. */
420
+ export function convertDatasource(entry) {
421
+ const { id, entity } = entry;
422
+ const result = convertDatasourceDefinition({ key: id, legacy: entity, scope: 'app' });
423
+ if (result.type === 'skip') {
424
+ return { type: 'skip', gapId: `datasources:${result.slug}`, reason: result.reason };
425
+ }
426
+ return {
427
+ type: 'statements',
428
+ gaps: result.gaps.map(({ slug, reason, skippedNodes, path }) => ({
429
+ gapId: `datasources:${slug}`,
430
+ nodeType: 'datasources',
431
+ reason,
432
+ skippedNodes,
433
+ path,
434
+ })),
435
+ statements: [
436
+ {
437
+ code: result.code('app'),
438
+ run: (app) => {
439
+ result.attach(app);
440
+ },
441
+ },
442
+ ],
443
+ };
444
+ }
445
+ //# sourceMappingURL=datasources.js.map