attio 0.0.1-experimental.20241011.3 → 0.0.1-experimental.20241011.5

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.
@@ -7,11 +7,10 @@ const addConnectionSchema = z.object({
7
7
  app_id: z.string(),
8
8
  connection_definition_id: z.string(),
9
9
  });
10
- export async function addConnectionDefinition({ token, devSlug, appId, key, label, description, global, connectionType, clientId, clientSecret, authorizeUrl, accessTokenUrl, major, scopes, }) {
10
+ export async function addConnectionDefinition({ token, devSlug, appId, label, description, global, connectionType, clientId, clientSecret, authorizeUrl, accessTokenUrl, major, scopes, }) {
11
11
  const connectionDefinitionId = uuid();
12
12
  const body = {
13
13
  connection_type: connectionType,
14
- slug: key,
15
14
  label,
16
15
  description,
17
16
  global,
@@ -3,7 +3,7 @@ import { API } from "../env.js";
3
3
  import { handleError } from "./handle-error.js";
4
4
  import { makeHeaders } from "./make-headers.js";
5
5
  const connectionDefinitionsResponseSchema = z.object({
6
- connection_definitions: z.record(z.string(), z.object({
6
+ values: z.array(z.object({
7
7
  label: z.string(),
8
8
  connection_type: z.enum(["oauth2-code", "secret"]),
9
9
  description: z.string().nullable(),
@@ -16,5 +16,5 @@ export async function fetchConnections({ token, devSlug, appId, major, }) {
16
16
  headers: makeHeaders(token),
17
17
  });
18
18
  await handleError(response);
19
- return connectionDefinitionsResponseSchema.parse(await response.json()).connection_definitions;
19
+ return connectionDefinitionsResponseSchema.parse(await response.json()).values;
20
20
  }
@@ -1,8 +1,8 @@
1
1
  import { API } from "../env.js";
2
2
  import { handleError } from "./handle-error.js";
3
3
  import { makeHeaders } from "./make-headers.js";
4
- export async function removeConnectionDefinition({ token, devSlug, appId, slug, major, }) {
5
- const response = await fetch(`${API}/developer-portal/accounts/${devSlug}/apps/${appId}/versions/${major}/connection-definitions/${slug}`, {
4
+ export async function removeConnectionDefinition({ token, devSlug, appId, global, major, }) {
5
+ const response = await fetch(`${API}/developer-portal/accounts/${devSlug}/apps/${appId}/versions/${major}/connection-definitions/${global ? "workspace" : "user"}/remove`, {
6
6
  method: "DELETE",
7
7
  headers: makeHeaders(token),
8
8
  });
@@ -11,10 +11,6 @@ import { Select } from "../../components/Select.js";
11
11
  import { addConnectionMachine, connectionTypes } from "../../machines/add-connection-machine.js";
12
12
  export const description = "Create a new connection for your Attio app";
13
13
  export const options = z.object({
14
- key: z
15
- .string()
16
- .optional()
17
- .describe(option({ description: "A unique key for your connection" })),
18
14
  label: z
19
15
  .string()
20
16
  .optional()
@@ -61,10 +57,9 @@ export const options = z.object({
61
57
  .default(false)
62
58
  .describe(option({ description: "Run in development mode (additional debugging info)" })),
63
59
  });
64
- export default function AddConnection({ options: { key, label, description, type: connectionType, authorizeUrl, accessTokenUrl, scopes, clientId, clientSecret, dev, }, }) {
60
+ export default function AddConnection({ options: { label, description, type: connectionType, authorizeUrl, accessTokenUrl, scopes, clientId, clientSecret, dev, }, }) {
65
61
  const [snapshot, send] = useMachine(addConnectionMachine, {
66
62
  input: {
67
- key,
68
63
  label,
69
64
  description,
70
65
  connectionType,
@@ -90,9 +85,6 @@ export default function AddConnection({ options: { key, label, description, type
90
85
  snapshot.context.label && !snapshot.matches("Ask for label") && (React.createElement(Box, null,
91
86
  React.createElement(Text, null, "Label: "),
92
87
  React.createElement(Text, { color: "green" }, snapshot.context.label))),
93
- snapshot.context.key && !snapshot.matches("Ask for key") && (React.createElement(Box, null,
94
- React.createElement(Text, null, "Connection Key: "),
95
- React.createElement(Text, { color: "green" }, snapshot.context.key))),
96
88
  snapshot.context.description && !snapshot.matches("Ask for description") && (React.createElement(Box, null,
97
89
  React.createElement(Text, null, "Description: "),
98
90
  React.createElement(Text, { color: "green" }, snapshot.context.description))),
@@ -124,51 +116,6 @@ export default function AddConnection({ options: { key, label, description, type
124
116
  !snapshot.matches("Ask for Client ID") && (React.createElement(Box, null,
125
117
  React.createElement(Text, null, "Client ID: "),
126
118
  React.createElement(Text, { color: "green" }, snapshot.context.clientId)))))),
127
- snapshot.matches("Ask for key") && (React.createElement(React.Fragment, null,
128
- React.createElement(Box, { flexDirection: "column" },
129
- React.createElement(Box, { flexDirection: "column", margin: 1, borderStyle: "round", padding: 1 },
130
- React.createElement(Text, null,
131
- "import ",
132
- "{",
133
- " connections ",
134
- "}",
135
- " from \"attio/server\""),
136
- React.createElement(Box, { marginY: 1 },
137
- React.createElement(Text, null, "...")),
138
- React.createElement(Text, null,
139
- "const response = await fetch(\"https://api.yourdomain.com/your-endpoint\", ",
140
- "{"),
141
- React.createElement(Text, null,
142
- " ",
143
- "method: \"GET\","),
144
- React.createElement(Text, null,
145
- " ",
146
- "headers: ",
147
- "{"),
148
- React.createElement(Text, null,
149
- " ",
150
- "\"Content-Type\": \"application/json\","),
151
- React.createElement(Box, { flexWrap: "wrap" },
152
- React.createElement(Text, null,
153
- " ",
154
- "Authorization: `Bearer $",
155
- "{",
156
- "connections"),
157
- React.createElement(Text, null, snapshot.context.key?.includes("-") ? '["' : "."),
158
- React.createElement(Text, { color: "yellowBright" }, snapshot.context.key),
159
- snapshot.context.key?.includes("-") && React.createElement(Text, null, "\"]"),
160
- React.createElement(Text, null,
161
- "}",
162
- "`,")),
163
- React.createElement(Box, { marginLeft: 41 + (snapshot.context.key?.includes("-") ? 1 : 0) },
164
- React.createElement(Text, { color: "cyan" }, "^".repeat(snapshot.context.key?.length ?? 0))),
165
- React.createElement(Text, null, " }"),
166
- React.createElement(Text, null,
167
- "}",
168
- ");")),
169
- React.createElement(Box, null,
170
- React.createElement(Text, null, "Unique Connection Key: "),
171
- React.createElement(TextInput, { value: snapshot.context.key ?? "", onChange: (key) => send({ type: "Update Key", key }), onSubmit: () => send({ type: "Submit" }) }))))),
172
119
  snapshot.matches("Ask for label") && (React.createElement(React.Fragment, null,
173
120
  React.createElement(Box, null,
174
121
  React.createElement(Text, null, "Provide a label for your connection. This is what your users will see.")),
@@ -42,8 +42,7 @@ export default function ListConnections({ options: { dev } }) {
42
42
  snapshot.matches("Display Connections") &&
43
43
  snapshot.context.connections &&
44
44
  snapshot.context.connections && (React.createElement(Box, null,
45
- React.createElement(Table, { rows: Object.entries(snapshot.context.connections).map(([slug, connection]) => ({
46
- Slug: slug,
45
+ React.createElement(Table, { rows: snapshot.context.connections.map((connection) => ({
47
46
  Label: connection.label,
48
47
  Global: connection.global ? "Yes" : "No",
49
48
  Type: connectionTypeNames[connection.connection_type],
@@ -37,17 +37,17 @@ export default function RemoveConnection({ options: { dev } }) {
37
37
  React.createElement(Box, null,
38
38
  React.createElement(Text, null, "Which connection would you like to remove?")),
39
39
  React.createElement(Box, null,
40
- React.createElement(Select, { items: Object.entries(snapshot.context.connections).map(([slug, value]) => ({
41
- value: slug,
42
- label: value.label,
43
- })), onSelect: (slug) => send({ type: "Connection Chosen", slug }) })))),
40
+ React.createElement(Select, { items: snapshot.context.connections.map((connection) => ({
41
+ value: connection.global,
42
+ label: connection.label,
43
+ })), onSelect: (global) => send({ type: "Connection Chosen", global }) })))),
44
44
  snapshot.matches("Confirm Removal") &&
45
- snapshot.context.chosenConnectionSlug &&
45
+ snapshot.context.global !== undefined &&
46
46
  snapshot.context.connections && (React.createElement(Box, { flexDirection: "column" },
47
47
  React.createElement(Box, null,
48
48
  React.createElement(Text, null,
49
49
  "Are you sure you want to remove \"",
50
- snapshot.context.connections[snapshot.context.chosenConnectionSlug].label,
50
+ snapshot.context.connections.find(({ global }) => global === snapshot.context.global).label,
51
51
  "\"?")),
52
52
  React.createElement(Box, null,
53
53
  React.createElement(Select, { items: [
@@ -3,8 +3,6 @@ import { assign, setup, fromCallback } from "xstate";
3
3
  import { addConnectionDefinition } from "../api/add-connection-definition.js";
4
4
  import { fetchConnections } from "../api/fetch-connections.js";
5
5
  import { options } from "../commands/connection/add.js";
6
- import { updateAppConfig } from "../util/app-config.js";
7
- import { slugifyExtension } from "../util/slugify-extension.js";
8
6
  import { loadAppConfig, loadDeveloperConfig } from "./actors.js";
9
7
  export const connectionTypes = [
10
8
  { value: "secret", label: "Secret" },
@@ -17,7 +15,7 @@ export const addConnectionMachine = setup({
17
15
  input: {},
18
16
  },
19
17
  actors: {
20
- "createConnectionDefinition": fromCallback(({ sendBack, input: { developer: { token, slug: devSlug }, config, connectionType: connection_type, key, label, description, global, authorizeUrl, accessTokenUrl, clientId, clientSecret, scopes, }, }) => {
18
+ "createConnectionDefinition": fromCallback(({ sendBack, input: { developer: { token, slug: devSlug }, config, connectionType: connection_type, label, description, global, authorizeUrl, accessTokenUrl, clientId, clientSecret, scopes, }, }) => {
21
19
  const add = async () => {
22
20
  try {
23
21
  await addConnectionDefinition({
@@ -26,7 +24,6 @@ export const addConnectionMachine = setup({
26
24
  appId: config.id,
27
25
  major: config.major,
28
26
  connectionType: connection_type,
29
- key,
30
27
  label,
31
28
  description,
32
29
  global,
@@ -36,10 +33,6 @@ export const addConnectionMachine = setup({
36
33
  clientSecret,
37
34
  scopes,
38
35
  });
39
- updateAppConfig((config) => ({
40
- ...config,
41
- connectionType: connection_type,
42
- }));
43
36
  sendBack({ type: "Success" });
44
37
  }
45
38
  catch (error) {
@@ -77,18 +70,18 @@ export const addConnectionMachine = setup({
77
70
  }
78
71
  };
79
72
  }),
80
- "validateKey": fromCallback(({ sendBack, input: { key, developer, config } }) => {
73
+ "validateGlobal": fromCallback(({ sendBack, input: { developer, config, global } }) => {
81
74
  fetchConnections({
82
75
  token: developer.token,
83
76
  devSlug: developer.slug,
84
77
  appId: config.id,
85
78
  major: config.major,
86
79
  }).then((connections) => {
87
- if (connections[key]) {
88
- sendBack({ type: "Key Taken" });
80
+ if (connections.some((connection) => connection.global === global)) {
81
+ sendBack({ type: "Global Taken" });
89
82
  }
90
83
  else {
91
- sendBack({ type: "Valid Key" });
84
+ sendBack({ type: "Valid Global" });
92
85
  }
93
86
  });
94
87
  }),
@@ -136,9 +129,6 @@ export const addConnectionMachine = setup({
136
129
  setDeveloperConfig: assign({
137
130
  developer: (_, params) => params,
138
131
  }),
139
- setKey: assign({
140
- key: (_, params) => slugifyExtension(params.key, false),
141
- }),
142
132
  setInvalidAuthorizeUrl: assign({
143
133
  error: (_, params) => {
144
134
  const result = options.shape.authorizeUrl
@@ -190,16 +180,12 @@ export const addConnectionMachine = setup({
190
180
  setAppConfig: assign({
191
181
  config: (_, params) => params.config,
192
182
  }),
193
- setKeyTaken: assign({
194
- error: () => "Key taken",
195
- }),
196
- slugifyLabel: assign({
197
- key: (_, params) => slugifyExtension(params.label, true),
183
+ setGlobalTaken: assign({
184
+ error: () => "Global taken",
198
185
  }),
199
186
  },
200
187
  guards: {
201
188
  "have connection type": (_, params) => Boolean(params.connectionType),
202
- "have key": (_, params) => Boolean(params.key),
203
189
  "have label": (_, params) => Boolean(params.label),
204
190
  "have description": (_, params) => Boolean(params.description),
205
191
  "have authorize url": (_, params) => params.connectionType === "secret" ||
@@ -274,7 +260,6 @@ export const addConnectionMachine = setup({
274
260
  global: context.global,
275
261
  label: context.label,
276
262
  description: context.description,
277
- key: context.key,
278
263
  }),
279
264
  },
280
265
  on: {
@@ -454,52 +439,6 @@ export const addConnectionMachine = setup({
454
439
  },
455
440
  ],
456
441
  },
457
- "Do we have a key?": {
458
- always: [
459
- {
460
- target: "Validating Key",
461
- guard: { type: "have key", params: ({ context }) => context },
462
- },
463
- {
464
- target: "Ask for key",
465
- actions: {
466
- type: "slugifyLabel",
467
- params: ({ context }) => ({ label: context.label }),
468
- },
469
- },
470
- ],
471
- },
472
- "Validating Key": {
473
- on: {
474
- "Key Taken": {
475
- target: "Ask for key",
476
- actions: "setKeyTaken",
477
- },
478
- "Valid Key": {
479
- target: "Do we have a description?",
480
- reenter: true,
481
- actions: "clearError",
482
- },
483
- },
484
- invoke: {
485
- src: "validateKey",
486
- input: ({ context }) => ({
487
- key: context.key,
488
- developer: context.developer,
489
- config: context.config,
490
- }),
491
- },
492
- },
493
- "Ask for key": {
494
- on: {
495
- "Update Key": {
496
- actions: { type: "setKey", params: ({ event }) => event },
497
- },
498
- "Submit": "Validating Key",
499
- "Previous": "Ask for label",
500
- "Next": "Validating Key",
501
- },
502
- },
503
442
  "Do we have a connection type?": {
504
443
  always: [
505
444
  {
@@ -537,7 +476,7 @@ export const addConnectionMachine = setup({
537
476
  "Do we have a label?": {
538
477
  always: [
539
478
  {
540
- target: "Do we have a key?",
479
+ target: "Do we have a description?",
541
480
  guard: { type: "have label", params: ({ context }) => context },
542
481
  reenter: true,
543
482
  },
@@ -560,7 +499,7 @@ export const addConnectionMachine = setup({
560
499
  "Do we have global?": {
561
500
  always: [
562
501
  {
563
- target: "Split on connection type",
502
+ target: "Validating Global",
564
503
  guard: { type: "have global", params: ({ context }) => context },
565
504
  reenter: true,
566
505
  },
@@ -572,7 +511,7 @@ export const addConnectionMachine = setup({
572
511
  "Ask for label": {
573
512
  on: {
574
513
  "Submit": {
575
- target: "Do we have a key?",
514
+ target: "Do we have a description?",
576
515
  guard: { type: "have label", params: ({ context }) => context },
577
516
  reenter: true,
578
517
  },
@@ -581,7 +520,7 @@ export const addConnectionMachine = setup({
581
520
  },
582
521
  "Previous": "Ask for connection type",
583
522
  "Next": {
584
- target: "Ask for key",
523
+ target: "Ask for description",
585
524
  guard: { type: "have label", params: ({ context }) => context },
586
525
  },
587
526
  },
@@ -602,7 +541,7 @@ export const addConnectionMachine = setup({
602
541
  guard: { type: "have description", params: ({ context }) => context },
603
542
  actions: "clearError",
604
543
  },
605
- "Previous": "Ask for key",
544
+ "Previous": "Ask for label",
606
545
  "Next": {
607
546
  target: "Ask for global",
608
547
  guard: { type: "have description", params: ({ context }) => context },
@@ -612,18 +551,38 @@ export const addConnectionMachine = setup({
612
551
  "Ask for global": {
613
552
  on: {
614
553
  "Choose Global": {
615
- target: "Split on connection type",
554
+ target: "Validating Global",
616
555
  actions: { type: "setGlobal", params: ({ event }) => event },
617
556
  reenter: true,
618
557
  },
619
558
  "Previous": "Ask for description",
620
559
  "Next": {
621
- target: "Split on connection type",
560
+ target: "Validating Global",
622
561
  guard: { type: "have global", params: ({ context }) => context },
623
562
  reenter: true,
624
563
  },
625
564
  },
626
565
  },
566
+ "Validating Global": {
567
+ on: {
568
+ "Global Taken": {
569
+ target: "Ask for global",
570
+ actions: "setGlobalTaken",
571
+ },
572
+ "Valid Global": {
573
+ target: "Split on connection type",
574
+ reenter: true,
575
+ },
576
+ },
577
+ invoke: {
578
+ src: "validateGlobal",
579
+ input: ({ context }) => ({
580
+ global: context.global,
581
+ developer: context.developer,
582
+ config: context.config,
583
+ }),
584
+ },
585
+ },
627
586
  },
628
587
  initial: "Loading Developer Config",
629
588
  invoke: {
@@ -39,7 +39,7 @@ export const listConnectionsMachine = setup({
39
39
  }),
40
40
  },
41
41
  guards: {
42
- "have connections": (_, params) => Boolean(params.connections && Object.keys(params.connections).length > 0),
42
+ "have connections": (_, params) => Boolean(params.connections && params.connections.length > 0),
43
43
  },
44
44
  }).createMachine({
45
45
  context: ({ input }) => ({
@@ -2,7 +2,6 @@ import { assign, setup, fromCallback } from "xstate";
2
2
  import { fetchConnections } from "../api/fetch-connections.js";
3
3
  import { removeConnectionDefinition } from "../api/remove-connection-definition.js";
4
4
  import { emptyConfig } from "../schema.js";
5
- import { updateAppConfig } from "../util/app-config.js";
6
5
  import { loadAppConfig, loadDeveloperConfig } from "./actors.js";
7
6
  export const removeConnectionMachine = setup({
8
7
  types: {
@@ -17,13 +16,9 @@ export const removeConnectionMachine = setup({
17
16
  token: input.developer.token,
18
17
  devSlug: input.developer.slug,
19
18
  appId: input.config.id,
20
- slug: input.chosenConnectionSlug,
19
+ global: input.global,
21
20
  major: input.config.major,
22
21
  });
23
- updateAppConfig((config) => ({
24
- ...config,
25
- connection: null,
26
- }));
27
22
  sendBack({ type: "Success" });
28
23
  }
29
24
  catch (error) {
@@ -64,16 +59,16 @@ export const removeConnectionMachine = setup({
64
59
  setConnections: assign({
65
60
  connections: (_, params) => params.connections,
66
61
  }),
67
- setConnection: assign({
68
- chosenConnectionSlug: (_, params) => params.slug,
62
+ setGlobal: assign({
63
+ global: (_, params) => params.global,
69
64
  }),
70
65
  setOnlyConnection: assign({
71
- chosenConnectionSlug: (_, params) => Object.keys(params.connections)[0],
66
+ global: (_, params) => params.connections[0].global,
72
67
  }),
73
68
  },
74
69
  guards: {
75
- "have more than one connection": (_, params) => Boolean(params.connections && Object.keys(params.connections).length > 1),
76
- "have only one connection": (_, params) => Boolean(params.connections && Object.keys(params.connections).length === 1),
70
+ "have more than one connection": (_, params) => Boolean(params.connections && params.connections.length > 1),
71
+ "have only one connection": (_, params) => Boolean(params.connections && params.connections.length === 1),
77
72
  },
78
73
  }).createMachine({
79
74
  context: ({ input }) => ({
@@ -125,7 +120,7 @@ export const removeConnectionMachine = setup({
125
120
  input: ({ context }) => ({
126
121
  developer: context.developer,
127
122
  config: context.config,
128
- chosenConnectionSlug: context.chosenConnectionSlug,
123
+ global: context.global,
129
124
  }),
130
125
  },
131
126
  on: {
@@ -187,7 +182,12 @@ export const removeConnectionMachine = setup({
187
182
  on: {
188
183
  "Connection Chosen": {
189
184
  target: "Confirm Removal",
190
- actions: { type: "setConnection", params: ({ event }) => event },
185
+ actions: {
186
+ type: "setGlobal",
187
+ params: ({ event }) => ({
188
+ global: event.global,
189
+ }),
190
+ },
191
191
  reenter: true,
192
192
  },
193
193
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "attio",
3
- "version": "0.0.1-experimental.20241011.3",
3
+ "version": "0.0.1-experimental.20241011.5",
4
4
  "bin": "lib/attio.js",
5
5
  "type": "module",
6
6
  "files": [