@eide/uniformgen 0.1.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 (299) hide show
  1. package/README.md +356 -0
  2. package/dist/auth/credentials.d.ts +58 -0
  3. package/dist/auth/credentials.d.ts.map +1 -0
  4. package/dist/auth/credentials.js +107 -0
  5. package/dist/cli.d.ts +3 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +563 -0
  8. package/dist/commands/init.d.ts +11 -0
  9. package/dist/commands/init.d.ts.map +1 -0
  10. package/dist/commands/init.js +113 -0
  11. package/dist/commands/login.d.ts +9 -0
  12. package/dist/commands/login.d.ts.map +1 -0
  13. package/dist/commands/login.js +158 -0
  14. package/dist/commands/logout.d.ts +5 -0
  15. package/dist/commands/logout.d.ts.map +1 -0
  16. package/dist/commands/logout.js +13 -0
  17. package/dist/commands/push.d.ts +13 -0
  18. package/dist/commands/push.d.ts.map +1 -0
  19. package/dist/commands/push.js +328 -0
  20. package/dist/commands/scaffold.d.ts +19 -0
  21. package/dist/commands/scaffold.d.ts.map +1 -0
  22. package/dist/commands/scaffold.js +366 -0
  23. package/dist/commands/seed.d.ts +20 -0
  24. package/dist/commands/seed.d.ts.map +1 -0
  25. package/dist/commands/seed.js +380 -0
  26. package/dist/commands/select-project.d.ts +10 -0
  27. package/dist/commands/select-project.d.ts.map +1 -0
  28. package/dist/commands/select-project.js +277 -0
  29. package/dist/commands/setup.d.ts +5 -0
  30. package/dist/commands/setup.d.ts.map +1 -0
  31. package/dist/commands/setup.js +51 -0
  32. package/dist/commands/sync.d.ts +13 -0
  33. package/dist/commands/sync.d.ts.map +1 -0
  34. package/dist/commands/sync.js +318 -0
  35. package/dist/commands/whoami.d.ts +5 -0
  36. package/dist/commands/whoami.d.ts.map +1 -0
  37. package/dist/commands/whoami.js +31 -0
  38. package/dist/config/load-config.d.ts +6 -0
  39. package/dist/config/load-config.d.ts.map +1 -0
  40. package/dist/config/load-config.js +103 -0
  41. package/dist/config/settings.d.ts +20 -0
  42. package/dist/config/settings.d.ts.map +1 -0
  43. package/dist/config/settings.js +64 -0
  44. package/dist/config/types.d.ts +152 -0
  45. package/dist/config/types.d.ts.map +1 -0
  46. package/dist/config/types.js +94 -0
  47. package/dist/fetcher/fetch-schemas.d.ts +140 -0
  48. package/dist/fetcher/fetch-schemas.d.ts.map +1 -0
  49. package/dist/fetcher/fetch-schemas.js +223 -0
  50. package/dist/fetcher/fetch-workflows.d.ts +53 -0
  51. package/dist/fetcher/fetch-workflows.d.ts.map +1 -0
  52. package/dist/fetcher/fetch-workflows.js +164 -0
  53. package/dist/generated/hooks/customer-detail.d.ts +74 -0
  54. package/dist/generated/hooks/customer-detail.d.ts.map +1 -0
  55. package/dist/generated/hooks/customer-detail.js +113 -0
  56. package/dist/generated/hooks/design-system.d.ts +74 -0
  57. package/dist/generated/hooks/design-system.d.ts.map +1 -0
  58. package/dist/generated/hooks/design-system.js +109 -0
  59. package/dist/generated/hooks/index.d.ts +16 -0
  60. package/dist/generated/hooks/index.d.ts.map +1 -0
  61. package/dist/generated/hooks/index.js +14 -0
  62. package/dist/generated/hooks/shopify-collection.d.ts +74 -0
  63. package/dist/generated/hooks/shopify-collection.d.ts.map +1 -0
  64. package/dist/generated/hooks/shopify-collection.js +113 -0
  65. package/dist/generated/hooks/shopify-market.d.ts +74 -0
  66. package/dist/generated/hooks/shopify-market.d.ts.map +1 -0
  67. package/dist/generated/hooks/shopify-market.js +109 -0
  68. package/dist/generated/hooks/shopify-product.d.ts +74 -0
  69. package/dist/generated/hooks/shopify-product.d.ts.map +1 -0
  70. package/dist/generated/hooks/shopify-product.js +113 -0
  71. package/dist/generated/hooks/shopify-variant.d.ts +74 -0
  72. package/dist/generated/hooks/shopify-variant.d.ts.map +1 -0
  73. package/dist/generated/hooks/shopify-variant.js +113 -0
  74. package/dist/generated/hooks/template.d.ts +74 -0
  75. package/dist/generated/hooks/template.d.ts.map +1 -0
  76. package/dist/generated/hooks/template.js +107 -0
  77. package/dist/generated/types/config.d.ts +88 -0
  78. package/dist/generated/types/config.d.ts.map +1 -0
  79. package/dist/generated/types/config.js +14 -0
  80. package/dist/generated/types/data-models/index.d.ts +7 -0
  81. package/dist/generated/types/data-models/index.d.ts.map +1 -0
  82. package/dist/generated/types/data-models/index.js +6 -0
  83. package/dist/generated/types/data-models/test.d.ts +29 -0
  84. package/dist/generated/types/data-models/test.d.ts.map +1 -0
  85. package/dist/generated/types/data-models/test.js +1 -0
  86. package/dist/generated/types/data-models/watch.d.ts +26 -0
  87. package/dist/generated/types/data-models/watch.d.ts.map +1 -0
  88. package/dist/generated/types/data-models/watch.js +1 -0
  89. package/dist/generated/types/field-types.d.ts +255 -0
  90. package/dist/generated/types/field-types.d.ts.map +1 -0
  91. package/dist/generated/types/field-types.js +35 -0
  92. package/dist/generated/types/hooks.d.ts +106 -0
  93. package/dist/generated/types/hooks.d.ts.map +1 -0
  94. package/dist/generated/types/hooks.js +9 -0
  95. package/dist/generated/types/index.d.ts +10 -0
  96. package/dist/generated/types/index.d.ts.map +1 -0
  97. package/dist/generated/types/index.js +9 -0
  98. package/dist/generated/types/models/button-variant.d.ts +16 -0
  99. package/dist/generated/types/models/button-variant.d.ts.map +1 -0
  100. package/dist/generated/types/models/button-variant.js +1 -0
  101. package/dist/generated/types/models/color-palette.d.ts +27 -0
  102. package/dist/generated/types/models/color-palette.d.ts.map +1 -0
  103. package/dist/generated/types/models/color-palette.js +1 -0
  104. package/dist/generated/types/models/color-with-scale.d.ts +15 -0
  105. package/dist/generated/types/models/color-with-scale.d.ts.map +1 -0
  106. package/dist/generated/types/models/color-with-scale.js +1 -0
  107. package/dist/generated/types/models/context.d.ts +53 -0
  108. package/dist/generated/types/models/context.d.ts.map +1 -0
  109. package/dist/generated/types/models/context.js +51 -0
  110. package/dist/generated/types/models/customer-detail.d.ts +32 -0
  111. package/dist/generated/types/models/customer-detail.d.ts.map +1 -0
  112. package/dist/generated/types/models/customer-detail.js +26 -0
  113. package/dist/generated/types/models/design-system-badges.d.ts +16 -0
  114. package/dist/generated/types/models/design-system-badges.d.ts.map +1 -0
  115. package/dist/generated/types/models/design-system-badges.js +1 -0
  116. package/dist/generated/types/models/design-system-buttons.d.ts +17 -0
  117. package/dist/generated/types/models/design-system-buttons.d.ts.map +1 -0
  118. package/dist/generated/types/models/design-system-buttons.js +1 -0
  119. package/dist/generated/types/models/design-system-cards.d.ts +16 -0
  120. package/dist/generated/types/models/design-system-cards.d.ts.map +1 -0
  121. package/dist/generated/types/models/design-system-cards.js +1 -0
  122. package/dist/generated/types/models/design-system-colors.d.ts +12 -0
  123. package/dist/generated/types/models/design-system-colors.d.ts.map +1 -0
  124. package/dist/generated/types/models/design-system-colors.js +1 -0
  125. package/dist/generated/types/models/design-system-dark-mode.d.ts +13 -0
  126. package/dist/generated/types/models/design-system-dark-mode.d.ts.map +1 -0
  127. package/dist/generated/types/models/design-system-dark-mode.js +1 -0
  128. package/dist/generated/types/models/design-system-focus-ring.d.ts +14 -0
  129. package/dist/generated/types/models/design-system-focus-ring.d.ts.map +1 -0
  130. package/dist/generated/types/models/design-system-focus-ring.js +1 -0
  131. package/dist/generated/types/models/design-system-grid.d.ts +18 -0
  132. package/dist/generated/types/models/design-system-grid.d.ts.map +1 -0
  133. package/dist/generated/types/models/design-system-grid.js +1 -0
  134. package/dist/generated/types/models/design-system-inputs.d.ts +26 -0
  135. package/dist/generated/types/models/design-system-inputs.d.ts.map +1 -0
  136. package/dist/generated/types/models/design-system-inputs.js +1 -0
  137. package/dist/generated/types/models/design-system-links.d.ts +16 -0
  138. package/dist/generated/types/models/design-system-links.d.ts.map +1 -0
  139. package/dist/generated/types/models/design-system-links.js +1 -0
  140. package/dist/generated/types/models/design-system-shadows.d.ts +20 -0
  141. package/dist/generated/types/models/design-system-shadows.d.ts.map +1 -0
  142. package/dist/generated/types/models/design-system-shadows.js +1 -0
  143. package/dist/generated/types/models/design-system-spacing.d.ts +13 -0
  144. package/dist/generated/types/models/design-system-spacing.d.ts.map +1 -0
  145. package/dist/generated/types/models/design-system-spacing.js +1 -0
  146. package/dist/generated/types/models/design-system-transitions.d.ts +15 -0
  147. package/dist/generated/types/models/design-system-transitions.d.ts.map +1 -0
  148. package/dist/generated/types/models/design-system-transitions.js +1 -0
  149. package/dist/generated/types/models/design-system-typography.d.ts +21 -0
  150. package/dist/generated/types/models/design-system-typography.d.ts.map +1 -0
  151. package/dist/generated/types/models/design-system-typography.js +1 -0
  152. package/dist/generated/types/models/design-system.d.ts +138 -0
  153. package/dist/generated/types/models/design-system.d.ts.map +1 -0
  154. package/dist/generated/types/models/design-system.js +64 -0
  155. package/dist/generated/types/models/experiment.d.ts +57 -0
  156. package/dist/generated/types/models/experiment.d.ts.map +1 -0
  157. package/dist/generated/types/models/experiment.js +55 -0
  158. package/dist/generated/types/models/font-file.d.ts +16 -0
  159. package/dist/generated/types/models/font-file.d.ts.map +1 -0
  160. package/dist/generated/types/models/font-file.js +1 -0
  161. package/dist/generated/types/models/index.d.ts +38 -0
  162. package/dist/generated/types/models/index.d.ts.map +1 -0
  163. package/dist/generated/types/models/index.js +12 -0
  164. package/dist/generated/types/models/integration.d.ts +32 -0
  165. package/dist/generated/types/models/integration.d.ts.map +1 -0
  166. package/dist/generated/types/models/integration.js +26 -0
  167. package/dist/generated/types/models/route-tree.d.ts +43 -0
  168. package/dist/generated/types/models/route-tree.d.ts.map +1 -0
  169. package/dist/generated/types/models/route-tree.js +39 -0
  170. package/dist/generated/types/models/segment.d.ts +57 -0
  171. package/dist/generated/types/models/segment.d.ts.map +1 -0
  172. package/dist/generated/types/models/segment.js +55 -0
  173. package/dist/generated/types/models/shopify-collection.d.ts +32 -0
  174. package/dist/generated/types/models/shopify-collection.d.ts.map +1 -0
  175. package/dist/generated/types/models/shopify-collection.js +26 -0
  176. package/dist/generated/types/models/shopify-market.d.ts +32 -0
  177. package/dist/generated/types/models/shopify-market.d.ts.map +1 -0
  178. package/dist/generated/types/models/shopify-market.js +26 -0
  179. package/dist/generated/types/models/shopify-product.d.ts +32 -0
  180. package/dist/generated/types/models/shopify-product.d.ts.map +1 -0
  181. package/dist/generated/types/models/shopify-product.js +26 -0
  182. package/dist/generated/types/models/shopify-variant.d.ts +32 -0
  183. package/dist/generated/types/models/shopify-variant.d.ts.map +1 -0
  184. package/dist/generated/types/models/shopify-variant.js +26 -0
  185. package/dist/generated/types/models/template.d.ts +53 -0
  186. package/dist/generated/types/models/template.d.ts.map +1 -0
  187. package/dist/generated/types/models/template.js +40 -0
  188. package/dist/generated/types/models/typography-variant.d.ts +15 -0
  189. package/dist/generated/types/models/typography-variant.d.ts.map +1 -0
  190. package/dist/generated/types/models/typography-variant.js +1 -0
  191. package/dist/generated/types/scalars.d.ts +56 -0
  192. package/dist/generated/types/scalars.d.ts.map +1 -0
  193. package/dist/generated/types/scalars.js +6 -0
  194. package/dist/generators/admin/index.d.ts +32 -0
  195. package/dist/generators/admin/index.d.ts.map +1 -0
  196. package/dist/generators/admin/index.js +219 -0
  197. package/dist/generators/admin/mutations.d.ts +23 -0
  198. package/dist/generators/admin/mutations.d.ts.map +1 -0
  199. package/dist/generators/admin/mutations.js +424 -0
  200. package/dist/generators/admin/queries.d.ts +20 -0
  201. package/dist/generators/admin/queries.d.ts.map +1 -0
  202. package/dist/generators/admin/queries.js +476 -0
  203. package/dist/generators/admin/types.d.ts +28 -0
  204. package/dist/generators/admin/types.d.ts.map +1 -0
  205. package/dist/generators/admin/types.js +254 -0
  206. package/dist/generators/cms/index.d.ts +29 -0
  207. package/dist/generators/cms/index.d.ts.map +1 -0
  208. package/dist/generators/cms/index.js +126 -0
  209. package/dist/generators/cms/route.d.ts +27 -0
  210. package/dist/generators/cms/route.d.ts.map +1 -0
  211. package/dist/generators/cms/route.js +409 -0
  212. package/dist/generators/cms/types.d.ts +15 -0
  213. package/dist/generators/cms/types.d.ts.map +1 -0
  214. package/dist/generators/cms/types.js +137 -0
  215. package/dist/generators/contexts/index.d.ts +25 -0
  216. package/dist/generators/contexts/index.d.ts.map +1 -0
  217. package/dist/generators/contexts/index.js +591 -0
  218. package/dist/generators/documents/data-models.d.ts +6 -0
  219. package/dist/generators/documents/data-models.d.ts.map +1 -0
  220. package/dist/generators/documents/data-models.js +61 -0
  221. package/dist/generators/documents/entity-models.d.ts +7 -0
  222. package/dist/generators/documents/entity-models.d.ts.map +1 -0
  223. package/dist/generators/documents/entity-models.js +87 -0
  224. package/dist/generators/documents/workflows.d.ts +11 -0
  225. package/dist/generators/documents/workflows.d.ts.map +1 -0
  226. package/dist/generators/documents/workflows.js +101 -0
  227. package/dist/generators/filters/index.d.ts +16 -0
  228. package/dist/generators/filters/index.d.ts.map +1 -0
  229. package/dist/generators/filters/index.js +384 -0
  230. package/dist/generators/hooks/agnostic.d.ts +16 -0
  231. package/dist/generators/hooks/agnostic.d.ts.map +1 -0
  232. package/dist/generators/hooks/agnostic.js +248 -0
  233. package/dist/generators/hooks/index.d.ts +9 -0
  234. package/dist/generators/hooks/index.d.ts.map +1 -0
  235. package/dist/generators/hooks/index.js +8 -0
  236. package/dist/generators/hooks/react.d.ts +16 -0
  237. package/dist/generators/hooks/react.d.ts.map +1 -0
  238. package/dist/generators/hooks/react.js +394 -0
  239. package/dist/generators/hooks/remix.d.ts +16 -0
  240. package/dist/generators/hooks/remix.d.ts.map +1 -0
  241. package/dist/generators/hooks/remix.js +349 -0
  242. package/dist/generators/hooks/workflows.d.ts +23 -0
  243. package/dist/generators/hooks/workflows.d.ts.map +1 -0
  244. package/dist/generators/hooks/workflows.js +312 -0
  245. package/dist/generators/resolve/index.d.ts +13 -0
  246. package/dist/generators/resolve/index.d.ts.map +1 -0
  247. package/dist/generators/resolve/index.js +13 -0
  248. package/dist/generators/resolve/platform.d.ts +29 -0
  249. package/dist/generators/resolve/platform.d.ts.map +1 -0
  250. package/dist/generators/resolve/platform.js +479 -0
  251. package/dist/generators/types/config.d.ts +7 -0
  252. package/dist/generators/types/config.d.ts.map +1 -0
  253. package/dist/generators/types/config.js +113 -0
  254. package/dist/generators/types/data-models.d.ts +10 -0
  255. package/dist/generators/types/data-models.d.ts.map +1 -0
  256. package/dist/generators/types/data-models.js +100 -0
  257. package/dist/generators/types/entity-models.d.ts +13 -0
  258. package/dist/generators/types/entity-models.d.ts.map +1 -0
  259. package/dist/generators/types/entity-models.js +241 -0
  260. package/dist/generators/types/field-types.d.ts +9 -0
  261. package/dist/generators/types/field-types.d.ts.map +1 -0
  262. package/dist/generators/types/field-types.js +651 -0
  263. package/dist/generators/types/hooks.d.ts +7 -0
  264. package/dist/generators/types/hooks.d.ts.map +1 -0
  265. package/dist/generators/types/hooks.js +132 -0
  266. package/dist/generators/types/scalars.d.ts +6 -0
  267. package/dist/generators/types/scalars.d.ts.map +1 -0
  268. package/dist/generators/types/scalars.js +68 -0
  269. package/dist/generators/types/user-details.d.ts +6 -0
  270. package/dist/generators/types/user-details.d.ts.map +1 -0
  271. package/dist/generators/types/user-details.js +60 -0
  272. package/dist/generators/types/workflows.d.ts +15 -0
  273. package/dist/generators/types/workflows.d.ts.map +1 -0
  274. package/dist/generators/types/workflows.js +163 -0
  275. package/dist/graphql/generated/gql.d.ts +47 -0
  276. package/dist/graphql/generated/gql.d.ts.map +1 -0
  277. package/dist/graphql/generated/gql.js +10 -0
  278. package/dist/graphql/generated/graphql.d.ts +8455 -0
  279. package/dist/graphql/generated/graphql.d.ts.map +1 -0
  280. package/dist/graphql/generated/graphql.js +573 -0
  281. package/dist/graphql/generated/index.d.ts +2 -0
  282. package/dist/graphql/generated/index.d.ts.map +1 -0
  283. package/dist/graphql/generated/index.js +1 -0
  284. package/dist/index.d.ts +13 -0
  285. package/dist/index.d.ts.map +1 -0
  286. package/dist/index.js +9 -0
  287. package/dist/schema/define-entity-model.d.ts +122 -0
  288. package/dist/schema/define-entity-model.d.ts.map +1 -0
  289. package/dist/schema/define-entity-model.js +59 -0
  290. package/dist/schema/schema-loader.d.ts +10 -0
  291. package/dist/schema/schema-loader.d.ts.map +1 -0
  292. package/dist/schema/schema-loader.js +91 -0
  293. package/dist/utils/field-mapping.d.ts +83 -0
  294. package/dist/utils/field-mapping.d.ts.map +1 -0
  295. package/dist/utils/field-mapping.js +334 -0
  296. package/dist/writer/write-files.d.ts +12 -0
  297. package/dist/writer/write-files.d.ts.map +1 -0
  298. package/dist/writer/write-files.js +35 -0
  299. package/package.json +70 -0
