@eide/foir-cli 0.1.35 → 0.1.37

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 (228) hide show
  1. package/dist/cli.js +7467 -42
  2. package/dist/config/types.d.ts +7 -6
  3. package/dist/config/types.js +6 -14
  4. package/dist/generated-CPsQ9jfu.d.ts +195 -0
  5. package/dist/lib/extension-helpers.d.ts +10 -7
  6. package/dist/lib/extension-helpers.js +15 -85
  7. package/dist/lib/hook-helpers.d.ts +9 -6
  8. package/dist/lib/hook-helpers.js +12 -105
  9. package/dist/lib/seed-helpers.d.ts +10 -8
  10. package/dist/lib/seed-helpers.js +18 -124
  11. package/dist/schema.graphql +6062 -0
  12. package/package.json +9 -8
  13. package/dist/auth/credentials.d.ts +0 -31
  14. package/dist/auth/credentials.d.ts.map +0 -1
  15. package/dist/auth/credentials.js +0 -139
  16. package/dist/cli.d.ts +0 -3
  17. package/dist/cli.d.ts.map +0 -1
  18. package/dist/codegen/fetch-customer-profile-schema.d.ts +0 -12
  19. package/dist/codegen/fetch-customer-profile-schema.d.ts.map +0 -1
  20. package/dist/codegen/fetch-customer-profile-schema.js +0 -21
  21. package/dist/codegen/fetch-models.d.ts +0 -58
  22. package/dist/codegen/fetch-models.d.ts.map +0 -1
  23. package/dist/codegen/fetch-models.js +0 -96
  24. package/dist/codegen/field-mapping.d.ts +0 -34
  25. package/dist/codegen/field-mapping.d.ts.map +0 -1
  26. package/dist/codegen/field-mapping.js +0 -250
  27. package/dist/codegen/generators/config.d.ts +0 -5
  28. package/dist/codegen/generators/config.d.ts.map +0 -1
  29. package/dist/codegen/generators/config.js +0 -82
  30. package/dist/codegen/generators/customer-profile-documents.d.ts +0 -5
  31. package/dist/codegen/generators/customer-profile-documents.d.ts.map +0 -1
  32. package/dist/codegen/generators/customer-profile-documents.js +0 -42
  33. package/dist/codegen/generators/customer-profile-hooks.d.ts +0 -5
  34. package/dist/codegen/generators/customer-profile-hooks.d.ts.map +0 -1
  35. package/dist/codegen/generators/customer-profile-hooks.js +0 -78
  36. package/dist/codegen/generators/customer-profile-loaders.d.ts +0 -5
  37. package/dist/codegen/generators/customer-profile-loaders.d.ts.map +0 -1
  38. package/dist/codegen/generators/customer-profile-loaders.js +0 -67
  39. package/dist/codegen/generators/customer-profile-operations.d.ts +0 -5
  40. package/dist/codegen/generators/customer-profile-operations.d.ts.map +0 -1
  41. package/dist/codegen/generators/customer-profile-operations.js +0 -126
  42. package/dist/codegen/generators/customer-profile-types.d.ts +0 -6
  43. package/dist/codegen/generators/customer-profile-types.d.ts.map +0 -1
  44. package/dist/codegen/generators/customer-profile-types.js +0 -45
  45. package/dist/codegen/generators/documents.d.ts +0 -12
  46. package/dist/codegen/generators/documents.d.ts.map +0 -1
  47. package/dist/codegen/generators/documents.js +0 -178
  48. package/dist/codegen/generators/field-types.d.ts +0 -5
  49. package/dist/codegen/generators/field-types.d.ts.map +0 -1
  50. package/dist/codegen/generators/field-types.js +0 -346
  51. package/dist/codegen/generators/model-index.d.ts +0 -6
  52. package/dist/codegen/generators/model-index.d.ts.map +0 -1
  53. package/dist/codegen/generators/model-index.js +0 -26
  54. package/dist/codegen/generators/model-types.d.ts +0 -12
  55. package/dist/codegen/generators/model-types.d.ts.map +0 -1
  56. package/dist/codegen/generators/model-types.js +0 -177
  57. package/dist/codegen/generators/public-schema-content.d.ts +0 -14
  58. package/dist/codegen/generators/public-schema-content.d.ts.map +0 -1
  59. package/dist/codegen/generators/public-schema-content.js +0 -22
  60. package/dist/codegen/generators/react-hooks-index.d.ts +0 -6
  61. package/dist/codegen/generators/react-hooks-index.d.ts.map +0 -1
  62. package/dist/codegen/generators/react-hooks-index.js +0 -20
  63. package/dist/codegen/generators/react-hooks.d.ts +0 -7
  64. package/dist/codegen/generators/react-hooks.d.ts.map +0 -1
  65. package/dist/codegen/generators/react-hooks.js +0 -139
  66. package/dist/codegen/generators/remix-loaders-index.d.ts +0 -6
  67. package/dist/codegen/generators/remix-loaders-index.d.ts.map +0 -1
  68. package/dist/codegen/generators/remix-loaders-index.js +0 -20
  69. package/dist/codegen/generators/remix-loaders.d.ts +0 -7
  70. package/dist/codegen/generators/remix-loaders.d.ts.map +0 -1
  71. package/dist/codegen/generators/remix-loaders.js +0 -107
  72. package/dist/codegen/generators/static-documents.d.ts +0 -14
  73. package/dist/codegen/generators/static-documents.d.ts.map +0 -1
  74. package/dist/codegen/generators/static-documents.js +0 -771
  75. package/dist/codegen/generators/swift-customer-profile.d.ts +0 -9
  76. package/dist/codegen/generators/swift-customer-profile.d.ts.map +0 -1
  77. package/dist/codegen/generators/swift-customer-profile.js +0 -152
  78. package/dist/codegen/generators/swift-field-types.d.ts +0 -5
  79. package/dist/codegen/generators/swift-field-types.d.ts.map +0 -1
  80. package/dist/codegen/generators/swift-field-types.js +0 -151
  81. package/dist/codegen/generators/swift-model-keys.d.ts +0 -6
  82. package/dist/codegen/generators/swift-model-keys.d.ts.map +0 -1
  83. package/dist/codegen/generators/swift-model-keys.js +0 -25
  84. package/dist/codegen/generators/swift-types.d.ts +0 -13
  85. package/dist/codegen/generators/swift-types.d.ts.map +0 -1
  86. package/dist/codegen/generators/swift-types.js +0 -188
  87. package/dist/codegen/generators/typed-operations-common.d.ts +0 -6
  88. package/dist/codegen/generators/typed-operations-common.d.ts.map +0 -1
  89. package/dist/codegen/generators/typed-operations-common.js +0 -84
  90. package/dist/codegen/generators/typed-operations-index.d.ts +0 -6
  91. package/dist/codegen/generators/typed-operations-index.d.ts.map +0 -1
  92. package/dist/codegen/generators/typed-operations-index.js +0 -22
  93. package/dist/codegen/generators/typed-operations.d.ts +0 -11
  94. package/dist/codegen/generators/typed-operations.d.ts.map +0 -1
  95. package/dist/codegen/generators/typed-operations.js +0 -263
  96. package/dist/codegen/swift-field-mapping.d.ts +0 -30
  97. package/dist/codegen/swift-field-mapping.d.ts.map +0 -1
  98. package/dist/codegen/swift-field-mapping.js +0 -150
  99. package/dist/codegen/write-files.d.ts +0 -15
  100. package/dist/codegen/write-files.d.ts.map +0 -1
  101. package/dist/codegen/write-files.js +0 -36
  102. package/dist/commands/api-keys.d.ts +0 -4
  103. package/dist/commands/api-keys.d.ts.map +0 -1
  104. package/dist/commands/api-keys.js +0 -129
  105. package/dist/commands/auth-config.d.ts +0 -4
  106. package/dist/commands/auth-config.d.ts.map +0 -1
  107. package/dist/commands/auth-config.js +0 -38
  108. package/dist/commands/auth-providers.d.ts +0 -4
  109. package/dist/commands/auth-providers.d.ts.map +0 -1
  110. package/dist/commands/auth-providers.js +0 -207
  111. package/dist/commands/context.d.ts +0 -4
  112. package/dist/commands/context.d.ts.map +0 -1
  113. package/dist/commands/context.js +0 -91
  114. package/dist/commands/create-extension.d.ts +0 -4
  115. package/dist/commands/create-extension.d.ts.map +0 -1
  116. package/dist/commands/create-extension.js +0 -60
  117. package/dist/commands/customer-profiles.d.ts +0 -4
  118. package/dist/commands/customer-profiles.d.ts.map +0 -1
  119. package/dist/commands/customer-profiles.js +0 -99
  120. package/dist/commands/customers.d.ts +0 -4
  121. package/dist/commands/customers.d.ts.map +0 -1
  122. package/dist/commands/customers.js +0 -126
  123. package/dist/commands/embeddings.d.ts +0 -4
  124. package/dist/commands/embeddings.d.ts.map +0 -1
  125. package/dist/commands/embeddings.js +0 -145
  126. package/dist/commands/experiments.d.ts +0 -4
  127. package/dist/commands/experiments.d.ts.map +0 -1
  128. package/dist/commands/experiments.js +0 -196
  129. package/dist/commands/extensions.d.ts +0 -4
  130. package/dist/commands/extensions.d.ts.map +0 -1
  131. package/dist/commands/extensions.js +0 -210
  132. package/dist/commands/files.d.ts +0 -4
  133. package/dist/commands/files.d.ts.map +0 -1
  134. package/dist/commands/files.js +0 -143
  135. package/dist/commands/hooks.d.ts +0 -4
  136. package/dist/commands/hooks.d.ts.map +0 -1
  137. package/dist/commands/hooks.js +0 -228
  138. package/dist/commands/locales.d.ts +0 -4
  139. package/dist/commands/locales.d.ts.map +0 -1
  140. package/dist/commands/locales.js +0 -140
  141. package/dist/commands/login.d.ts +0 -4
  142. package/dist/commands/login.d.ts.map +0 -1
  143. package/dist/commands/login.js +0 -124
  144. package/dist/commands/logout.d.ts +0 -4
  145. package/dist/commands/logout.d.ts.map +0 -1
  146. package/dist/commands/logout.js +0 -16
  147. package/dist/commands/media.d.ts +0 -4
  148. package/dist/commands/media.d.ts.map +0 -1
  149. package/dist/commands/media.js +0 -44
  150. package/dist/commands/models.d.ts +0 -4
  151. package/dist/commands/models.d.ts.map +0 -1
  152. package/dist/commands/models.js +0 -153
  153. package/dist/commands/notes.d.ts +0 -4
  154. package/dist/commands/notes.d.ts.map +0 -1
  155. package/dist/commands/notes.js +0 -132
  156. package/dist/commands/notifications.d.ts +0 -4
  157. package/dist/commands/notifications.d.ts.map +0 -1
  158. package/dist/commands/notifications.js +0 -73
  159. package/dist/commands/operations.d.ts +0 -4
  160. package/dist/commands/operations.d.ts.map +0 -1
  161. package/dist/commands/operations.js +0 -341
  162. package/dist/commands/playground.d.ts +0 -4
  163. package/dist/commands/playground.d.ts.map +0 -1
  164. package/dist/commands/playground.js +0 -270
  165. package/dist/commands/pull.d.ts +0 -4
  166. package/dist/commands/pull.d.ts.map +0 -1
  167. package/dist/commands/pull.js +0 -300
  168. package/dist/commands/records.d.ts +0 -4
  169. package/dist/commands/records.d.ts.map +0 -1
  170. package/dist/commands/records.js +0 -314
  171. package/dist/commands/register-commands.d.ts +0 -7
  172. package/dist/commands/register-commands.d.ts.map +0 -1
  173. package/dist/commands/register-commands.js +0 -259
  174. package/dist/commands/schedules.d.ts +0 -4
  175. package/dist/commands/schedules.d.ts.map +0 -1
  176. package/dist/commands/schedules.js +0 -155
  177. package/dist/commands/search.d.ts +0 -4
  178. package/dist/commands/search.d.ts.map +0 -1
  179. package/dist/commands/search.js +0 -60
  180. package/dist/commands/segments.d.ts +0 -4
  181. package/dist/commands/segments.d.ts.map +0 -1
  182. package/dist/commands/segments.js +0 -155
  183. package/dist/commands/select-project.d.ts +0 -4
  184. package/dist/commands/select-project.d.ts.map +0 -1
  185. package/dist/commands/select-project.js +0 -144
  186. package/dist/commands/settings.d.ts +0 -4
  187. package/dist/commands/settings.d.ts.map +0 -1
  188. package/dist/commands/settings.js +0 -115
  189. package/dist/commands/variant-catalog.d.ts +0 -4
  190. package/dist/commands/variant-catalog.d.ts.map +0 -1
  191. package/dist/commands/variant-catalog.js +0 -118
  192. package/dist/commands/whoami.d.ts +0 -4
  193. package/dist/commands/whoami.d.ts.map +0 -1
  194. package/dist/commands/whoami.js +0 -51
  195. package/dist/config/pull-config.d.ts +0 -33
  196. package/dist/config/pull-config.d.ts.map +0 -1
  197. package/dist/config/pull-config.js +0 -119
  198. package/dist/config/types.d.ts.map +0 -1
  199. package/dist/graphql/generated.d.ts +0 -6074
  200. package/dist/graphql/generated.d.ts.map +0 -1
  201. package/dist/graphql/generated.js +0 -355
  202. package/dist/lib/client.d.ts +0 -18
  203. package/dist/lib/client.d.ts.map +0 -1
  204. package/dist/lib/client.js +0 -64
  205. package/dist/lib/config-loader.d.ts +0 -28
  206. package/dist/lib/config-loader.d.ts.map +0 -1
  207. package/dist/lib/config-loader.js +0 -49
  208. package/dist/lib/config.d.ts +0 -12
  209. package/dist/lib/config.d.ts.map +0 -1
  210. package/dist/lib/config.js +0 -8
  211. package/dist/lib/errors.d.ts +0 -6
  212. package/dist/lib/errors.d.ts.map +0 -1
  213. package/dist/lib/errors.js +0 -76
  214. package/dist/lib/extension-helpers.d.ts.map +0 -1
  215. package/dist/lib/hook-helpers.d.ts.map +0 -1
  216. package/dist/lib/input.d.ts +0 -38
  217. package/dist/lib/input.d.ts.map +0 -1
  218. package/dist/lib/input.js +0 -108
  219. package/dist/lib/output.d.ts +0 -31
  220. package/dist/lib/output.d.ts.map +0 -1
  221. package/dist/lib/output.js +0 -107
  222. package/dist/lib/seed-helpers.d.ts.map +0 -1
  223. package/dist/scaffold/package-manager.d.ts +0 -12
  224. package/dist/scaffold/package-manager.d.ts.map +0 -1
  225. package/dist/scaffold/package-manager.js +0 -51
  226. package/dist/scaffold/scaffold.d.ts +0 -4
  227. package/dist/scaffold/scaffold.d.ts.map +0 -1
  228. package/dist/scaffold/scaffold.js +0 -462
