attio 0.0.1-experimental.20240925 → 0.0.1-experimental.20240926.1

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.
@@ -1,16 +1,14 @@
1
1
  import { assign, setup, fromCallback } from "xstate";
2
2
  import { addConnectionDefinition } from "../api/add-connection-definition.js";
3
+ import { fetchConnections } from "../api/fetch-connections.js";
3
4
  import { options } from "../commands/connection/add.js";
4
5
  import { updateAppConfig } from "../util/app-config.js";
6
+ import { slugifyExtension } from "../util/slugify-extension.js";
5
7
  import { loadAppConfig, loadDeveloperConfig } from "./actors.js";
6
8
  export const connectionTypes = [
7
9
  { value: "secret", label: "Secret" },
8
10
  { value: "oauth2-code", label: "OAuth2" },
9
11
  ];
10
- export const audiences = [
11
- { value: "workspace", label: "Workspace" },
12
- { value: "workspace-member", label: "Workspace Member" },
13
- ];
14
12
  export const addConnectionMachine = setup({
15
13
  types: {
16
14
  context: {},
@@ -18,14 +16,20 @@ export const addConnectionMachine = setup({
18
16
  input: {},
19
17
  },
20
18
  actors: {
21
- createConnectionDefinition: fromCallback(({ sendBack, input: { developer: { token, slug: devSlug }, appId, connectionType: connection_type, audience, authorizeUrl, accessTokenUrl, clientId, clientSecret, scopes, }, }) => {
19
+ createConnectionDefinition: fromCallback(({ sendBack, input: { developer: { token, slug: devSlug }, config, connectionType: connection_type, slug, label, description, allowMultiple, global, authorizeUrl, accessTokenUrl, clientId, clientSecret, scopes, }, }) => {
22
20
  const add = async () => {
23
21
  try {
24
22
  await addConnectionDefinition({
25
23
  token,
26
24
  devSlug,
27
- appId,
28
- connection: { connection_type, audience },
25
+ appId: config.id,
26
+ major: config.major,
27
+ connectionType: connection_type,
28
+ slug,
29
+ label,
30
+ description,
31
+ allowMultiple,
32
+ global,
29
33
  accessTokenUrl,
30
34
  authorizeUrl,
31
35
  clientId,
@@ -34,7 +38,7 @@ export const addConnectionMachine = setup({
34
38
  });
35
39
  updateAppConfig((config) => ({
36
40
  ...config,
37
- connection: { connection_type, audience },
41
+ connectionType: connection_type,
38
42
  }));
39
43
  sendBack({ type: "Success" });
40
44
  }
@@ -46,6 +50,21 @@ export const addConnectionMachine = setup({
46
50
  }),
47
51
  loadDeveloperConfig,
48
52
  loadAppConfig,
53
+ validateSlug: fromCallback(({ sendBack, input: { slug, developer, config } }) => {
54
+ fetchConnections({
55
+ token: developer.token,
56
+ devSlug: developer.slug,
57
+ appId: config.id,
58
+ major: config.major,
59
+ }).then((connections) => {
60
+ if (connections[slug]) {
61
+ sendBack({ type: "Slug Taken" });
62
+ }
63
+ else {
64
+ sendBack({ type: "Valid Slug" });
65
+ }
66
+ });
67
+ }),
49
68
  },
50
69
  actions: {
51
70
  clearError: assign({
@@ -54,9 +73,6 @@ export const addConnectionMachine = setup({
54
73
  setError: assign({
55
74
  error: (_, params) => params.error,
56
75
  }),
57
- setAudience: assign({
58
- audience: (_, params) => params.audience,
59
- }),
60
76
  setConnectionType: assign({
61
77
  connectionType: (_, params) => params.connectionType,
62
78
  }),
@@ -78,6 +94,9 @@ export const addConnectionMachine = setup({
78
94
  setDeveloperConfig: assign({
79
95
  developer: (_, params) => params,
80
96
  }),
97
+ setSlug: assign({
98
+ slug: (_, params) => slugifyExtension(params.slug, false),
99
+ }),
81
100
  setInvalidAuthorizeUrl: assign({
82
101
  error: (_, params) => {
83
102
  const result = options.shape.authorizeUrl
@@ -117,15 +136,30 @@ export const addConnectionMachine = setup({
117
136
  setConfigError: assign({
118
137
  configError: (_, params) => params.configError,
119
138
  }),
139
+ setLabel: assign({
140
+ label: (_, params) => params.label,
141
+ }),
142
+ setDescription: assign({
143
+ description: (_, params) => params.description,
144
+ }),
145
+ setGlobal: assign({
146
+ global: (_, params) => params.global,
147
+ }),
148
+ setAllowMultiple: assign({
149
+ allowMultiple: (_, params) => params.allowMultiple,
150
+ }),
120
151
  setAppConfig: assign({
121
- appId: (_, params) => params.config.id,
122
- haveConnection: (_, params) => Boolean(params.config.connection),
152
+ config: (_, params) => params.config,
153
+ }),
154
+ setSlugTaken: assign({
155
+ error: () => "Slug taken",
123
156
  }),
124
157
  },
125
158
  guards: {
126
- "already have a connection": (_, params) => params.haveConnection,
127
- "have audience": (_, params) => Boolean(params.audience),
128
159
  "have connection type": (_, params) => Boolean(params.connectionType),
160
+ "have slug": (_, params) => Boolean(params.slug),
161
+ "have label": (_, params) => Boolean(params.label),
162
+ "have description": (_, params) => Boolean(params.description),
129
163
  "have authorize url": (_, params) => params.connectionType === "secret" ||
130
164
  options.shape.authorizeUrl.unwrap().safeParse(params.authorizeUrl?.trim()).success,
131
165
  "have access token url": (_, params) => params.connectionType === "secret" ||
@@ -134,14 +168,15 @@ export const addConnectionMachine = setup({
134
168
  options.shape.scopes.unwrap().safeParse(params.scopes?.trim()).success,
135
169
  "have client id": (_, params) => params.connectionType === "secret" ||
136
170
  options.shape.clientId.unwrap().safeParse(params.clientId?.trim()).success,
171
+ "have global": (_, params) => params.global !== undefined,
172
+ "have allow multiple": (_, params) => params.allowMultiple !== undefined,
137
173
  "have client secret": (_, params) => params.connectionType === "secret" ||
138
174
  options.shape.clientSecret.unwrap().safeParse(params.clientSecret?.trim()).success,
175
+ "is oauth": (_, params) => params.connectionType === "oauth2-code",
139
176
  },
140
177
  }).createMachine({
141
178
  context: ({ input }) => ({
142
179
  developer: { slug: "", token: "" },
143
- appId: "",
144
- haveConnection: false,
145
180
  ...input,
146
181
  }),
147
182
  id: "Add Connection Machine",
@@ -173,71 +208,47 @@ export const addConnectionMachine = setup({
173
208
  target: "Error",
174
209
  actions: { type: "setError", params: ({ event }) => event },
175
210
  },
176
- "App Config Loaded": {
177
- target: "Do we already have a connection?",
178
- actions: { type: "setAppConfig", params: ({ event }) => event },
179
- },
211
+ "App Config Loaded": [
212
+ {
213
+ target: "Do we have a slug?",
214
+ actions: { type: "setAppConfig", params: ({ event }) => event },
215
+ },
216
+ ],
180
217
  },
181
218
  },
182
219
  "Error": {
183
220
  type: "final",
184
221
  },
185
- "Ask for connection type": {
186
- on: {
187
- "Choose Connection Type": {
188
- target: "Do we have an audience?",
189
- actions: { type: "setConnectionType", params: ({ event }) => event },
190
- },
191
- },
192
- },
193
- "Ask for audience": {
194
- on: {
195
- "Choose Audience": {
196
- target: "Do we have an authorize url?",
197
- actions: { type: "setAudience", params: ({ event }) => event },
198
- },
199
- },
200
- },
201
222
  "Creating connection definition": {
202
223
  invoke: {
203
224
  src: "createConnectionDefinition",
204
225
  input: ({ context }) => ({
205
226
  developer: context.developer,
206
- appId: context.appId,
227
+ config: context.config,
207
228
  connectionType: context.connectionType,
208
- audience: context.audience,
209
229
  authorizeUrl: context.authorizeUrl,
210
230
  accessTokenUrl: context.accessTokenUrl,
211
231
  scopes: context.scopes,
212
232
  clientId: context.clientId,
213
233
  clientSecret: context.clientSecret,
234
+ global: context.global,
235
+ allowMultiple: context.allowMultiple,
236
+ label: context.label,
237
+ description: context.description,
238
+ slug: context.slug,
214
239
  }),
215
240
  },
216
241
  on: {
217
- Success: "Success",
218
242
  Error: {
219
243
  target: "Error",
220
244
  actions: { type: "setError", params: ({ event }) => event },
221
245
  },
246
+ Success: "Success",
222
247
  },
223
248
  },
224
249
  "Success": {
225
250
  type: "final",
226
251
  },
227
- "Do we already have a connection?": {
228
- always: [
229
- {
230
- target: "Already have a connection",
231
- guard: { type: "already have a connection", params: ({ context }) => context },
232
- },
233
- {
234
- target: "Do we have a connection type?",
235
- },
236
- ],
237
- },
238
- "Already have a connection": {
239
- type: "final",
240
- },
241
252
  "Ask for Authorize URL": {
242
253
  on: {
243
254
  "Update Authorize URL": {
@@ -316,35 +327,9 @@ export const addConnectionMachine = setup({
316
327
  target: "Creating connection definition",
317
328
  guard: { type: "have client secret", params: ({ context }) => context },
318
329
  },
319
- {
320
- target: "Ask for Client Secret",
321
- actions: { type: "setInvalidClientSecret", params: ({ context }) => context },
322
- },
323
330
  ],
324
331
  },
325
332
  },
326
- "Do we have a connection type?": {
327
- always: [
328
- {
329
- target: "Do we have an audience?",
330
- guard: { type: "have connection type", params: ({ context }) => context },
331
- },
332
- {
333
- target: "Ask for connection type",
334
- },
335
- ],
336
- },
337
- "Do we have an audience?": {
338
- always: [
339
- {
340
- target: "Do we have an authorize url?",
341
- guard: { type: "have audience", params: ({ context }) => context },
342
- },
343
- {
344
- target: "Ask for audience",
345
- },
346
- ],
347
- },
348
333
  "Do we have an authorize url?": {
349
334
  always: [
350
335
  {
@@ -400,6 +385,154 @@ export const addConnectionMachine = setup({
400
385
  },
401
386
  ],
402
387
  },
388
+ "Do we have a slug?": {
389
+ always: [
390
+ {
391
+ target: "Validating Slug",
392
+ guard: { type: "have slug", params: ({ context }) => context },
393
+ },
394
+ {
395
+ target: "Ask for slug",
396
+ },
397
+ ],
398
+ },
399
+ "Validating Slug": {
400
+ on: {
401
+ "Slug Taken": {
402
+ target: "Ask for slug",
403
+ actions: "setSlugTaken",
404
+ },
405
+ "Valid Slug": {
406
+ target: "Do we have a label?",
407
+ },
408
+ },
409
+ invoke: {
410
+ src: "validateSlug",
411
+ input: ({ context }) => ({
412
+ slug: context.slug,
413
+ developer: context.developer,
414
+ config: context.config,
415
+ }),
416
+ },
417
+ },
418
+ "Ask for slug": {
419
+ on: {
420
+ "Update Slug": {
421
+ actions: { type: "setSlug", params: ({ event }) => event },
422
+ },
423
+ "Submit": "Validating Slug",
424
+ },
425
+ },
426
+ "Do we have a connection type?": {
427
+ always: [
428
+ {
429
+ target: "Split on connection type",
430
+ guard: { type: "have connection type", params: ({ context }) => context },
431
+ },
432
+ "Ask for connection type",
433
+ ],
434
+ },
435
+ "Ask for connection type": {
436
+ on: {
437
+ "Choose Connection Type": {
438
+ target: "Split on connection type",
439
+ actions: { type: "setConnectionType", params: ({ event }) => event },
440
+ },
441
+ },
442
+ },
443
+ "Split on connection type": {
444
+ always: [
445
+ {
446
+ target: "Do we have an authorize url?",
447
+ guard: { type: "is oauth", params: ({ context }) => context },
448
+ },
449
+ {
450
+ target: "Creating connection definition",
451
+ },
452
+ ],
453
+ },
454
+ "Do we have a label?": {
455
+ always: [
456
+ {
457
+ target: "Do we have a description?",
458
+ guard: { type: "have label", params: ({ context }) => context },
459
+ },
460
+ {
461
+ target: "Ask for label",
462
+ },
463
+ ],
464
+ },
465
+ "Do we have a description?": {
466
+ always: [
467
+ {
468
+ target: "Do we have global?",
469
+ guard: { type: "have description", params: ({ context }) => context },
470
+ },
471
+ {
472
+ target: "Ask for description",
473
+ },
474
+ ],
475
+ },
476
+ "Do we have global?": {
477
+ always: [
478
+ {
479
+ target: "Do we have allow multiple?",
480
+ guard: { type: "have global", params: ({ context }) => context },
481
+ },
482
+ {
483
+ target: "Ask for global",
484
+ },
485
+ ],
486
+ },
487
+ "Do we have allow multiple?": {
488
+ always: [
489
+ {
490
+ target: "Do we have a connection type?",
491
+ guard: { type: "have allow multiple", params: ({ context }) => context },
492
+ },
493
+ {
494
+ target: "Ask for allow multiple",
495
+ },
496
+ ],
497
+ },
498
+ "Ask for label": {
499
+ on: {
500
+ "Submit": {
501
+ target: "Do we have a description?",
502
+ guard: { type: "have label", params: ({ context }) => context },
503
+ },
504
+ "Update Label": {
505
+ actions: { type: "setLabel", params: ({ event }) => event },
506
+ },
507
+ },
508
+ },
509
+ "Ask for description": {
510
+ on: {
511
+ "Update Description": {
512
+ actions: { type: "setDescription", params: ({ event }) => event },
513
+ },
514
+ "Submit": {
515
+ target: "Do we have global?",
516
+ guard: { type: "have description", params: ({ context }) => context },
517
+ },
518
+ },
519
+ },
520
+ "Ask for global": {
521
+ on: {
522
+ "Choose Global": {
523
+ target: "Do we have allow multiple?",
524
+ actions: { type: "setGlobal", params: ({ event }) => event },
525
+ },
526
+ },
527
+ },
528
+ "Ask for allow multiple": {
529
+ on: {
530
+ "Choose Allow Multiple": {
531
+ target: "Do we have a connection type?",
532
+ actions: { type: "setAllowMultiple", params: ({ event }) => event },
533
+ },
534
+ },
535
+ },
403
536
  },
404
537
  initial: "Loading Developer Config",
405
538
  });
@@ -1,7 +1,10 @@
1
1
  import chokidar from "chokidar";
2
+ import open from "open";
3
+ import readline from "readline";
2
4
  import { assign, fromCallback, setup, enqueueActions } from "xstate";
3
5
  import { completeBundleUpload } from "../api/complete-bundle-upload.js";
4
6
  import { createDevVersion } from "../api/create-dev-version.js";
7
+ import { startGraphqlServer } from "../api/start-graphql-server.js";
5
8
  import { startUpload } from "../api/start-upload.js";
6
9
  import { loadAppConfigFile } from "../util/app-config.js";
7
10
  import { loadDeveloperConfig, loadInitialDeveloperConfig, } from "../util/load-developer-config.js";
@@ -30,6 +33,24 @@ export const devMachine = setup({
30
33
  }
31
34
  sendBack({ type: "Initialized", config });
32
35
  }),
36
+ listenForGraphqlOpen: fromCallback(({ input }) => {
37
+ readline.emitKeypressEvents(process.stdin);
38
+ if (process.stdin.isTTY) {
39
+ process.stdin.setRawMode(true);
40
+ }
41
+ const handleKeyPress = (str, key) => {
42
+ if (key.name?.toLowerCase() === "o") {
43
+ open(`http://localhost:${input.graphqlPort}/graphql`);
44
+ }
45
+ };
46
+ process.stdin.on("keypress", handleKeyPress);
47
+ return () => {
48
+ process.stdin.removeListener("keypress", handleKeyPress);
49
+ if (process.stdin.isTTY) {
50
+ process.stdin.setRawMode(false);
51
+ }
52
+ };
53
+ }),
33
54
  prepareUpload: fromCallback(({ sendBack }) => {
34
55
  const prepareUpload = async () => {
35
56
  const config = await loadDeveloperConfig();
@@ -108,6 +129,7 @@ export const devMachine = setup({
108
129
  watcher.close();
109
130
  };
110
131
  }),
132
+ graphql: fromCallback(({ sendBack }) => startGraphqlServer(sendBack)),
111
133
  },
112
134
  actions: {
113
135
  clearUploadError: assign({ uploadError: undefined }),
@@ -125,6 +147,9 @@ export const devMachine = setup({
125
147
  setDevVersion: assign({
126
148
  devVersion: (_, params) => params.devVersion,
127
149
  }),
150
+ setGraphqlPort: assign({
151
+ graphqlPort: (_, params) => params.port,
152
+ }),
128
153
  setSuccess: assign({
129
154
  jsContents: (_, params) => params.contents,
130
155
  lastSuccessfulJavaScriptBuild: (_, params) => params.time,
@@ -252,6 +277,31 @@ export const devMachine = setup({
252
277
  },
253
278
  initial: "Validating",
254
279
  },
280
+ Graphql: {
281
+ invoke: {
282
+ src: "graphql",
283
+ },
284
+ states: {
285
+ "Not Started": {
286
+ on: {
287
+ "GraphQL Server Started": {
288
+ target: "Started",
289
+ actions: {
290
+ type: "setGraphqlPort",
291
+ params: ({ event }) => event,
292
+ },
293
+ },
294
+ },
295
+ },
296
+ "Started": {
297
+ invoke: {
298
+ src: "listenForGraphqlOpen",
299
+ input: ({ context }) => ({ graphqlPort: context.graphqlPort }),
300
+ },
301
+ },
302
+ },
303
+ initial: "Not Started",
304
+ },
255
305
  },
256
306
  type: "parallel",
257
307
  },