@@ -0,0 +1,113 @@
1
+ import { promises as fs } from 'fs';
2
+ import { join, resolve } from 'path';
3
+ import chalk from 'chalk';
4
+ import { getCredentials } from '../auth/credentials.js';
5
+ import { generateSchemaFile } from '../schema/schema-loader.js';
6
+ /**
7
+ * Fetch entity models from the API
8
+ */
9
+ async function fetchRemoteSchemas(apiUrl, accessToken) {
10
+ const response = await fetch(`${apiUrl}/graphql`, {
11
+ method: 'POST',
12
+ headers: {
13
+ 'Content-Type': 'application/json',
14
+ Authorization: `Bearer ${accessToken}`,
15
+ },
16
+ body: JSON.stringify({
17
+ query: `
18
+ query GetEntityModels {
19
+ entityModels {
20
+ key
21
+ name
22
+ pluralName
23
+ description
24
+ tier
25
+ editorMode
26
+ fields {
27
+ key
28
+ type
29
+ label
30
+ required
31
+ helpText
32
+ placeholder
33
+ defaultValue
34
+ options
35
+ validation {
36
+ type
37
+ value
38
+ message
39
+ }
40
+ }
41
+ modes {
42
+ records
43
+ inline
44
+ }
45
+ }
46
+ }
47
+ `,
48
+ }),
49
+ });
50
+ if (!response.ok) {
51
+ throw new Error(`Failed to fetch schemas: ${response.statusText}`);
52
+ }
53
+ const result = (await response.json());
54
+ if (result.errors && result.errors.length > 0) {
55
+ throw new Error(`GraphQL error: ${result.errors[0]?.message ?? 'Unknown error'}`);
56
+ }
57
+ return result.data?.entityModels ?? [];
58
+ }
59
+ /**
60
+ * Init command - generate local schema files from platform schemas
61
+ */
62
+ export async function init(options) {
63
+ const credentials = await getCredentials();
64
+ if (!credentials) {
65
+ console.log('Not logged in. Run `uniformgen login` first.');
66
+ process.exit(1);
67
+ }
68
+ if (!credentials.selectedProject) {
69
+ console.log('No project selected. Run `uniformgen select-project` first.');
70
+ process.exit(1);
71
+ }
72
+ console.log(`Initializing schemas from project: ${credentials.selectedProject.name}\n`);
73
+ // Fetch remote schemas
74
+ console.log('Fetching schemas from platform...');
75
+ const schemas = await fetchRemoteSchemas(options.apiUrl, credentials.accessToken);
76
+ if (schemas.length === 0) {
77
+ console.log(chalk.yellow('No schemas found in project.'));
78
+ return;
79
+ }
80
+ console.log(`Found ${schemas.length} schema(s)\n`);
81
+ // Ensure schemas directory exists
82
+ const schemasDir = resolve(process.cwd(), options.schemasDir);
83
+ await fs.mkdir(schemasDir, { recursive: true });
84
+ let created = 0;
85
+ let skipped = 0;
86
+ for (const schema of schemas) {
87
+ const filePath = join(schemasDir, `${schema.key}.schema.ts`);
88
+ // Check if file exists
89
+ try {
90
+ await fs.access(filePath);
91
+ if (!options.overwrite) {
92
+ console.log(chalk.gray(`- ${schema.key}.schema.ts`) + chalk.gray(' (exists, skipped)'));
93
+ skipped++;
94
+ continue;
95
+ }
96
+ }
97
+ catch {
98
+ // File doesn't exist, continue
99
+ }
100
+ // Generate schema file
101
+ const content = generateSchemaFile(schema);
102
+ await fs.writeFile(filePath, content, 'utf-8');
103
+ console.log(chalk.green(`+ ${schema.key}.schema.ts`));
104
+ created++;
105
+ }
106
+ // Summary
107
+ console.log('\n' + '─'.repeat(40));
108
+ console.log('Summary');
109
+ console.log('─'.repeat(40));
110
+ console.log(` Created: ${created}`);
111
+ console.log(` Skipped: ${skipped}`);
112
+ console.log(` Output: ${schemasDir}`);
113
+ }
@@ -0,0 +1,9 @@
1
+ interface LoginOptions {
2
+ apiUrl: string;
3
+ }
4
+ /**
5
+ * Login command - authenticate via browser OAuth
6
+ */
7
+ export declare function login(options: LoginOptions): Promise<void>;
8
+ export {};
9
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAQA,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AA4ED;;GAEG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAmIhE"}
@@ -0,0 +1,158 @@
1
+ import open from 'open';
2
+ import http from 'http';
3
+ import crypto from 'crypto';
4
+ import { writeCredentials, } from '../auth/credentials.js';
5
+ /**
6
+ * Find an available port in a range
7
+ */
8
+ async function findAvailablePort(start, end) {
9
+ for (let port = start; port <= end; port++) {
10
+ const available = await new Promise((resolve) => {
11
+ const server = http.createServer();
12
+ server.listen(port, () => {
13
+ server.close();
14
+ resolve(true);
15
+ });
16
+ server.on('error', () => resolve(false));
17
+ });
18
+ if (available) {
19
+ return port;
20
+ }
21
+ }
22
+ throw new Error(`No available ports in range ${start}-${end}`);
23
+ }
24
+ /**
25
+ * Exchange authorization code for tokens
26
+ */
27
+ async function exchangeCodeForTokens(apiUrl, code, codeVerifier, redirectUri) {
28
+ const tokenUrl = new URL('/auth/cli/token', apiUrl);
29
+ const response = await fetch(tokenUrl.toString(), {
30
+ method: 'POST',
31
+ headers: { 'Content-Type': 'application/json' },
32
+ body: JSON.stringify({
33
+ grant_type: 'authorization_code',
34
+ code,
35
+ code_verifier: codeVerifier,
36
+ redirect_uri: redirectUri,
37
+ }),
38
+ });
39
+ if (!response.ok) {
40
+ const error = await response.text();
41
+ throw new Error(`Token exchange failed: ${error}`);
42
+ }
43
+ const data = (await response.json());
44
+ // Map snake_case API response to camelCase
45
+ return {
46
+ accessToken: data.access_token,
47
+ refreshToken: data.refresh_token,
48
+ expiresIn: data.expires_in,
49
+ user: data.user,
50
+ };
51
+ }
52
+ /**
53
+ * Login command - authenticate via browser OAuth
54
+ */
55
+ export async function login(options) {
56
+ console.log('Starting authentication...\n');
57
+ // Generate PKCE values
58
+ const codeVerifier = crypto.randomBytes(32).toString('base64url');
59
+ const codeChallenge = crypto
60
+ .createHash('sha256')
61
+ .update(codeVerifier)
62
+ .digest('base64url');
63
+ const state = crypto.randomBytes(16).toString('hex');
64
+ const port = await findAvailablePort(9876, 9900);
65
+ const redirectUri = `http://localhost:${port}/callback`;
66
+ // Start local server to receive callback
67
+ const authCode = await new Promise((resolve, reject) => {
68
+ const server = http.createServer((req, res) => {
69
+ const url = new URL(req.url, `http://localhost:${port}`);
70
+ if (url.pathname === '/callback') {
71
+ const code = url.searchParams.get('code');
72
+ const returnedState = url.searchParams.get('state');
73
+ const error = url.searchParams.get('error');
74
+ if (error) {
75
+ res.writeHead(400, { 'Content-Type': 'text/html' });
76
+ res.end(`
77
+ <html>
78
+ <body style="font-family: system-ui; text-align: center; padding: 50px;">
79
+ <h1>✗ Authentication failed</h1>
80
+ <p>${error}</p>
81
+ <p>You can close this window.</p>
82
+ </body>
83
+ </html>
84
+ `);
85
+ server.close();
86
+ reject(new Error(`Authentication failed: ${error}`));
87
+ return;
88
+ }
89
+ if (returnedState !== state) {
90
+ res.writeHead(400, { 'Content-Type': 'text/html' });
91
+ res.end(`
92
+ <html>
93
+ <body style="font-family: system-ui; text-align: center; padding: 50px;">
94
+ <h1>✗ Security error</h1>
95
+ <p>Invalid state parameter. Please try again.</p>
96
+ </body>
97
+ </html>
98
+ `);
99
+ server.close();
100
+ reject(new Error('Invalid state parameter'));
101
+ return;
102
+ }
103
+ // Derive admin URL from API URL (api-dev.eide.app -> admin-dev.eide.app)
104
+ const apiHost = new URL(options.apiUrl).host;
105
+ const adminHost = apiHost.replace(/^api/, 'admin');
106
+ const adminUrl = `https://${adminHost}`;
107
+ res.writeHead(200, { 'Content-Type': 'text/html' });
108
+ res.end(`
109
+ <html>
110
+ <head>
111
+ <meta http-equiv="refresh" content="2;url=${adminUrl}">
112
+ </head>
113
+ <body style="font-family: system-ui; text-align: center; padding: 50px;">
114
+ <h1>Authentication successful!</h1>
115
+ <p>Redirecting to admin panel...</p>
116
+ <p style="color: #666; font-size: 14px;">If not redirected, <a href="${adminUrl}">click here</a>.</p>
117
+ </body>
118
+ </html>
119
+ `);
120
+ server.close();
121
+ resolve(code);
122
+ }
123
+ });
124
+ server.listen(port);
125
+ // Timeout after 5 minutes
126
+ setTimeout(() => {
127
+ server.close();
128
+ reject(new Error('Authentication timed out after 5 minutes'));
129
+ }, 5 * 60 * 1000);
130
+ // Build auth URL and open browser
131
+ const authUrl = new URL('/auth/cli', options.apiUrl);
132
+ authUrl.searchParams.set('response_type', 'code');
133
+ authUrl.searchParams.set('code_challenge', codeChallenge);
134
+ authUrl.searchParams.set('code_challenge_method', 'S256');
135
+ authUrl.searchParams.set('redirect_uri', redirectUri);
136
+ authUrl.searchParams.set('state', state);
137
+ console.log('Opening browser for authentication...');
138
+ console.log(`If the browser doesn't open, visit: ${authUrl.toString()}\n`);
139
+ open(authUrl.toString()).catch(() => {
140
+ console.log('Could not open browser automatically.');
141
+ console.log(`Please visit: ${authUrl.toString()}\n`);
142
+ });
143
+ });
144
+ console.log('Exchanging code for tokens...');
145
+ // Exchange code for tokens
146
+ const tokens = await exchangeCodeForTokens(options.apiUrl, authCode, codeVerifier, redirectUri);
147
+ // Store credentials
148
+ const credentials = {
149
+ accessToken: tokens.accessToken,
150
+ refreshToken: tokens.refreshToken,
151
+ expiresAt: new Date(Date.now() + tokens.expiresIn * 1000).toISOString(),
152
+ user: tokens.user,
153
+ };
154
+ await writeCredentials(credentials);
155
+ console.log(`\n✓ Logged in as ${tokens.user.email}`);
156
+ console.log('\nRun `uniformgen select-project` to choose a project.');
157
+ process.exit(0);
158
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Logout command - clear stored credentials
3
+ */
4
+ export declare function logout(): Promise<void>;
5
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAU5C"}
@@ -0,0 +1,13 @@
1
+ import { deleteCredentials, getCredentials } from '../auth/credentials.js';
2
+ /**
3
+ * Logout command - clear stored credentials
4
+ */
5
+ export async function logout() {
6
+ const credentials = await getCredentials();
7
+ if (!credentials) {
8
+ console.log('Not logged in.');
9
+ return;
10
+ }
11
+ await deleteCredentials();
12
+ console.log(`✓ Logged out (was ${credentials.user.email})`);
13
+ }
@@ -0,0 +1,13 @@
1
+ interface PushOptions {
2
+ apiUrl: string;
3
+ schemasDir: string;
4
+ pattern?: string;
5
+ dryRun?: boolean;
6
+ publish?: boolean;
7
+ }
8
+ /**
9
+ * Push command - sync local schemas to platform
10
+ */
11
+ export declare function push(options: PushOptions): Promise<void>;
12
+ export {};
13
+ //# sourceMappingURL=push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AAaA,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAmVD;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAkJ9D"}
@@ -0,0 +1,328 @@
1
+ import chalk from 'chalk';
2
+ import { getCredentials } from '../auth/credentials.js';
3
+ import { loadSchemas } from '../schema/schema-loader.js';
4
+ /**
5
+ * Get the internal GraphQL endpoint URL from the base API URL
6
+ */
7
+ function getGraphQLEndpoint(apiUrl) {
8
+ const base = apiUrl.replace(/\/$/, '').replace(/\/graphql$/, '');
9
+ return `${base}/graphql`;
10
+ }
11
+ /**
12
+ * Fetch existing entity models from the API
13
+ */
14
+ async function fetchRemoteSchemas(apiUrl, accessToken, tenantId, projectId) {
15
+ const response = await fetch(getGraphQLEndpoint(apiUrl), {
16
+ method: 'POST',
17
+ headers: {
18
+ 'Content-Type': 'application/json',
19
+ Authorization: `Bearer ${accessToken}`,
20
+ 'x-tenant-id': tenantId,
21
+ 'x-project-id': projectId,
22
+ },
23
+ body: JSON.stringify({
24
+ query: `
25
+ query GetEntityModels {
26
+ entityModels(limit: 500) {
27
+ items {
28
+ id
29
+ key
30
+ metadata {
31
+ name
32
+ description
33
+ pluralName
34
+ }
35
+ schema
36
+ currentVersionId
37
+ }
38
+ total
39
+ }
40
+ }
41
+ `,
42
+ }),
43
+ });
44
+ if (!response.ok) {
45
+ const errorText = await response.text().catch(() => 'No response body');
46
+ console.error(`[Debug] API URL: ${apiUrl}`);
47
+ console.error(`[Debug] Response status: ${response.status}`);
48
+ console.error(`[Debug] Response body: ${errorText.substring(0, 500)}`);
49
+ throw new Error(`Failed to fetch schemas: ${response.statusText}`);
50
+ }
51
+ const result = (await response.json());
52
+ if (result.errors && result.errors.length > 0) {
53
+ console.error(`[Debug] GraphQL errors:`, JSON.stringify(result.errors, null, 2));
54
+ throw new Error(`GraphQL error: ${result.errors[0]?.message ?? 'Unknown error'}`);
55
+ }
56
+ const models = new Map();
57
+ for (const model of result.data?.entityModels?.items ?? []) {
58
+ models.set(model.key, model);
59
+ }
60
+ return models;
61
+ }
62
+ /**
63
+ * Create a new entity model
64
+ */
65
+ async function createEntityModel(apiUrl, accessToken, tenantId, projectId, model) {
66
+ const response = await fetch(`${apiUrl}/graphql`, {
67
+ method: 'POST',
68
+ headers: {
69
+ 'Content-Type': 'application/json',
70
+ Authorization: `Bearer ${accessToken}`,
71
+ 'x-tenant-id': tenantId,
72
+ 'x-project-id': projectId,
73
+ },
74
+ body: JSON.stringify({
75
+ query: `
76
+ mutation CreateEntityModel($input: CreateEntityModelInput!) {
77
+ createEntityModel(input: $input) {
78
+ id
79
+ key
80
+ currentVersionId
81
+ }
82
+ }
83
+ `,
84
+ variables: {
85
+ input: {
86
+ key: model.key,
87
+ metadata: {
88
+ name: model.name,
89
+ description: model.description,
90
+ pluralName: model.pluralName,
91
+ },
92
+ schema: {
93
+ fields: model.fields,
94
+ },
95
+ modes: model.modes,
96
+ editorMode: model.editorMode,
97
+ pages: model.pages,
98
+ hooks: model.hooks,
99
+ },
100
+ },
101
+ }),
102
+ });
103
+ if (!response.ok) {
104
+ throw new Error(`Failed to create schema: ${response.statusText}`);
105
+ }
106
+ const result = (await response.json());
107
+ if (result.errors && result.errors.length > 0) {
108
+ throw new Error(result.errors[0]?.message ?? 'Unknown error');
109
+ }
110
+ return {
111
+ id: result.data.createEntityModel.id,
112
+ currentVersionId: result.data.createEntityModel.currentVersionId,
113
+ };
114
+ }
115
+ /**
116
+ * Update an entity model schema
117
+ */
118
+ async function updateEntityModelSchema(apiUrl, accessToken, tenantId, projectId, modelId, model) {
119
+ const response = await fetch(`${apiUrl}/graphql`, {
120
+ method: 'POST',
121
+ headers: {
122
+ 'Content-Type': 'application/json',
123
+ Authorization: `Bearer ${accessToken}`,
124
+ 'x-tenant-id': tenantId,
125
+ 'x-project-id': projectId,
126
+ },
127
+ body: JSON.stringify({
128
+ query: `
129
+ mutation UpdateEntityModel($id: ID!, $input: UpdateEntityModelInput!) {
130
+ updateEntityModel(id: $id, input: $input) {
131
+ id
132
+ key
133
+ currentVersionId
134
+ }
135
+ }
136
+ `,
137
+ variables: {
138
+ id: modelId,
139
+ input: {
140
+ metadata: {
141
+ name: model.name,
142
+ description: model.description,
143
+ pluralName: model.pluralName,
144
+ },
145
+ schema: {
146
+ fields: model.fields,
147
+ },
148
+ modes: model.modes,
149
+ editorMode: model.editorMode,
150
+ pages: model.pages,
151
+ hooks: model.hooks,
152
+ changeDescription: `Updated via uniformgen push`,
153
+ },
154
+ },
155
+ }),
156
+ });
157
+ if (!response.ok) {
158
+ throw new Error(`Failed to update schema: ${response.statusText}`);
159
+ }
160
+ const result = (await response.json());
161
+ if (result.errors && result.errors.length > 0) {
162
+ throw new Error(result.errors[0]?.message ?? 'Unknown error');
163
+ }
164
+ return {
165
+ id: result.data.updateEntityModel.id,
166
+ currentVersionId: result.data.updateEntityModel.currentVersionId,
167
+ };
168
+ }
169
+ /**
170
+ * Publish an entity model schema
171
+ */
172
+ async function publishEntityModelSchema(apiUrl, accessToken, tenantId, projectId, modelId, versionId) {
173
+ const response = await fetch(`${apiUrl}/graphql`, {
174
+ method: 'POST',
175
+ headers: {
176
+ 'Content-Type': 'application/json',
177
+ Authorization: `Bearer ${accessToken}`,
178
+ 'x-tenant-id': tenantId,
179
+ 'x-project-id': projectId,
180
+ },
181
+ body: JSON.stringify({
182
+ query: `
183
+ mutation PublishEntityModel($id: ID!, $versionId: ID!) {
184
+ publishEntityModel(id: $id, versionId: $versionId) {
185
+ id
186
+ key
187
+ }
188
+ }
189
+ `,
190
+ variables: { id: modelId, versionId },
191
+ }),
192
+ });
193
+ if (!response.ok) {
194
+ throw new Error(`Failed to publish schema: ${response.statusText}`);
195
+ }
196
+ const result = (await response.json());
197
+ if (result.errors && result.errors.length > 0) {
198
+ throw new Error(result.errors[0]?.message ?? 'Unknown error');
199
+ }
200
+ }
201
+ /**
202
+ * Compare two schemas and determine if they differ
203
+ */
204
+ function schemasAreDifferent(local, remote) {
205
+ // Compare basic properties via metadata
206
+ if (local.name !== remote.metadata.name ||
207
+ local.pluralName !== remote.metadata.pluralName ||
208
+ local.description !== remote.metadata.description) {
209
+ return true;
210
+ }
211
+ // Compare fields
212
+ const localFields = local.fields ?? [];
213
+ const remoteFields = remote.schema?.fields ?? [];
214
+ if (localFields.length !== remoteFields.length) {
215
+ return true;
216
+ }
217
+ for (let i = 0; i < localFields.length; i++) {
218
+ const localField = localFields[i];
219
+ const remoteField = remoteFields[i];
220
+ if (localField.key !== remoteField.key ||
221
+ localField.type !== remoteField.type ||
222
+ localField.label !== remoteField.label ||
223
+ localField.required !== remoteField.required ||
224
+ localField.helpText !== remoteField.helpText ||
225
+ JSON.stringify(localField.options) !== JSON.stringify(remoteField.options)) {
226
+ return true;
227
+ }
228
+ }
229
+ return false;
230
+ }
231
+ /**
232
+ * Push command - sync local schemas to platform
233
+ */
234
+ export async function push(options) {
235
+ const credentials = await getCredentials();
236
+ if (!credentials) {
237
+ console.log('Not logged in. Run `uniformgen login` first.');
238
+ process.exit(1);
239
+ }
240
+ if (!credentials.selectedProject) {
241
+ console.log('No project selected. Run `uniformgen select-project` first.');
242
+ process.exit(1);
243
+ }
244
+ console.log(`Syncing schemas to project: ${credentials.selectedProject.name}\n`);
245
+ // Load local schemas
246
+ console.log(`Loading schemas from ${options.schemasDir}...`);
247
+ const localSchemas = await loadSchemas(options.schemasDir, options.pattern);
248
+ if (localSchemas.length === 0) {
249
+ console.log(chalk.yellow('No schema files found.'));
250
+ return;
251
+ }
252
+ console.log(`Found ${localSchemas.length} local schema(s)\n`);
253
+ // Fetch remote schemas
254
+ console.log('Fetching remote schemas...');
255
+ const remoteSchemas = await fetchRemoteSchemas(options.apiUrl, credentials.accessToken, credentials.selectedProject.tenantId, credentials.selectedProject.id);
256
+ console.log(`Found ${remoteSchemas.size} remote schema(s)\n`);
257
+ // Compare and sync
258
+ const result = {
259
+ created: [],
260
+ updated: [],
261
+ unchanged: [],
262
+ errors: [],
263
+ };
264
+ for (const local of localSchemas) {
265
+ const remote = remoteSchemas.get(local.key);
266
+ if (!remote) {
267
+ // Create new schema
268
+ if (options.dryRun) {
269
+ console.log(chalk.green(`+ ${local.key}`) + chalk.gray(' (would create)'));
270
+ result.created.push(local.key);
271
+ }
272
+ else {
273
+ try {
274
+ const created = await createEntityModel(options.apiUrl, credentials.accessToken, credentials.selectedProject.tenantId, credentials.selectedProject.id, local);
275
+ if (options.publish && created.currentVersionId) {
276
+ await publishEntityModelSchema(options.apiUrl, credentials.accessToken, credentials.selectedProject.tenantId, credentials.selectedProject.id, created.id, created.currentVersionId);
277
+ }
278
+ console.log(chalk.green(`+ ${local.key}`) + chalk.gray(' (created)'));
279
+ result.created.push(local.key);
280
+ }
281
+ catch (error) {
282
+ const message = error instanceof Error ? error.message : String(error);
283
+ console.log(chalk.red(`✗ ${local.key}`) + chalk.gray(` (error: ${message})`));
284
+ result.errors.push({ key: local.key, error: message });
285
+ }
286
+ }
287
+ }
288
+ else if (schemasAreDifferent(local, remote)) {
289
+ // Update existing schema
290
+ if (options.dryRun) {
291
+ console.log(chalk.yellow(`~ ${local.key}`) + chalk.gray(' (would update)'));
292
+ result.updated.push(local.key);
293
+ }
294
+ else {
295
+ try {
296
+ const updated = await updateEntityModelSchema(options.apiUrl, credentials.accessToken, credentials.selectedProject.tenantId, credentials.selectedProject.id, remote.id, local);
297
+ if (options.publish && updated.currentVersionId) {
298
+ await publishEntityModelSchema(options.apiUrl, credentials.accessToken, credentials.selectedProject.tenantId, credentials.selectedProject.id, updated.id, updated.currentVersionId);
299
+ }
300
+ console.log(chalk.yellow(`~ ${local.key}`) + chalk.gray(' (updated)'));
301
+ result.updated.push(local.key);
302
+ }
303
+ catch (error) {
304
+ const message = error instanceof Error ? error.message : String(error);
305
+ console.log(chalk.red(`✗ ${local.key}`) + chalk.gray(` (error: ${message})`));
306
+ result.errors.push({ key: local.key, error: message });
307
+ }
308
+ }
309
+ }
310
+ else {
311
+ console.log(chalk.gray(`= ${local.key}`) + chalk.gray(' (unchanged)'));
312
+ result.unchanged.push(local.key);
313
+ }
314
+ }
315
+ // Summary
316
+ console.log('\n' + '─'.repeat(40));
317
+ console.log('Summary');
318
+ console.log('─'.repeat(40));
319
+ console.log(` Created: ${result.created.length}`);
320
+ console.log(` Updated: ${result.updated.length}`);
321
+ console.log(` Unchanged: ${result.unchanged.length}`);
322
+ if (result.errors.length > 0) {
323
+ console.log(` Errors: ${result.errors.length}`);
324
+ }
325
+ if (options.dryRun) {
326
+ console.log(chalk.cyan('\n(Dry run - no changes made)'));
327
+ }
328
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Scaffold Command
3
+ *
4
+ * Generates component stubs for EIDE entity models using @eide/foir-renderer.
5
+ * Creates type-safe components that integrate with the EntityRenderer.
6
+ */
7
+ export interface ScaffoldOptions {
8
+ apiUrl: string;
9
+ componentsDir: string;
10
+ models?: string;
11
+ overwrite?: boolean;
12
+ framework?: 'react' | 'remix' | 'next';
13
+ config?: string;
14
+ }
15
+ /**
16
+ * Main scaffold function
17
+ */
18
+ export declare function scaffold(options: ScaffoldOptions): Promise<void>;
19
+ //# sourceMappingURL=scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/commands/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAmSD;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAsGtE"}