attio 0.0.1-experimental.20250311 → 0.0.1-experimental.20250324

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 (51) hide show
  1. package/lib/api/add-connection-definition.js +2 -2
  2. package/lib/api/auth.js +114 -0
  3. package/lib/api/complete-bundle-upload.js +2 -2
  4. package/lib/api/complete-prod-bundle-upload.js +2 -2
  5. package/lib/api/create-dev-version.js +2 -2
  6. package/lib/api/create-version.js +2 -2
  7. package/lib/api/ensure-authed.js +24 -0
  8. package/lib/api/fetch-connections.js +2 -2
  9. package/lib/api/fetch-installation.js +2 -2
  10. package/lib/api/fetch-versions.js +2 -2
  11. package/lib/api/keychain.js +30 -0
  12. package/lib/api/load-app-id.js +9 -0
  13. package/lib/api/load-dev-slug.js +9 -0
  14. package/lib/api/make-headers.js +1 -1
  15. package/lib/api/remove-connection-definition.js +2 -2
  16. package/lib/api/start-upload.js +2 -2
  17. package/lib/api/whoami.js +21 -0
  18. package/lib/attio.js +6 -2
  19. package/lib/commands/login.js +11 -0
  20. package/lib/commands/logout.js +11 -0
  21. package/lib/commands/version/index.js +1 -3
  22. package/lib/commands/version/list.js +31 -17
  23. package/lib/commands/whoami.js +19 -0
  24. package/lib/graphql/graphql-error.js +3 -0
  25. package/lib/machines/actors.js +3 -1
  26. package/lib/machines/dev-machine.js +5 -2
  27. package/lib/machines/init-machine.js +14 -7
  28. package/lib/templates/javascript/src/cat-fact.jsx +16 -0
  29. package/lib/templates/javascript/src/get-cat-fact.server.js +6 -0
  30. package/lib/templates/javascript/src/hello-world-dialog.jsx +6 -5
  31. package/lib/templates/typescript/src/cat-fact.tsx +16 -0
  32. package/lib/templates/typescript/src/get-cat-fact.server.ts +6 -0
  33. package/lib/templates/typescript/src/hello-world-dialog.tsx +5 -4
  34. package/lib/tsconfig.tsbuildinfo +1 -1
  35. package/lib/util/load-developer-config.js +1 -0
  36. package/package.json +2 -1
  37. package/lib/api/publish-version.js +0 -15
  38. package/lib/commands/connection/add.js +0 -67
  39. package/lib/commands/connection/index.js +0 -9
  40. package/lib/commands/connection/list.js +0 -20
  41. package/lib/commands/connection/remove.js +0 -20
  42. package/lib/commands/version/publish.js +0 -48
  43. package/lib/machines/add-connection-machine.js +0 -559
  44. package/lib/machines/list-connections-machine.js +0 -174
  45. package/lib/machines/list-versions-machine.js +0 -151
  46. package/lib/machines/publish-version-machine.js +0 -230
  47. package/lib/machines/remove-connection-machine.js +0 -253
  48. package/lib/templates/javascript/src/advice.jsx +0 -16
  49. package/lib/templates/javascript/src/get-advice.server.js +0 -6
  50. package/lib/templates/typescript/src/advice.tsx +0 -16
  51. package/lib/templates/typescript/src/get-advice.server.ts +0 -6