@@ -1,140 +0,0 @@
1
- import { withErrorHandler } from '../lib/errors.js';
2
- import { createClient } from '../lib/client.js';
3
- import { formatOutput, formatList, success } from '../lib/output.js';
4
- import { parseInputData, confirmAction } from '../lib/input.js';
5
- import { ListLocalesDocument, GetLocaleDocument, GetLocaleByCodeDocument, GetDefaultLocaleDocument, CreateLocaleDocument, UpdateLocaleDocument, DeleteLocaleDocument, } from '../graphql/generated.js';
6
- export function registerLocalesCommands(program, globalOpts) {
7
- const locales = program.command('locales').description('Manage locales');
8
- // list
9
- locales
10
- .command('list')
11
- .description('List locales')
12
- .option('--include-inactive', 'Include inactive locales')
13
- .option('--limit <n>', 'Max results', '50')
14
- .action(withErrorHandler(globalOpts, async (cmdOpts) => {
15
- const opts = globalOpts();
16
- const client = await createClient(opts);
17
- const data = await client.request(ListLocalesDocument, {
18
- includeInactive: !!cmdOpts.includeInactive,
19
- limit: parseInt(String(cmdOpts.limit ?? '50'), 10),
20
- });
21
- formatList(data.locales, opts, {
22
- columns: [
23
- { key: 'locale', header: 'Code', width: 8 },
24
- { key: 'displayName', header: 'Name', width: 20 },
25
- { key: 'nativeName', header: 'Native', width: 20 },
26
- {
27
- key: 'isDefault',
28
- header: 'Default',
29
- width: 8,
30
- format: (v) => (v ? 'yes' : ''),
31
- },
32
- {
33
- key: 'isActive',
34
- header: 'Active',
35
- width: 8,
36
- format: (v) => (v ? 'yes' : 'no'),
37
- },
38
- {
39
- key: 'isRtl',
40
- header: 'RTL',
41
- width: 4,
42
- format: (v) => (v ? 'yes' : ''),
43
- },
44
- ],
45
- });
46
- }));
47
- // get
48
- locales
49
- .command('get <idOrCode>')
50
- .description('Get a locale by ID or code')
51
- .action(withErrorHandler(globalOpts, async (idOrCode) => {
52
- const opts = globalOpts();
53
- const client = await createClient(opts);
54
- let result;
55
- // Locale codes are short (e.g. "en", "en-US") — not UUIDs
56
- if (/^[0-9a-f]{8}-/.test(idOrCode)) {
57
- const data = await client.request(GetLocaleDocument, {
58
- id: idOrCode,
59
- });
60
- result = data.locale;
61
- }
62
- else {
63
- const data = await client.request(GetLocaleByCodeDocument, {
64
- code: idOrCode,
65
- });
66
- result = data.localeByCode;
67
- }
68
- if (!result)
69
- throw new Error(`Locale "${idOrCode}" not found.`);
70
- formatOutput(result, opts);
71
- }));
72
- // default
73
- locales
74
- .command('default')
75
- .description('Get the default locale')
76
- .action(withErrorHandler(globalOpts, async () => {
77
- const opts = globalOpts();
78
- const client = await createClient(opts);
79
- const data = await client.request(GetDefaultLocaleDocument);
80
- if (!data.defaultLocale)
81
- throw new Error('No default locale configured.');
82
- formatOutput(data.defaultLocale, opts);
83
- }));
84
- // create
85
- locales
86
- .command('create')
87
- .description('Create a new locale')
88
- .option('-d, --data <json>', 'Locale data as JSON')
89
- .option('-f, --file <path>', 'Read data from file')
90
- .action(withErrorHandler(globalOpts, async (cmdOpts) => {
91
- const opts = globalOpts();
92
- const client = await createClient(opts);
93
- const input = await parseInputData(cmdOpts);
94
- const data = await client.request(CreateLocaleDocument, {
95
- input,
96
- });
97
- formatOutput(data.createLocale, opts);
98
- if (!(opts.json || opts.jsonl || opts.quiet))
99
- success(`Created locale ${data.createLocale.locale}`);
100
- }));
101
- // update
102
- locales
103
- .command('update <id>')
104
- .description('Update a locale')
105
- .option('-d, --data <json>', 'Locale data as JSON')
106
- .option('-f, --file <path>', 'Read data from file')
107
- .action(withErrorHandler(globalOpts, async (id, cmdOpts) => {
108
- const opts = globalOpts();
109
- const client = await createClient(opts);
110
- const input = await parseInputData(cmdOpts);
111
- const data = await client.request(UpdateLocaleDocument, {
112
- id,
113
- input,
114
- });
115
- formatOutput(data.updateLocale, opts);
116
- if (!(opts.json || opts.jsonl || opts.quiet))
117
- success(`Updated locale ${data.updateLocale.locale}`);
118
- }));
119
- // delete
120
- locales
121
- .command('delete <id>')
122
- .description('Delete a locale')
123
- .option('--confirm', 'Skip confirmation prompt')
124
- .action(withErrorHandler(globalOpts, async (id, cmdOpts) => {
125
- const opts = globalOpts();
126
- const confirmed = await confirmAction(`Delete locale ${id}?`, {
127
- confirm: !!cmdOpts.confirm,
128
- });
129
- if (!confirmed) {
130
- console.log('Aborted.');
131
- return;
132
- }
133
- const client = await createClient(opts);
134
- await client.request(DeleteLocaleDocument, { id });
135
- if (opts.json || opts.jsonl)
136
- formatOutput({ deleted: true, id }, opts);
137
- else
138
- success(`Deleted locale ${id}`);
139
- }));
140
- }
@@ -1,4 +0,0 @@
1
- import type { Command } from 'commander';
2
- import { type GlobalOptions } from '../lib/config.js';
3
- export declare function registerLoginCommand(program: Command, globalOpts: () => GlobalOptions): void;
4
- //# sourceMappingURL=login.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,OAAO,EAAa,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AA2KjE,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,aAAa,GAC9B,IAAI,CASN"}
@@ -1,124 +0,0 @@
1
- import open from 'open';
2
- import http from 'http';
3
- import crypto from 'crypto';
4
- import { writeCredentials, } from '../auth/credentials.js';
5
- import { getApiUrl } from '../lib/config.js';
6
- import { withErrorHandler } from '../lib/errors.js';
7
- async function findAvailablePort(start, end) {
8
- for (let port = start; port <= end; port++) {
9
- const available = await new Promise((resolve) => {
10
- const server = http.createServer();
11
- server.listen(port, () => {
12
- server.close();
13
- resolve(true);
14
- });
15
- server.on('error', () => resolve(false));
16
- });
17
- if (available)
18
- return port;
19
- }
20
- throw new Error(`No available ports in range ${start}-${end}`);
21
- }
22
- async function exchangeCodeForTokens(apiUrl, code, codeVerifier, redirectUri) {
23
- const tokenUrl = new URL('/auth/cli/token', apiUrl);
24
- const response = await fetch(tokenUrl.toString(), {
25
- method: 'POST',
26
- headers: { 'Content-Type': 'application/json' },
27
- body: JSON.stringify({
28
- grant_type: 'authorization_code',
29
- code,
30
- code_verifier: codeVerifier,
31
- redirect_uri: redirectUri,
32
- }),
33
- });
34
- if (!response.ok) {
35
- const error = await response.text();
36
- throw new Error(`Token exchange failed: ${error}`);
37
- }
38
- const data = (await response.json());
39
- return {
40
- accessToken: data.access_token,
41
- refreshToken: data.refresh_token,
42
- expiresIn: data.expires_in,
43
- user: data.user,
44
- };
45
- }
46
- async function loginAction(globalOpts) {
47
- const apiUrl = getApiUrl(globalOpts);
48
- console.log('Starting authentication...\n');
49
- const codeVerifier = crypto.randomBytes(32).toString('base64url');
50
- const codeChallenge = crypto
51
- .createHash('sha256')
52
- .update(codeVerifier)
53
- .digest('base64url');
54
- const state = crypto.randomBytes(16).toString('hex');
55
- const port = await findAvailablePort(9876, 9900);
56
- const redirectUri = `http://localhost:${port}/callback`;
57
- const authCode = await new Promise((resolve, reject) => {
58
- const server = http.createServer((req, res) => {
59
- const url = new URL(req.url, `http://localhost:${port}`);
60
- if (url.pathname === '/callback') {
61
- const code = url.searchParams.get('code');
62
- const returnedState = url.searchParams.get('state');
63
- const error = url.searchParams.get('error');
64
- if (error) {
65
- res.writeHead(400, { 'Content-Type': 'text/html' });
66
- res.end(`<html><body style="font-family:system-ui;text-align:center;padding:50px"><h1>Authentication failed</h1><p>${error}</p></body></html>`);
67
- server.close();
68
- reject(new Error(`Authentication failed: ${error}`));
69
- return;
70
- }
71
- if (returnedState !== state) {
72
- res.writeHead(400, { 'Content-Type': 'text/html' });
73
- res.end(`<html><body style="font-family:system-ui;text-align:center;padding:50px"><h1>Security error</h1><p>Invalid state. Please try again.</p></body></html>`);
74
- server.close();
75
- reject(new Error('Invalid state parameter'));
76
- return;
77
- }
78
- const apiHost = new URL(apiUrl).host;
79
- const mainHost = apiHost.replace(/^api\./, '');
80
- const mainUrl = `https://${mainHost}`;
81
- res.writeHead(200, { 'Content-Type': 'text/html' });
82
- res.end(`<html><head><meta http-equiv="refresh" content="2;url=${mainUrl}"></head><body style="font-family:system-ui;text-align:center;padding:50px"><h1>Authentication successful!</h1><p>You can close this window.</p></body></html>`);
83
- server.close();
84
- resolve(code);
85
- }
86
- });
87
- server.listen(port);
88
- setTimeout(() => {
89
- server.close();
90
- reject(new Error('Authentication timed out after 5 minutes'));
91
- }, 5 * 60 * 1000);
92
- const authUrl = new URL('/auth/cli', apiUrl);
93
- authUrl.searchParams.set('response_type', 'code');
94
- authUrl.searchParams.set('code_challenge', codeChallenge);
95
- authUrl.searchParams.set('code_challenge_method', 'S256');
96
- authUrl.searchParams.set('redirect_uri', redirectUri);
97
- authUrl.searchParams.set('state', state);
98
- console.log('Opening browser for authentication...');
99
- console.log(`If the browser doesn't open, visit: ${authUrl.toString()}\n`);
100
- open(authUrl.toString()).catch(() => {
101
- console.log('Could not open browser automatically.');
102
- console.log(`Please visit: ${authUrl.toString()}\n`);
103
- });
104
- });
105
- console.log('Exchanging code for tokens...');
106
- const tokens = await exchangeCodeForTokens(apiUrl, authCode, codeVerifier, redirectUri);
107
- const credentials = {
108
- accessToken: tokens.accessToken,
109
- refreshToken: tokens.refreshToken,
110
- expiresAt: new Date(Date.now() + tokens.expiresIn * 1000).toISOString(),
111
- user: tokens.user,
112
- };
113
- await writeCredentials(credentials);
114
- console.log(`\n✓ Logged in as ${tokens.user.email}`);
115
- console.log('\nRun `foir select-project` to choose a project.');
116
- }
117
- export function registerLoginCommand(program, globalOpts) {
118
- program
119
- .command('login')
120
- .description('Authenticate via browser OAuth')
121
- .action(withErrorHandler(globalOpts, async () => {
122
- await loginAction(globalOpts());
123
- }));
124
- }
@@ -1,4 +0,0 @@
1
- import type { Command } from 'commander';
2
- import type { GlobalOptions } from '../lib/config.js';
3
- export declare function registerLogoutCommand(program: Command, globalOpts: () => GlobalOptions): void;
4
- //# sourceMappingURL=logout.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,aAAa,GAC9B,IAAI,CAeN"}
@@ -1,16 +0,0 @@
1
- import { deleteCredentials, getCredentials } from '../auth/credentials.js';
2
- import { withErrorHandler } from '../lib/errors.js';
3
- export function registerLogoutCommand(program, globalOpts) {
4
- program
5
- .command('logout')
6
- .description('Clear stored credentials')
7
- .action(withErrorHandler(globalOpts, async () => {
8
- const credentials = await getCredentials();
9
- if (!credentials) {
10
- console.log('Not logged in.');
11
- return;
12
- }
13
- await deleteCredentials();
14
- console.log(`✓ Logged out (was ${credentials.user.email})`);
15
- }));
16
- }
@@ -1,4 +0,0 @@
1
- import type { Command } from 'commander';
2
- import type { GlobalOptions } from '../lib/config.js';
3
- export declare function registerMediaCommands(program: Command, globalOpts: () => GlobalOptions): void;
4
- //# sourceMappingURL=media.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/commands/media.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAKtD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,aAAa,GAC9B,IAAI,CA6CN"}
@@ -1,44 +0,0 @@
1
- import { promises as fs } from 'fs';
2
- import { basename } from 'path';
3
- import chalk from 'chalk';
4
- import { withErrorHandler } from '../lib/errors.js';
5
- import { getRestAuth } from '../lib/client.js';
6
- import { formatOutput, success } from '../lib/output.js';
7
- export function registerMediaCommands(program, globalOpts) {
8
- const media = program.command('media').description('Media file operations');
9
- // upload
10
- media
11
- .command('upload <filepath>')
12
- .description('Upload a file')
13
- .action(withErrorHandler(globalOpts, async (filepath) => {
14
- const opts = globalOpts();
15
- const { apiUrl, headers } = await getRestAuth(opts);
16
- const fileBuffer = await fs.readFile(filepath);
17
- const fileName = basename(filepath);
18
- const formData = new FormData();
19
- formData.append('file', new Blob([fileBuffer]), fileName);
20
- const uploadUrl = `${apiUrl.replace(/\/$/, '')}/api/files/upload`;
21
- const response = await fetch(uploadUrl, {
22
- method: 'POST',
23
- headers,
24
- body: formData,
25
- });
26
- if (!response.ok) {
27
- const errorText = await response.text();
28
- throw new Error(`Upload failed (${response.status}): ${errorText}`);
29
- }
30
- const result = (await response.json());
31
- if (opts.json || opts.jsonl) {
32
- formatOutput(result, opts);
33
- }
34
- else {
35
- success(`Uploaded ${fileName}`);
36
- if (result.url) {
37
- console.log(chalk.bold(` URL: ${result.url}`));
38
- }
39
- if (result.storageKey) {
40
- console.log(chalk.gray(` Key: ${result.storageKey}`));
41
- }
42
- }
43
- }));
44
- }
@@ -1,4 +0,0 @@
1
- import type { Command } from 'commander';
2
- import type { GlobalOptions } from '../lib/config.js';
3
- export declare function registerModelsCommands(program: Command, globalOpts: () => GlobalOptions): void;
4
- //# sourceMappingURL=models.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AActD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,aAAa,GAC9B,IAAI,CAyLN"}
@@ -1,153 +0,0 @@
1
- import { withErrorHandler } from '../lib/errors.js';
2
- import { createClient } from '../lib/client.js';
3
- import { formatOutput, formatList, timeAgo, success } from '../lib/output.js';
4
- import { parseInputData, confirmAction } from '../lib/input.js';
5
- import { ListModelsDocument, GetModelByKeyDocument, CreateModelDocument, UpdateModelDocument, DeleteModelDocument, ModelVersionsDocument, } from '../graphql/generated.js';
6
- export function registerModelsCommands(program, globalOpts) {
7
- const models = program.command('models').description('Manage models');
8
- // list
9
- models
10
- .command('list')
11
- .description('List all models')
12
- .option('--category <cat>', 'Filter by category')
13
- .option('--search <term>', 'Search by name')
14
- .option('--limit <n>', 'Max results', '50')
15
- .option('--offset <n>', 'Skip results', '0')
16
- .action(withErrorHandler(globalOpts, async (cmdOpts) => {
17
- const opts = globalOpts();
18
- const client = await createClient(opts);
19
- const data = await client.request(ListModelsDocument, {
20
- search: cmdOpts.search,
21
- category: cmdOpts.category,
22
- limit: parseInt(cmdOpts.limit ?? '50', 10),
23
- offset: parseInt(cmdOpts.offset ?? '0', 10),
24
- });
25
- formatList(data.models.items, opts, {
26
- columns: [
27
- { key: 'key', header: 'Key', width: 24 },
28
- { key: 'name', header: 'Name', width: 24 },
29
- { key: 'category', header: 'Category', width: 14 },
30
- {
31
- key: 'updatedAt',
32
- header: 'Updated',
33
- width: 12,
34
- format: (v) => timeAgo(v),
35
- },
36
- ],
37
- total: data.models.total,
38
- });
39
- }));
40
- // get
41
- models
42
- .command('get <key>')
43
- .description('Get a model by key')
44
- .action(withErrorHandler(globalOpts, async (key) => {
45
- const opts = globalOpts();
46
- const client = await createClient(opts);
47
- const data = await client.request(GetModelByKeyDocument, { key });
48
- if (!data.modelByKey) {
49
- throw new Error(`Model "${key}" not found.`);
50
- }
51
- formatOutput(data.modelByKey, opts);
52
- }));
53
- // create
54
- models
55
- .command('create')
56
- .description('Create a new model')
57
- .option('-d, --data <json>', 'Model data as JSON')
58
- .option('-f, --file <path>', 'Read data from file')
59
- .action(withErrorHandler(globalOpts, async (cmdOpts) => {
60
- const opts = globalOpts();
61
- const client = await createClient(opts);
62
- const inputData = await parseInputData(cmdOpts);
63
- const data = await client.request(CreateModelDocument, {
64
- input: inputData,
65
- });
66
- formatOutput(data.createModel, opts);
67
- if (!(opts.json || opts.jsonl || opts.quiet)) {
68
- success(`Created model ${data.createModel.key}`);
69
- }
70
- }));
71
- // update
72
- models
73
- .command('update <key>')
74
- .description('Update a model')
75
- .option('-d, --data <json>', 'Model data as JSON')
76
- .option('-f, --file <path>', 'Read data from file')
77
- .action(withErrorHandler(globalOpts, async (key, cmdOpts) => {
78
- const opts = globalOpts();
79
- const client = await createClient(opts);
80
- // Resolve key -> id
81
- const existing = await client.request(GetModelByKeyDocument, { key });
82
- if (!existing.modelByKey) {
83
- throw new Error(`Model "${key}" not found.`);
84
- }
85
- const inputData = await parseInputData(cmdOpts);
86
- const input = { id: existing.modelByKey.id, ...inputData };
87
- const data = await client.request(UpdateModelDocument, { input });
88
- formatOutput(data.updateModel, opts);
89
- if (!(opts.json || opts.jsonl || opts.quiet)) {
90
- success(`Updated model ${key}`);
91
- }
92
- }));
93
- // delete
94
- models
95
- .command('delete <key>')
96
- .description('Delete a model')
97
- .option('--confirm', 'Skip confirmation prompt')
98
- .action(withErrorHandler(globalOpts, async (key, cmdOpts) => {
99
- const opts = globalOpts();
100
- const confirmed = await confirmAction(`Delete model "${key}"?`, {
101
- confirm: !!cmdOpts.confirm,
102
- });
103
- if (!confirmed) {
104
- console.log('Aborted.');
105
- return;
106
- }
107
- const client = await createClient(opts);
108
- const existing = await client.request(GetModelByKeyDocument, { key });
109
- if (!existing.modelByKey) {
110
- throw new Error(`Model "${key}" not found.`);
111
- }
112
- await client.request(DeleteModelDocument, {
113
- id: existing.modelByKey.id,
114
- });
115
- if (opts.json || opts.jsonl) {
116
- formatOutput({ deleted: true, key }, opts);
117
- }
118
- else {
119
- success(`Deleted model ${key}`);
120
- }
121
- }));
122
- // versions
123
- models
124
- .command('versions <key>')
125
- .description('List schema versions for a model')
126
- .option('--limit <n>', 'Max results', '20')
127
- .action(withErrorHandler(globalOpts, async (key, cmdOpts) => {
128
- const opts = globalOpts();
129
- const client = await createClient(opts);
130
- const existing = await client.request(GetModelByKeyDocument, { key });
131
- if (!existing.modelByKey) {
132
- throw new Error(`Model "${key}" not found.`);
133
- }
134
- const data = await client.request(ModelVersionsDocument, {
135
- modelId: existing.modelByKey.id,
136
- limit: parseInt(cmdOpts.limit ?? '20', 10),
137
- });
138
- formatList(data.modelVersions.items, opts, {
139
- columns: [
140
- { key: 'id', header: 'Version ID', width: 28 },
141
- { key: 'versionNumber', header: '#', width: 5 },
142
- { key: 'changeDescription', header: 'Description', width: 32 },
143
- {
144
- key: 'createdAt',
145
- header: 'Created',
146
- width: 12,
147
- format: (v) => timeAgo(v),
148
- },
149
- { key: 'createdBy', header: 'By', width: 18 },
150
- ],
151
- });
152
- }));
153
- }
@@ -1,4 +0,0 @@
1
- import type { Command } from 'commander';
2
- import type { GlobalOptions } from '../lib/config.js';
3
- export declare function registerNotesCommands(program: Command, globalOpts: () => GlobalOptions): void;
4
- //# sourceMappingURL=notes.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"notes.d.ts","sourceRoot":"","sources":["../../src/commands/notes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAatD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,aAAa,GAC9B,IAAI,CAgJN"}
@@ -1,132 +0,0 @@
1
- import { withErrorHandler } from '../lib/errors.js';
2
- import { createClient } from '../lib/client.js';
3
- import { formatOutput, formatList, timeAgo, success } from '../lib/output.js';
4
- import { confirmAction } from '../lib/input.js';
5
- import { ListNotesDocument, GetNoteDocument, CreateNoteDocument, ResolveNoteDocument, DeleteNoteDocument, } from '../graphql/generated.js';
6
- export function registerNotesCommands(program, globalOpts) {
7
- const notes = program
8
- .command('notes')
9
- .description('Manage notes and comments');
10
- // list
11
- notes
12
- .command('list')
13
- .description('List notes for an entity')
14
- .requiredOption('--entity-type <type>', 'Entity type (e.g. record, model)')
15
- .requiredOption('--entity-id <id>', 'Entity ID')
16
- .option('--include-resolved', 'Include resolved notes')
17
- .option('--limit <n>', 'Max results', '20')
18
- .action(withErrorHandler(globalOpts, async (cmdOpts) => {
19
- const opts = globalOpts();
20
- const client = await createClient(opts);
21
- const data = await client.request(ListNotesDocument, {
22
- entityType: cmdOpts.entityType,
23
- entityId: cmdOpts.entityId,
24
- includeResolved: !!cmdOpts.includeResolved,
25
- limit: parseInt(String(cmdOpts.limit ?? '20'), 10),
26
- });
27
- formatList(data.notes.items, opts, {
28
- columns: [
29
- { key: 'id', header: 'ID', width: 28 },
30
- {
31
- key: 'content',
32
- header: 'Content',
33
- width: 40,
34
- format: (v) => (typeof v === 'string' ? v : JSON.stringify(v)),
35
- },
36
- {
37
- key: 'author',
38
- header: 'Author',
39
- width: 16,
40
- format: (v) => v?.email ?? '',
41
- },
42
- {
43
- key: 'isResolved',
44
- header: 'Resolved',
45
- width: 9,
46
- format: (v) => (v ? 'yes' : ''),
47
- },
48
- {
49
- key: 'createdAt',
50
- header: 'Created',
51
- width: 12,
52
- format: (v) => timeAgo(v),
53
- },
54
- ],
55
- total: data.notes.total,
56
- });
57
- }));
58
- // get
59
- notes
60
- .command('get <id>')
61
- .description('Get a note by ID')
62
- .action(withErrorHandler(globalOpts, async (id) => {
63
- const opts = globalOpts();
64
- const client = await createClient(opts);
65
- const data = await client.request(GetNoteDocument, { id });
66
- if (!data.note)
67
- throw new Error(`Note "${id}" not found.`);
68
- formatOutput(data.note, opts);
69
- }));
70
- // create
71
- notes
72
- .command('create')
73
- .description('Create a note')
74
- .requiredOption('--entity-type <type>', 'Entity type')
75
- .requiredOption('--entity-id <id>', 'Entity ID')
76
- .requiredOption('--body <text>', 'Note body text')
77
- .option('--parent-note-id <id>', 'Reply to a note')
78
- .action(withErrorHandler(globalOpts, async (cmdOpts) => {
79
- const opts = globalOpts();
80
- const client = await createClient(opts);
81
- const input = {
82
- entityType: cmdOpts.entityType,
83
- entityId: cmdOpts.entityId,
84
- body: cmdOpts.body,
85
- };
86
- if (cmdOpts.parentNoteId)
87
- input.parentNoteId = cmdOpts.parentNoteId;
88
- const data = await client.request(CreateNoteDocument, { input });
89
- formatOutput(data.createNote, opts);
90
- if (!(opts.json || opts.jsonl || opts.quiet))
91
- success('Note created');
92
- }));
93
- // resolve
94
- notes
95
- .command('resolve <id>')
96
- .description('Resolve a note')
97
- .option('--resolution <text>', 'Resolution message')
98
- .action(withErrorHandler(globalOpts, async (id, cmdOpts) => {
99
- const opts = globalOpts();
100
- const client = await createClient(opts);
101
- const input = { noteId: id };
102
- if (cmdOpts.resolution)
103
- input.resolution = cmdOpts.resolution;
104
- const data = await client.request(ResolveNoteDocument, {
105
- input,
106
- });
107
- formatOutput(data.resolveNote, opts);
108
- if (!(opts.json || opts.jsonl || opts.quiet))
109
- success(`Resolved note ${id}`);
110
- }));
111
- // delete
112
- notes
113
- .command('delete <id>')
114
- .description('Delete a note')
115
- .option('--confirm', 'Skip confirmation prompt')
116
- .action(withErrorHandler(globalOpts, async (id, cmdOpts) => {
117
- const opts = globalOpts();
118
- const confirmed = await confirmAction(`Delete note ${id}?`, {
119
- confirm: !!cmdOpts.confirm,
120
- });
121
- if (!confirmed) {
122
- console.log('Aborted.');
123
- return;
124
- }
125
- const client = await createClient(opts);
126
- await client.request(DeleteNoteDocument, { noteId: id });
127
- if (opts.json || opts.jsonl)
128
- formatOutput({ deleted: true, id }, opts);
129
- else
130
- success(`Deleted note ${id}`);
131
- }));
132
- }
@@ -1,4 +0,0 @@
1
- import type { Command } from 'commander';
2
- import type { GlobalOptions } from '../lib/config.js';
3
- export declare function registerNotificationsCommands(program: Command, globalOpts: () => GlobalOptions): void;
4
- //# sourceMappingURL=notifications.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../src/commands/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAUtD,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,aAAa,GAC9B,IAAI,CAuFN"}