attio 0.0.1-experimental.20240926.1 → 0.0.1-experimental.20240927
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.
- package/lib/api/handle-error.js +8 -1
- package/lib/api/remove-connection-definition.js +2 -3
- package/lib/commands/connection/list.js +52 -0
- package/lib/commands/connection/remove.js +35 -8
- package/lib/machines/list-connections-machine.js +119 -0
- package/lib/machines/remove-connection-machine.js +86 -25
- package/package.json +1 -1
package/lib/api/handle-error.js
CHANGED
|
@@ -5,7 +5,14 @@ const serverErrorSchema = z.object({
|
|
|
5
5
|
export async function handleError(response) {
|
|
6
6
|
if (response.ok)
|
|
7
7
|
return;
|
|
8
|
-
const
|
|
8
|
+
const text = await response.text();
|
|
9
|
+
let json;
|
|
10
|
+
try {
|
|
11
|
+
json = JSON.parse(text);
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
throw new Error(`Error parsing JSON: ${JSON.stringify(text)}`);
|
|
15
|
+
}
|
|
9
16
|
const error = serverErrorSchema.parse(json);
|
|
10
17
|
throw new Error(error.message);
|
|
11
18
|
}
|
|
@@ -1,9 +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, }) {
|
|
5
|
-
const
|
|
6
|
-
const response = await fetch(`${API}/developer-portal/accounts/${devSlug}/apps/${appId}/versions/${major}/connection-definitions`, {
|
|
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}`, {
|
|
7
6
|
method: "DELETE",
|
|
8
7
|
headers: makeHeaders(token),
|
|
9
8
|
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useMachine } from "@xstate/react";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import Spinner from "ink-spinner";
|
|
4
|
+
import { option } from "pastel";
|
|
5
|
+
import React from "react";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { InitialInstructions } from "../../components/InitialInstructions.js";
|
|
8
|
+
import { Logo } from "../../components/Logo.js";
|
|
9
|
+
import { Table } from "../../components/Table.js";
|
|
10
|
+
import { listConnectionsMachine } from "../../machines/list-connections-machine.js";
|
|
11
|
+
export const description = "List all connections for the current major version of your Attio app";
|
|
12
|
+
export const options = z.object({
|
|
13
|
+
dev: z
|
|
14
|
+
.boolean()
|
|
15
|
+
.default(false)
|
|
16
|
+
.describe(option({ description: "Run in development mode (additional debugging info)" })),
|
|
17
|
+
});
|
|
18
|
+
const connectionTypeNames = {
|
|
19
|
+
"oauth2-code": "OAuth 2.0",
|
|
20
|
+
"secret": "Secret",
|
|
21
|
+
};
|
|
22
|
+
export default function ListConnections({ options: { dev } }) {
|
|
23
|
+
const [snapshot] = useMachine(listConnectionsMachine);
|
|
24
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
25
|
+
dev && (React.createElement(Box, null,
|
|
26
|
+
React.createElement(Text, null, JSON.stringify(snapshot.value, null, 2)))),
|
|
27
|
+
React.createElement(Logo, null),
|
|
28
|
+
snapshot.matches("Show config instructions") && (React.createElement(InitialInstructions, { reason: snapshot.context.configError })),
|
|
29
|
+
snapshot.matches("No Connections") && (React.createElement(Box, { flexDirection: "column" },
|
|
30
|
+
React.createElement(Box, null,
|
|
31
|
+
React.createElement(Text, { color: "redBright" }, "This app has no connections."),
|
|
32
|
+
React.createElement(Text, null, " To add one, use:")),
|
|
33
|
+
React.createElement(Box, { flexDirection: "column", borderStyle: "round", width: 27, paddingX: 1, marginBottom: 1 },
|
|
34
|
+
React.createElement(Text, null, "attio connection add")))),
|
|
35
|
+
snapshot.matches("Loading Connections") && (React.createElement(Box, { flexDirection: "column" },
|
|
36
|
+
React.createElement(Box, null,
|
|
37
|
+
React.createElement(Text, null, "Loading connections... "),
|
|
38
|
+
React.createElement(Text, { color: "green" },
|
|
39
|
+
React.createElement(Spinner, { type: "dots" }))))),
|
|
40
|
+
snapshot.matches("Error") && (React.createElement(Box, null,
|
|
41
|
+
React.createElement(Text, { color: "red" }, snapshot.context.error))),
|
|
42
|
+
snapshot.matches("Display Connections") &&
|
|
43
|
+
snapshot.context.connections &&
|
|
44
|
+
snapshot.context.connections && (React.createElement(Box, null,
|
|
45
|
+
React.createElement(Table, { rows: Object.entries(snapshot.context.connections).map(([slug, connection]) => ({
|
|
46
|
+
"Slug": slug,
|
|
47
|
+
"Label": connection.label,
|
|
48
|
+
"Global": connection.global ? "Yes" : "No",
|
|
49
|
+
"Allow Multiple": connection.allow_multiple ? "Yes" : "No",
|
|
50
|
+
"Type": connectionTypeNames[connection.connection_type],
|
|
51
|
+
})) })))));
|
|
52
|
+
}
|
|
@@ -6,6 +6,7 @@ import React from "react";
|
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { InitialInstructions } from "../../components/InitialInstructions.js";
|
|
8
8
|
import { Logo } from "../../components/Logo.js";
|
|
9
|
+
import { Select } from "../../components/Select.js";
|
|
9
10
|
import { removeConnectionMachine } from "../../machines/remove-connection-machine.js";
|
|
10
11
|
export const description = "Remove a connection from your Attio app";
|
|
11
12
|
export const options = z.object({
|
|
@@ -15,27 +16,53 @@ export const options = z.object({
|
|
|
15
16
|
.describe(option({ description: "Run in development mode (additional debugging info)" })),
|
|
16
17
|
});
|
|
17
18
|
export default function RemoveConnection({ options: { dev } }) {
|
|
18
|
-
const [snapshot] = useMachine(removeConnectionMachine);
|
|
19
|
+
const [snapshot, send] = useMachine(removeConnectionMachine);
|
|
19
20
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
20
21
|
dev && (React.createElement(Box, null,
|
|
21
22
|
React.createElement(Text, null, JSON.stringify(snapshot.value, null, 2)))),
|
|
22
23
|
React.createElement(Logo, null),
|
|
23
24
|
snapshot.matches("Show config instructions") && (React.createElement(InitialInstructions, { reason: snapshot.context.configError })),
|
|
24
|
-
snapshot.matches("No
|
|
25
|
+
snapshot.matches("No Connections") && (React.createElement(Box, { flexDirection: "column" },
|
|
25
26
|
React.createElement(Box, null,
|
|
26
27
|
React.createElement(Text, { color: "redBright" }, "This app has no connections to remove."),
|
|
27
28
|
React.createElement(Text, null, " To add one, use:")),
|
|
28
29
|
React.createElement(Box, { flexDirection: "column", borderStyle: "round", width: 27, paddingX: 1, marginBottom: 1 },
|
|
29
30
|
React.createElement(Text, null, "attio connection add")))),
|
|
30
|
-
snapshot.matches("
|
|
31
|
+
snapshot.matches("Loading Connections") && (React.createElement(Box, { flexDirection: "column" },
|
|
31
32
|
React.createElement(Box, null,
|
|
32
|
-
React.createElement(Text, null, "
|
|
33
|
+
React.createElement(Text, null, "Loading connections... "),
|
|
33
34
|
React.createElement(Text, { color: "green" },
|
|
34
35
|
React.createElement(Spinner, { type: "dots" }))))),
|
|
35
|
-
snapshot.matches("
|
|
36
|
+
snapshot.matches("Choosing a Connection") && snapshot.context.connections && (React.createElement(Box, { flexDirection: "column" },
|
|
37
|
+
React.createElement(Box, null,
|
|
38
|
+
React.createElement(Text, null, "Which connection would you like to remove?")),
|
|
36
39
|
React.createElement(Box, null,
|
|
37
|
-
React.createElement(
|
|
38
|
-
|
|
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 }) })))),
|
|
44
|
+
snapshot.matches("Confirm Removal") &&
|
|
45
|
+
snapshot.context.chosenConnectionSlug &&
|
|
46
|
+
snapshot.context.connections && (React.createElement(Box, { flexDirection: "column" },
|
|
39
47
|
React.createElement(Box, null,
|
|
40
|
-
React.createElement(Text,
|
|
48
|
+
React.createElement(Text, null,
|
|
49
|
+
"Are you sure you want to remove \"",
|
|
50
|
+
snapshot.context.connections[snapshot.context.chosenConnectionSlug].label,
|
|
51
|
+
"\"?")),
|
|
52
|
+
React.createElement(Box, null,
|
|
53
|
+
React.createElement(Select, { items: [
|
|
54
|
+
{ value: "Confirm", label: "Yes, remove it" },
|
|
55
|
+
{ value: "Cancel", label: "Cancel" },
|
|
56
|
+
], onSelect: (type) => send({ type }) })))),
|
|
57
|
+
snapshot.matches("Removing connection definition") && (React.createElement(Box, { flexDirection: "column" },
|
|
58
|
+
React.createElement(Box, null,
|
|
59
|
+
React.createElement(Text, null, "Removing connection definition..."),
|
|
60
|
+
React.createElement(Text, { color: "green" },
|
|
61
|
+
React.createElement(Spinner, { type: "dots" }))))),
|
|
62
|
+
snapshot.matches("Cancelled") && (React.createElement(Box, null,
|
|
63
|
+
React.createElement(Text, null, "No connections have been removed."))),
|
|
64
|
+
snapshot.matches("Success") && (React.createElement(Box, null,
|
|
65
|
+
React.createElement(Text, { color: "green" }, "SUCCESS!! \uD83C\uDF89 Your connection has been removed."))),
|
|
66
|
+
snapshot.matches("Error") && (React.createElement(Box, null,
|
|
67
|
+
React.createElement(Text, { color: "red" }, snapshot.context.error)))));
|
|
41
68
|
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { assign, setup, fromCallback } from "xstate";
|
|
2
|
+
import { fetchConnections } from "../api/fetch-connections.js";
|
|
3
|
+
import { emptyConfig } from "../schema.js";
|
|
4
|
+
import { loadAppConfig, loadDeveloperConfig } from "./actors.js";
|
|
5
|
+
export const listConnectionsMachine = setup({
|
|
6
|
+
types: {
|
|
7
|
+
context: {},
|
|
8
|
+
events: {},
|
|
9
|
+
},
|
|
10
|
+
actors: {
|
|
11
|
+
loadDeveloperConfig,
|
|
12
|
+
loadAppConfig,
|
|
13
|
+
loadConnections: fromCallback(({ sendBack, input }) => {
|
|
14
|
+
fetchConnections({
|
|
15
|
+
token: input.developer.token,
|
|
16
|
+
devSlug: input.developer.slug,
|
|
17
|
+
appId: input.config.id,
|
|
18
|
+
major: input.config.major,
|
|
19
|
+
})
|
|
20
|
+
.then((connections) => sendBack({ type: "Connections Loaded", connections }))
|
|
21
|
+
.catch((error) => sendBack({ type: "Error", error: error.message }));
|
|
22
|
+
}),
|
|
23
|
+
},
|
|
24
|
+
actions: {
|
|
25
|
+
setError: assign({
|
|
26
|
+
error: (_, params) => params.error,
|
|
27
|
+
}),
|
|
28
|
+
setDeveloperConfig: assign({
|
|
29
|
+
developer: (_, params) => params,
|
|
30
|
+
}),
|
|
31
|
+
setConfigError: assign({
|
|
32
|
+
configError: (_, params) => params.configError,
|
|
33
|
+
}),
|
|
34
|
+
setConfig: assign({
|
|
35
|
+
config: (_, params) => params.config,
|
|
36
|
+
}),
|
|
37
|
+
setConnections: assign({
|
|
38
|
+
connections: (_, params) => params.connections,
|
|
39
|
+
}),
|
|
40
|
+
},
|
|
41
|
+
guards: {
|
|
42
|
+
"have connections": (_, params) => Boolean(params.connections && Object.keys(params.connections).length > 0),
|
|
43
|
+
},
|
|
44
|
+
}).createMachine({
|
|
45
|
+
context: ({ input }) => ({
|
|
46
|
+
developer: { slug: "", token: "" },
|
|
47
|
+
config: emptyConfig,
|
|
48
|
+
...input,
|
|
49
|
+
}),
|
|
50
|
+
id: "List Connections Machine",
|
|
51
|
+
states: {
|
|
52
|
+
"Loading Developer Config": {
|
|
53
|
+
invoke: {
|
|
54
|
+
src: "loadDeveloperConfig",
|
|
55
|
+
},
|
|
56
|
+
on: {
|
|
57
|
+
"Developer Config Loaded": {
|
|
58
|
+
target: "Loading App Config",
|
|
59
|
+
actions: { type: "setDeveloperConfig", params: ({ event }) => event },
|
|
60
|
+
},
|
|
61
|
+
"No Developer Config": {
|
|
62
|
+
target: "Show config instructions",
|
|
63
|
+
actions: { type: "setConfigError", params: ({ event }) => event },
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
"Show config instructions": {
|
|
68
|
+
type: "final",
|
|
69
|
+
},
|
|
70
|
+
"Loading App Config": {
|
|
71
|
+
invoke: {
|
|
72
|
+
src: "loadAppConfig",
|
|
73
|
+
},
|
|
74
|
+
on: {
|
|
75
|
+
"Error": {
|
|
76
|
+
target: "Error",
|
|
77
|
+
actions: { type: "setError", params: ({ event }) => event },
|
|
78
|
+
},
|
|
79
|
+
"App Config Loaded": {
|
|
80
|
+
target: "Loading Connections",
|
|
81
|
+
actions: { type: "setConfig", params: ({ event }) => event },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
"Error": {
|
|
86
|
+
type: "final",
|
|
87
|
+
},
|
|
88
|
+
"Loading Connections": {
|
|
89
|
+
invoke: {
|
|
90
|
+
src: "loadConnections",
|
|
91
|
+
input: ({ context }) => context,
|
|
92
|
+
},
|
|
93
|
+
on: {
|
|
94
|
+
"Connections Loaded": [
|
|
95
|
+
{
|
|
96
|
+
target: "Display Connections",
|
|
97
|
+
actions: { type: "setConnections", params: ({ event }) => event },
|
|
98
|
+
guard: {
|
|
99
|
+
type: "have connections",
|
|
100
|
+
params: ({ event }) => event,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
"No Connections",
|
|
104
|
+
],
|
|
105
|
+
"Error": {
|
|
106
|
+
target: "Error",
|
|
107
|
+
actions: { type: "setError", params: ({ event }) => event },
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
"No Connections": {
|
|
112
|
+
type: "final",
|
|
113
|
+
},
|
|
114
|
+
"Display Connections": {
|
|
115
|
+
type: "final",
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
initial: "Loading Developer Config",
|
|
119
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { assign, setup, fromCallback } from "xstate";
|
|
2
|
+
import { fetchConnections } from "../api/fetch-connections.js";
|
|
2
3
|
import { removeConnectionDefinition } from "../api/remove-connection-definition.js";
|
|
3
4
|
import { emptyConfig } from "../schema.js";
|
|
4
5
|
import { updateAppConfig } from "../util/app-config.js";
|
|
@@ -16,6 +17,8 @@ export const removeConnectionMachine = setup({
|
|
|
16
17
|
token: input.developer.token,
|
|
17
18
|
devSlug: input.developer.slug,
|
|
18
19
|
appId: input.config.id,
|
|
20
|
+
slug: input.chosenConnectionSlug,
|
|
21
|
+
major: input.config.major,
|
|
19
22
|
});
|
|
20
23
|
updateAppConfig((config) => ({
|
|
21
24
|
...config,
|
|
@@ -31,6 +34,16 @@ export const removeConnectionMachine = setup({
|
|
|
31
34
|
}),
|
|
32
35
|
loadDeveloperConfig,
|
|
33
36
|
loadAppConfig,
|
|
37
|
+
loadConnections: fromCallback(({ sendBack, input }) => {
|
|
38
|
+
fetchConnections({
|
|
39
|
+
token: input.developer.token,
|
|
40
|
+
devSlug: input.developer.slug,
|
|
41
|
+
appId: input.config.id,
|
|
42
|
+
major: input.config.major,
|
|
43
|
+
})
|
|
44
|
+
.then((connections) => sendBack({ type: "Connections Loaded", connections }))
|
|
45
|
+
.catch((error) => sendBack({ type: "Error", error: error.message }));
|
|
46
|
+
}),
|
|
34
47
|
},
|
|
35
48
|
actions: {
|
|
36
49
|
clearError: assign({
|
|
@@ -45,12 +58,22 @@ export const removeConnectionMachine = setup({
|
|
|
45
58
|
setConfigError: assign({
|
|
46
59
|
configError: (_, params) => params.configError,
|
|
47
60
|
}),
|
|
48
|
-
|
|
61
|
+
setConfig: assign({
|
|
49
62
|
config: (_, params) => params.config,
|
|
50
63
|
}),
|
|
64
|
+
setConnections: assign({
|
|
65
|
+
connections: (_, params) => params.connections,
|
|
66
|
+
}),
|
|
67
|
+
setConnection: assign({
|
|
68
|
+
chosenConnectionSlug: (_, params) => params.slug,
|
|
69
|
+
}),
|
|
70
|
+
setOnlyConnection: assign({
|
|
71
|
+
chosenConnectionSlug: (_, params) => Object.keys(params.connections)[0],
|
|
72
|
+
}),
|
|
51
73
|
},
|
|
52
74
|
guards: {
|
|
53
|
-
"have
|
|
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),
|
|
54
77
|
},
|
|
55
78
|
}).createMachine({
|
|
56
79
|
context: ({ input }) => ({
|
|
@@ -88,9 +111,8 @@ export const removeConnectionMachine = setup({
|
|
|
88
111
|
actions: { type: "setError", params: ({ event }) => event },
|
|
89
112
|
},
|
|
90
113
|
"App Config Loaded": {
|
|
91
|
-
target: "
|
|
92
|
-
actions: { type: "
|
|
93
|
-
reenter: true,
|
|
114
|
+
target: "Loading Connections",
|
|
115
|
+
actions: { type: "setConfig", params: ({ event }) => event },
|
|
94
116
|
},
|
|
95
117
|
},
|
|
96
118
|
},
|
|
@@ -100,7 +122,11 @@ export const removeConnectionMachine = setup({
|
|
|
100
122
|
"Removing connection definition": {
|
|
101
123
|
invoke: {
|
|
102
124
|
src: "removeConnectionDefinition",
|
|
103
|
-
input: ({ context }) =>
|
|
125
|
+
input: ({ context }) => ({
|
|
126
|
+
developer: context.developer,
|
|
127
|
+
config: context.config,
|
|
128
|
+
chosenConnectionSlug: context.chosenConnectionSlug,
|
|
129
|
+
}),
|
|
104
130
|
},
|
|
105
131
|
on: {
|
|
106
132
|
Success: "Success",
|
|
@@ -113,32 +139,67 @@ export const removeConnectionMachine = setup({
|
|
|
113
139
|
"Success": {
|
|
114
140
|
type: "final",
|
|
115
141
|
},
|
|
116
|
-
"
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
142
|
+
"Loading Connections": {
|
|
143
|
+
invoke: {
|
|
144
|
+
src: "loadConnections",
|
|
145
|
+
input: ({ context }) => context,
|
|
146
|
+
},
|
|
147
|
+
on: {
|
|
148
|
+
"Connections Loaded": [
|
|
149
|
+
{
|
|
150
|
+
target: "Choosing a Connection",
|
|
151
|
+
actions: { type: "setConnections", params: ({ event }) => event },
|
|
152
|
+
guard: {
|
|
153
|
+
type: "have more than one connection",
|
|
154
|
+
params: ({ event }) => event,
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
target: "Confirm Removal",
|
|
159
|
+
guard: {
|
|
160
|
+
type: "have only one connection",
|
|
161
|
+
params: ({ event }) => event,
|
|
162
|
+
},
|
|
163
|
+
reenter: true,
|
|
164
|
+
actions: [
|
|
165
|
+
{
|
|
166
|
+
type: "setConnections",
|
|
167
|
+
params: ({ event }) => event,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type: "setOnlyConnection",
|
|
171
|
+
params: ({ event }) => event,
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
"No Connections",
|
|
176
|
+
],
|
|
177
|
+
"Error": {
|
|
178
|
+
target: "Error",
|
|
179
|
+
actions: { type: "setError", params: ({ event }) => event },
|
|
126
180
|
},
|
|
127
|
-
|
|
181
|
+
},
|
|
128
182
|
},
|
|
129
|
-
"No
|
|
183
|
+
"No Connections": {
|
|
130
184
|
type: "final",
|
|
131
185
|
},
|
|
132
|
-
"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
186
|
+
"Choosing a Connection": {
|
|
187
|
+
on: {
|
|
188
|
+
"Connection Chosen": {
|
|
189
|
+
target: "Confirm Removal",
|
|
190
|
+
actions: { type: "setConnection", params: ({ event }) => event },
|
|
191
|
+
reenter: true,
|
|
192
|
+
},
|
|
136
193
|
},
|
|
194
|
+
},
|
|
195
|
+
"Confirm Removal": {
|
|
137
196
|
on: {
|
|
138
|
-
|
|
139
|
-
|
|
197
|
+
Confirm: "Removing connection definition",
|
|
198
|
+
Cancel: "Cancelled",
|
|
140
199
|
},
|
|
141
|
-
|
|
200
|
+
},
|
|
201
|
+
"Cancelled": {
|
|
202
|
+
type: "final",
|
|
142
203
|
},
|
|
143
204
|
},
|
|
144
205
|
initial: "Loading Developer Config",
|