@@ -1,559 +0,0 @@
1
- import { assign, setup, fromCallback } from "xstate";
2
- import { addConnectionDefinition } from "../api/add-connection-definition.js";
3
- import { fetchConnections } from "../api/fetch-connections.js";
4
- import { optionsSchema } from "../commands/connection/add.js";
5
- import { ask, askPassword, askWithChoices, loadAppConfig, loadDeveloperConfig } from "./actors.js";
6
- import { printInstallInstructions } from "../util/print-install-instructions.js";
7
- import { printLogo, showError } from "./actions.js";
8
- import Spinner from "tiny-spinner";
9
- import chalk from "chalk";
10
- export const connectionTypes = [
11
- { value: "secret", label: "Secret" },
12
- { value: "oauth2-code", label: "OAuth2" },
13
- ];
14
- export const addConnectionMachine = setup({
15
- types: {
16
- context: {},
17
- events: {},
18
- input: {},
19
- },
20
- actors: {
21
- ask,
22
- askWithChoices,
23
- askPassword,
24
- createConnectionDefinition: fromCallback(({ sendBack, input: { developer: { token, slug: devSlug }, config, connectionType: connection_type, label, description, global, authorizeUrl, accessTokenUrl, clientId, clientSecret, scopes, }, }) => {
25
- const spinner = new Spinner();
26
- const add = async () => {
27
- spinner.start("Creating connection definition...");
28
- try {
29
- await addConnectionDefinition({
30
- token,
31
- devSlug,
32
- appId: config.id,
33
- major: config.major,
34
- connectionType: connection_type,
35
- label,
36
- description,
37
- global,
38
- accessTokenUrl,
39
- authorizeUrl,
40
- clientId,
41
- clientSecret,
42
- scopes,
43
- });
44
- spinner.success("Connection definition created");
45
- sendBack({ type: "Success" });
46
- }
47
- catch (error) {
48
- spinner.error(`Failed to create connection definition: ${chalk.red(error.message)}`);
49
- sendBack({ type: "Error", error: error.message });
50
- }
51
- };
52
- add();
53
- }),
54
- loadDeveloperConfig,
55
- loadAppConfig,
56
- validateGlobal: fromCallback(({ sendBack, input: { developer, config, global } }) => {
57
- const spinner = new Spinner();
58
- spinner.start("Checking if global connection already exists..." + global);
59
- fetchConnections({
60
- token: developer.token,
61
- devSlug: developer.slug,
62
- appId: config.id,
63
- major: config.major,
64
- })
65
- .then((connections) => {
66
- const weHaveGlobal = connections.some((connection) => connection.global);
67
- const weHaveUser = connections.some((connection) => !connection.global);
68
- if (weHaveGlobal && weHaveUser) {
69
- spinner.stop();
70
- sendBack({
71
- type: "Error",
72
- error: "Both global and user connections already exist",
73
- });
74
- }
75
- else if (weHaveGlobal && global) {
76
- spinner.error("Global connection already exists");
77
- sendBack({ type: "Global Taken" });
78
- }
79
- else if (weHaveUser && !global) {
80
- spinner.error("A user connection already exists");
81
- sendBack({ type: "Global Taken" });
82
- }
83
- else {
84
- spinner.success("All good.");
85
- sendBack({ type: "Valid Global" });
86
- }
87
- })
88
- .catch((error) => {
89
- spinner.stop();
90
- sendBack({ type: "Error", error: error.message });
91
- });
92
- }),
93
- },
94
- actions: {
95
- printLogo,
96
- showError,
97
- showConfigInstructions: ({ context }) => printInstallInstructions(context.configError),
98
- clearError: assign({
99
- error: () => undefined,
100
- }),
101
- setError: assign({
102
- error: (_, params) => params.error,
103
- }),
104
- setConnectionType: assign({
105
- connectionType: (_, params) => params.output,
106
- }),
107
- setAuthorizeUrl: assign({
108
- authorizeUrl: (_, params) => params.output,
109
- }),
110
- setAccessTokenUrl: assign({
111
- accessTokenUrl: (_, params) => params.output,
112
- }),
113
- setScopes: assign({
114
- scopes: (_, params) => params.output,
115
- }),
116
- setClientId: assign({
117
- clientId: (_, params) => params.output,
118
- }),
119
- setClientSecret: assign({
120
- clientSecret: (_, params) => params.output,
121
- }),
122
- setDeveloperConfig: assign({
123
- developer: (_, params) => params,
124
- }),
125
- setInvalidAuthorizeUrl: assign({
126
- error: (_, params) => {
127
- const result = optionsSchema.shape.authorizeUrl
128
- .unwrap()
129
- .safeParse(params.authorizeUrl?.trim());
130
- return result.success ? undefined : result.error.errors[0].message;
131
- },
132
- }),
133
- setInvalidAccessTokenUrl: assign({
134
- error: (_, params) => {
135
- const result = optionsSchema.shape.accessTokenUrl
136
- .unwrap()
137
- .safeParse(params.accessTokenUrl?.trim());
138
- return result.success ? undefined : result.error.errors[0].message;
139
- },
140
- }),
141
- setInvalidScopes: assign({
142
- error: (_, params) => {
143
- const result = optionsSchema.shape.scopes.unwrap().safeParse(params.scopes?.trim());
144
- return result.success ? undefined : result.error.errors[0].message;
145
- },
146
- }),
147
- setInvalidClientId: assign({
148
- error: (_, params) => {
149
- const result = optionsSchema.shape.clientId
150
- .unwrap()
151
- .safeParse(params.clientId?.trim());
152
- return result.success ? undefined : result.error.errors[0].message;
153
- },
154
- }),
155
- setInvalidClientSecret: assign({
156
- error: (_, params) => {
157
- const result = optionsSchema.shape.clientSecret
158
- .unwrap()
159
- .safeParse(params.clientSecret?.trim());
160
- return result.success ? undefined : result.error.errors[0].message;
161
- },
162
- }),
163
- setConfigError: assign({
164
- configError: (_, params) => params.configError,
165
- }),
166
- setLabel: assign({
167
- label: (_, params) => params.output,
168
- }),
169
- setDescription: assign({
170
- description: (_, params) => params.output,
171
- }),
172
- setGlobal: assign({
173
- global: (_, params) => params.output === "true",
174
- }),
175
- setAppConfig: assign({
176
- config: (_, params) => params.config,
177
- }),
178
- setGlobalTaken: assign({
179
- error: () => "Global taken",
180
- }),
181
- },
182
- guards: {
183
- "have connection type": (_, params) => Boolean(params.connectionType),
184
- "have label": (_, params) => Boolean(params.label),
185
- "have description": (_, params) => Boolean(params.description),
186
- "have authorize url": (_, params) => params.connectionType === "secret" ||
187
- optionsSchema.shape.authorizeUrl.unwrap().safeParse(params.authorizeUrl?.trim())
188
- .success,
189
- "have access token url": (_, params) => params.connectionType === "secret" ||
190
- optionsSchema.shape.accessTokenUrl.unwrap().safeParse(params.accessTokenUrl?.trim())
191
- .success,
192
- "have scopes": (_, params) => params.connectionType === "secret" ||
193
- optionsSchema.shape.scopes.unwrap().safeParse(params.scopes?.trim()).success,
194
- "have client id": (_, params) => params.connectionType === "secret" ||
195
- optionsSchema.shape.clientId.unwrap().safeParse(params.clientId?.trim()).success,
196
- "have global": (_, params) => params.global !== undefined,
197
- "have client secret": (_, params) => params.connectionType === "secret" ||
198
- optionsSchema.shape.clientSecret.unwrap().safeParse(params.clientSecret?.trim())
199
- .success,
200
- "is oauth": (_, params) => params.connectionType === "oauth2-code",
201
- },
202
- }).createMachine({
203
- context: ({ input }) => ({
204
- developer: { slug: "", token: "" },
205
- ...input,
206
- }),
207
- id: "Add Connection Machine",
208
- states: {
209
- "Loading Developer Config": {
210
- invoke: {
211
- src: "loadDeveloperConfig",
212
- },
213
- on: {
214
- "Developer Config Loaded": {
215
- target: "Loading App Config",
216
- actions: { type: "setDeveloperConfig", params: ({ event }) => event },
217
- },
218
- "No Developer Config": {
219
- target: "Show config instructions",
220
- actions: { type: "setConfigError", params: ({ event }) => event },
221
- },
222
- },
223
- },
224
- "Show config instructions": {
225
- type: "final",
226
- entry: "showConfigInstructions",
227
- },
228
- "Loading App Config": {
229
- invoke: {
230
- src: "loadAppConfig",
231
- },
232
- on: {
233
- "Error": {
234
- target: "Error",
235
- actions: { type: "setError", params: ({ event }) => event },
236
- },
237
- "App Config Loaded": {
238
- target: "Do we have a connection type?",
239
- actions: { type: "setAppConfig", params: ({ event }) => event },
240
- reenter: true,
241
- },
242
- },
243
- },
244
- "Error": {
245
- type: "final",
246
- entry: { type: "showError", params: ({ context }) => ({ error: context.error }) },
247
- },
248
- "Creating connection definition": {
249
- invoke: {
250
- src: "createConnectionDefinition",
251
- input: ({ context }) => ({
252
- developer: context.developer,
253
- config: context.config,
254
- connectionType: context.connectionType,
255
- authorizeUrl: context.authorizeUrl,
256
- accessTokenUrl: context.accessTokenUrl,
257
- scopes: context.scopes,
258
- clientId: context.clientId,
259
- clientSecret: context.clientSecret,
260
- global: context.global,
261
- label: context.label,
262
- description: context.description,
263
- }),
264
- },
265
- on: {
266
- Error: {
267
- target: "Error",
268
- actions: { type: "setError", params: ({ event }) => event },
269
- },
270
- Success: "Success",
271
- },
272
- },
273
- "Success": {
274
- type: "final",
275
- },
276
- "Ask for Authorize URL": {
277
- invoke: {
278
- src: "ask",
279
- input: {
280
- message: "e.g. https://authorization-server.com/oauth/authorize\nOAuth Authorize URL:",
281
- required: true,
282
- validate: (value) => {
283
- const result = optionsSchema.shape.authorizeUrl
284
- .unwrap()
285
- .safeParse(value.trim());
286
- return result.success ? true : result.error.errors[0].message;
287
- },
288
- },
289
- onDone: {
290
- target: "Do we have an access token url?",
291
- actions: { type: "setAuthorizeUrl", params: ({ event }) => event },
292
- },
293
- },
294
- },
295
- "Ask for Access Token URL": {
296
- invoke: {
297
- src: "ask",
298
- input: {
299
- message: "e.g. https://authorization-server.com/oauth/token\nOAuth Access Token URL:",
300
- required: true,
301
- validate: (value) => {
302
- const result = optionsSchema.shape.accessTokenUrl
303
- .unwrap()
304
- .safeParse(value.trim());
305
- return result.success ? true : result.error.errors[0].message;
306
- },
307
- },
308
- onDone: {
309
- target: "Do we have scopes?",
310
- actions: { type: "setAccessTokenUrl", params: ({ event }) => event },
311
- },
312
- },
313
- },
314
- "Ask for Scopes": {
315
- invoke: {
316
- src: "ask",
317
- input: {
318
- message: "e.g. read:user,read:org\nOAuth Scopes:",
319
- required: true,
320
- validate: (value) => {
321
- const result = optionsSchema.shape.scopes.unwrap().safeParse(value.trim());
322
- return result.success ? true : result.error.errors[0].message;
323
- },
324
- },
325
- onDone: {
326
- target: "Do we have a client id?",
327
- actions: { type: "setScopes", params: ({ event }) => event },
328
- },
329
- },
330
- },
331
- "Ask for Client ID": {
332
- invoke: {
333
- src: "ask",
334
- input: {
335
- message: "OAuth Client ID:",
336
- required: true,
337
- },
338
- onDone: {
339
- target: "Do we have a client secret?",
340
- actions: { type: "setClientId", params: ({ event }) => event },
341
- },
342
- },
343
- },
344
- "Ask for Client Secret": {
345
- invoke: {
346
- src: "askPassword",
347
- input: {
348
- message: "OAuth Client Secret:",
349
- required: true,
350
- },
351
- onDone: {
352
- target: "Creating connection definition",
353
- actions: { type: "setClientSecret", params: ({ event }) => event },
354
- },
355
- },
356
- },
357
- "Do we have an authorize url?": {
358
- always: [
359
- {
360
- target: "Do we have an access token url?",
361
- guard: { type: "have authorize url", params: ({ context }) => context },
362
- },
363
- {
364
- target: "Ask for Authorize URL",
365
- },
366
- ],
367
- },
368
- "Do we have an access token url?": {
369
- always: [
370
- {
371
- target: "Do we have scopes?",
372
- guard: { type: "have access token url", params: ({ context }) => context },
373
- },
374
- {
375
- target: "Ask for Access Token URL",
376
- },
377
- ],
378
- },
379
- "Do we have scopes?": {
380
- always: [
381
- {
382
- target: "Do we have a client id?",
383
- guard: { type: "have scopes", params: ({ context }) => context },
384
- },
385
- {
386
- target: "Ask for Scopes",
387
- },
388
- ],
389
- },
390
- "Do we have a client id?": {
391
- always: [
392
- {
393
- target: "Do we have a client secret?",
394
- guard: { type: "have client id", params: ({ context }) => context },
395
- },
396
- {
397
- target: "Ask for Client ID",
398
- },
399
- ],
400
- },
401
- "Do we have a client secret?": {
402
- always: [
403
- {
404
- target: "Creating connection definition",
405
- guard: { type: "have client secret", params: ({ context }) => context },
406
- },
407
- {
408
- target: "Ask for Client Secret",
409
- },
410
- ],
411
- },
412
- "Do we have a connection type?": {
413
- always: [
414
- {
415
- target: "Do we have a label?",
416
- guard: { type: "have connection type", params: ({ context }) => context },
417
- reenter: true,
418
- },
419
- "Ask for connection type",
420
- ],
421
- },
422
- "Ask for connection type": {
423
- invoke: {
424
- src: "askWithChoices",
425
- input: {
426
- message: "What type of connection would you like to add?",
427
- choices: [
428
- { name: "OAuth2 Code", value: "oauth2-code" },
429
- { name: "Secret", value: "secret" },
430
- ],
431
- },
432
- onDone: {
433
- target: "Do we have a label?",
434
- actions: { type: "setConnectionType", params: ({ event }) => event },
435
- },
436
- },
437
- },
438
- "Split on connection type": {
439
- always: [
440
- {
441
- target: "Do we have an authorize url?",
442
- guard: { type: "is oauth", params: ({ context }) => context },
443
- },
444
- {
445
- target: "Creating connection definition",
446
- },
447
- ],
448
- },
449
- "Do we have a label?": {
450
- always: [
451
- {
452
- target: "Do we have a description?",
453
- guard: { type: "have label", params: ({ context }) => context },
454
- reenter: true,
455
- },
456
- {
457
- target: "Ask for label",
458
- },
459
- ],
460
- },
461
- "Do we have a description?": {
462
- always: [
463
- {
464
- target: "Do we have global?",
465
- guard: { type: "have description", params: ({ context }) => context },
466
- },
467
- {
468
- target: "Ask for description",
469
- },
470
- ],
471
- },
472
- "Do we have global?": {
473
- always: [
474
- {
475
- target: "Validating Global",
476
- guard: { type: "have global", params: ({ context }) => context },
477
- reenter: true,
478
- },
479
- {
480
- target: "Ask for global",
481
- },
482
- ],
483
- },
484
- "Ask for label": {
485
- invoke: {
486
- src: "ask",
487
- input: ({ context }) => ({
488
- message: "What would you like to call this connection?",
489
- required: true,
490
- default: context.connectionType === "oauth2-code"
491
- ? "Connection"
492
- : context.connectionType === "secret"
493
- ? "Access Token"
494
- : "",
495
- }),
496
- onDone: {
497
- target: "Do we have a description?",
498
- actions: { type: "setLabel", params: ({ event }) => event },
499
- },
500
- },
501
- },
502
- "Ask for description": {
503
- invoke: {
504
- src: "ask",
505
- input: {
506
- message: "Description: (will be displayed in the UI)",
507
- required: true,
508
- },
509
- onDone: {
510
- target: "Do we have global?",
511
- actions: { type: "setDescription", params: ({ event }) => event },
512
- },
513
- },
514
- },
515
- "Ask for global": {
516
- invoke: {
517
- src: "askWithChoices",
518
- input: ({ context }) => ({
519
- message: `A ${context.connectionType === "secret" ? "secret" : "token"} will be created for:`,
520
- choices: [
521
- { name: "The entire workspace", value: "true" },
522
- { name: "An individual user", value: "false" },
523
- ],
524
- }),
525
- onDone: {
526
- target: "Validating Global",
527
- actions: { type: "setGlobal", params: ({ event }) => event },
528
- },
529
- },
530
- },
531
- "Validating Global": {
532
- on: {
533
- "Global Taken": {
534
- target: "Ask for global",
535
- actions: "setGlobalTaken",
536
- },
537
- "Valid Global": {
538
- target: "Split on connection type",
539
- reenter: true,
540
- },
541
- "Error": {
542
- target: "Error",
543
- reenter: true,
544
- actions: { type: "setError", params: ({ event }) => event },
545
- },
546
- },
547
- invoke: {
548
- src: "validateGlobal",
549
- input: ({ context }) => ({
550
- global: context.global,
551
- developer: context.developer,
552
- config: context.config,
553
- }),
554
- },
555
- },
556
- },
557
- initial: "Loading Developer Config",
558
- entry: "printLogo",
559
- });