attio 0.0.1-experimental.20250328.1 → 0.0.1-experimental.20250401.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.
Files changed (39) hide show
  1. package/lib/api/determine-workspace.spinner.js +39 -0
  2. package/lib/api/{get-app-info.js → fetch-app-info.js} +1 -1
  3. package/lib/api/fetch-workspaces.js +11 -0
  4. package/lib/api/get-app-info.spinner.js +18 -0
  5. package/lib/api/get-app-slug-from-package-json.js +26 -0
  6. package/lib/api/get-versions.spinner.js +21 -0
  7. package/lib/commands/build/build-javascript.js +24 -0
  8. package/lib/commands/build/validate-typescript.js +30 -0
  9. package/lib/commands/build.js +32 -16
  10. package/lib/commands/dev/boot.js +4 -4
  11. package/lib/commands/dev/build-javascript.js +2 -2
  12. package/lib/commands/dev/bundle-javascript.js +1 -1
  13. package/lib/commands/dev/prepare-build-contexts.js +3 -3
  14. package/lib/commands/init/ask-language.js +11 -0
  15. package/lib/commands/init/boot.js +14 -0
  16. package/lib/commands/init/create-project.js +50 -0
  17. package/lib/commands/init.js +23 -16
  18. package/lib/commands/login.js +2 -0
  19. package/lib/commands/logout.js +2 -0
  20. package/lib/commands/version/create/boot.js +9 -0
  21. package/lib/commands/version/create.js +71 -15
  22. package/lib/commands/version/list.js +4 -2
  23. package/lib/commands/whoami.js +2 -1
  24. package/lib/util/{validate-slug.js → can-write.js} +0 -2
  25. package/lib/util/print-logo.js +5 -0
  26. package/lib/util/print-message.js +3 -2
  27. package/package.json +2 -14
  28. package/lib/api/create-developer-account.js +0 -36
  29. package/lib/machines/actions.js +0 -8
  30. package/lib/machines/actors.js +0 -123
  31. package/lib/machines/build-machine.js +0 -192
  32. package/lib/machines/build-orchestrator.js +0 -1
  33. package/lib/machines/code-gen-machine.js +0 -97
  34. package/lib/machines/create-version-machine.js +0 -308
  35. package/lib/machines/env-machine.js +0 -82
  36. package/lib/machines/init-machine.js +0 -192
  37. package/lib/machines/js-machine.js +0 -231
  38. package/lib/machines/ts-machine.js +0 -105
  39. package/lib/util/set-terminal-title.js +0 -8
@@ -1,9 +1,10 @@
1
1
  import Blocker from "stdin-blocker";
2
2
  import Cursor from "tiny-cursor";
3
+ import readline from "readline";
3
4
  export function printMessage(message) {
4
5
  Blocker.block();
5
6
  Cursor.hide();
6
- process.stdout.cursorTo(0);
7
+ readline.cursorTo(process.stdout, 0);
7
8
  process.stdout.write(message);
8
- process.stdout.clearLine(1);
9
+ readline.clearLine(process.stdout, 1);
9
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "attio",
3
- "version": "0.0.1-experimental.20250328.1",
3
+ "version": "0.0.1-experimental.20250401.1",
4
4
  "bin": "lib/attio.js",
5
5
  "type": "module",
6
6
  "files": [
@@ -39,13 +39,10 @@
39
39
  "@hono/node-server": "1.13.7",
40
40
  "@inquirer/prompts": "7.2.0",
41
41
  "@swc/core": "^1.3.58",
42
- "@xstate/react": "4.1.1",
43
- "@xstate/store": "1.0.0",
44
42
  "boxen": "^8.0.1",
45
43
  "chalk": "^5.4.1",
46
44
  "chokidar": "^3.6.0",
47
45
  "cli-table3": "^0.6.5",
48
- "clipboardy": "^4.0.0",
49
46
  "commander": "^13.0.0",
50
47
  "date-fns": "^2.21.1",
51
48
  "dotenv": "^16.4.5",
@@ -54,24 +51,15 @@
54
51
  "glob": "^11.0.1",
55
52
  "graphql": "16.9.0",
56
53
  "hono": "4.6.18",
57
- "immer": "^5.0.0",
58
- "ini": "^4.1.3",
59
- "inquirer": "^12.3.0",
60
54
  "keytar": "^7.9.0",
61
55
  "node-notifier": "^10.0.1",
62
56
  "open": "^7.0.0",
63
- "prettier": "^3.4.1",
64
- "react": "18.3.1",
65
57
  "stdin-blocker": "^2.0.0",
66
58
  "tiny-cursor": "^2.0.0",
67
59
  "tmp-promise": "^3.0.3",
68
60
  "ts-morph": "^24.0.0",
69
61
  "typescript": "5.6.3",
70
- "uuid": "^9.0.1",
71
- "xstate": "5.19.1",
72
- "zod": "^3.22.3",
73
- "zod-to-json-schema": "3.23.1",
74
- "zod-validation-error": "3.3.0"
62
+ "zod": "^3.22.3"
75
63
  },
76
64
  "peerDependencies": {
77
65
  "react": "^18"
@@ -1,36 +0,0 @@
1
- import { v4 as uuid } from "uuid";
2
- import { z } from "zod";
3
- import { API } from "../env.js";
4
- import { handleError } from "./handle-error.js";
5
- import { makeHeaders } from "./make-headers.js";
6
- const isTest = process.env.NODE_ENV === "test";
7
- const createDeveloperAccountSchema = z.object({
8
- developer_account: z.object({
9
- developer_account_id: z.string(),
10
- }),
11
- developer_account_member: z.object({
12
- developer_account_member_id: z.string(),
13
- }),
14
- });
15
- export async function createDeveloperAccount({ token, developerSlug, }) {
16
- const accountId = uuid();
17
- if (isTest) {
18
- return createDeveloperAccountSchema.parse({
19
- developer_account: { developer_account_id: accountId },
20
- developer_account_member: { developer_account_member_id: accountId },
21
- });
22
- }
23
- const response = await fetch(`${API}/developer-accounts/${accountId}`, {
24
- method: "PUT",
25
- headers: makeHeaders(token),
26
- body: JSON.stringify({ slug: developerSlug, title: developerSlug }),
27
- });
28
- await handleError(response);
29
- const json = await response.json();
30
- try {
31
- return createDeveloperAccountSchema.parse(json);
32
- }
33
- catch {
34
- throw new Error(JSON.stringify(json));
35
- }
36
- }
@@ -1,8 +0,0 @@
1
- import chalk from "chalk";
2
- import { textGradient } from "../util/text-gradient.js";
3
- import { attioLogoAndName } from "../attio-logo.js";
4
- export const showError = (_, params) => process.stderr.write(`${chalk.red("✖ " + params.error)}\n`);
5
- export const showActorError = (_, params) => process.stderr.write(`${chalk.red("✖ " + params.error)}\n`);
6
- export const printLogo = () => {
7
- process.stdout.write(`\n${textGradient(attioLogoAndName, "#ff5f6d", "#ffc371")}\n\n`);
8
- };
@@ -1,123 +0,0 @@
1
- import { fetchVersions as fetchVersionsApi } from "../api/fetch-versions.js";
2
- import { input as inputPrompt, password as passwordPrompt, select as selectPrompt, confirm as confirmPrompt, } from "@inquirer/prompts";
3
- import { fromCallback, fromPromise } from "xstate";
4
- import { readFileSync } from "fs";
5
- import { join } from "path";
6
- import { z } from "zod";
7
- import { getAppInfo } from "../api/get-app-info.js";
8
- import { ensureAuthed } from "../api/ensure-authed.js";
9
- import { fetchWorkspaces } from "../api/fetch-workspaces.js";
10
- import { APP } from "../env.js";
11
- import { Spinner } from "../util/spinner.js";
12
- export const authenticate = fromPromise(ensureAuthed);
13
- const packageJsonSchema = z.object({
14
- name: z.string({
15
- required_error: "No name field found in package.json",
16
- invalid_type_error: "name must be a string in package.json",
17
- }),
18
- });
19
- export const getAppSlugFromPackageJson = async () => {
20
- try {
21
- const packageJsonPath = join(process.cwd(), "package.json");
22
- const packageJsonRaw = JSON.parse(readFileSync(packageJsonPath, "utf8"));
23
- const result = packageJsonSchema.safeParse(packageJsonRaw);
24
- if (!result.success) {
25
- throw new Error(result.error.issues[0]?.message || "Malformed package.json");
26
- }
27
- return result.data.name;
28
- }
29
- catch (error) {
30
- if (error instanceof SyntaxError) {
31
- throw new Error("Invalid JSON in package.json");
32
- }
33
- throw new Error("Failed to read package.json");
34
- }
35
- };
36
- export const loadAppSlug = fromPromise(getAppSlugFromPackageJson);
37
- export const fetchVersions = fromPromise(async ({ input: { token, appInfo } }) => {
38
- const spinner = new Spinner();
39
- try {
40
- spinner.start("Loading versions...");
41
- const versions = await fetchVersionsApi({
42
- token,
43
- appId: appInfo.app_id,
44
- });
45
- spinner.success("Versions loaded");
46
- return versions;
47
- }
48
- catch (error) {
49
- spinner.error("Error loading versions");
50
- throw error;
51
- }
52
- finally {
53
- spinner.stop();
54
- }
55
- });
56
- export async function fetchAppInfo({ token, appSlug, }) {
57
- const spinner = new Spinner();
58
- spinner.start("Loading app information...");
59
- try {
60
- const appInfo = await getAppInfo({ token, appSlug });
61
- if (appInfo === null) {
62
- spinner.error("App not found");
63
- throw new Error("App not found");
64
- }
65
- spinner.success(`App found: ${appInfo.title}`);
66
- return appInfo;
67
- }
68
- finally {
69
- spinner.stop();
70
- }
71
- }
72
- export const loadAppInfo = fromPromise(async ({ input: { token, appSlug } }) => await fetchAppInfo({ token, appSlug }));
73
- export const ask = fromPromise(async ({ input }) => await inputPrompt(input));
74
- export const askPassword = fromPromise(async ({ input }) => await passwordPrompt(input));
75
- export const askWithChoices = fromPromise(async ({ input, }) => await selectPrompt(input));
76
- export const askWithTypedChoices = () => fromPromise(async ({ input, }) => await selectPrompt(input));
77
- export const confirm = fromPromise(async ({ input }) => await confirmPrompt(input));
78
- export const fromCallbackWithErrorHandling = (callback) => fromCallback((...args) => {
79
- try {
80
- return callback(...args);
81
- }
82
- catch (error) {
83
- args[0].sendBack({
84
- type: "Error",
85
- error: typeof error === "string" ? new Error(error) : error,
86
- });
87
- }
88
- });
89
- export async function determineWorkspace({ token, workspaceSlug, }) {
90
- const spinner = new Spinner();
91
- spinner.start("Loading workspaces...");
92
- try {
93
- const workspaces = await fetchWorkspaces({ token });
94
- spinner.success("Workspaces loaded");
95
- const workspace = workspaces.find((workspace) => workspace.slug === workspaceSlug);
96
- if (workspace) {
97
- spinner.success(`Using workspace: ${workspace.name}`);
98
- return workspace;
99
- }
100
- if (workspaces.length === 0) {
101
- throw new Error(`You are not the admin of any workspaces. Either request permission from an existing workspace or create your own.
102
-
103
- ${APP}/welcome/workspace-details
104
- `);
105
- }
106
- if (workspaces.length === 1) {
107
- spinner.success(`Using workspace: ${workspaces[0].name}`);
108
- return workspaces[0];
109
- }
110
- const choice = await selectPrompt({
111
- message: "Choose a workspace",
112
- choices: workspaces.map((workspace) => ({
113
- name: workspace.name,
114
- value: workspace,
115
- })),
116
- });
117
- spinner.success(`Using workspace: ${choice.name}`);
118
- return choice;
119
- }
120
- finally {
121
- spinner.stop();
122
- }
123
- }
@@ -1,192 +0,0 @@
1
- import { assign, setup } from "xstate";
2
- import { codeGenMachine } from "./code-gen-machine.js";
3
- import { jsMachine } from "./js-machine.js";
4
- import { tsMachine } from "./ts-machine.js";
5
- import { printJsError, printTsError } from "../util/typescript.js";
6
- import { printLogo } from "./actions.js";
7
- import { Spinner } from "../util/spinner.js";
8
- const processes = ["javascript", "typescript"];
9
- const spinner = new Spinner();
10
- export const buildMachine = setup({
11
- types: {
12
- context: {},
13
- events: {},
14
- children: {},
15
- },
16
- actors: {
17
- "typescript": tsMachine,
18
- "javascript": jsMachine,
19
- "code-gen": codeGenMachine,
20
- },
21
- guards: {
22
- "all done": ({ context }) => context.failed.length + context.successful.length === processes.length,
23
- "all success": ({ context }) => context.successful.length === processes.length,
24
- },
25
- actions: {
26
- buildingStart: () => {
27
- spinner.start("🔨 Building...");
28
- },
29
- buildFail: ({ context }) => {
30
- spinner.error("Build failed");
31
- const { tsErrors = [], jsErrors } = context;
32
- process.stderr.write("\n");
33
- tsErrors.forEach(printTsError);
34
- jsErrors?.errors?.forEach((error) => {
35
- printJsError(error, "error");
36
- });
37
- jsErrors?.warnings?.forEach((warning) => {
38
- printJsError(warning, "warning");
39
- });
40
- },
41
- buildSuccess: () => {
42
- spinner.success("Build succeeded");
43
- },
44
- printLogo,
45
- setFailed: assign({
46
- failed: ({ context }, params) => [...context.failed, params.process],
47
- }),
48
- setTypeScriptErrors: assign({
49
- tsErrors: (_, params) => params.errors,
50
- }),
51
- setJavaScriptErrors: assign({
52
- jsErrors: (_, params) => params.errors,
53
- }),
54
- setSuccess: assign({
55
- successful: ({ context }, params) => [
56
- ...context.successful,
57
- params.process,
58
- ],
59
- }),
60
- },
61
- }).createMachine({
62
- context: { successful: [], failed: [] },
63
- id: "Build Machine",
64
- states: {
65
- "Errored": {
66
- type: "final",
67
- entry: "buildFail",
68
- },
69
- "Success": {
70
- type: "final",
71
- entry: "buildSuccess",
72
- },
73
- "Building": {
74
- type: "parallel",
75
- states: {
76
- JavaScript: {
77
- states: {
78
- Building: {
79
- on: {
80
- "JavaScript Success": {
81
- target: "Waiting",
82
- actions: {
83
- type: "setSuccess",
84
- params: { process: "javascript" },
85
- },
86
- },
87
- "JavaScript Error": {
88
- target: "Waiting",
89
- actions: [
90
- {
91
- type: "setFailed",
92
- params: { process: "javascript" },
93
- },
94
- {
95
- type: "setJavaScriptErrors",
96
- params: ({ event }) => event,
97
- },
98
- ],
99
- },
100
- },
101
- },
102
- Waiting: {
103
- always: {
104
- target: "#Build Machine.All Done",
105
- guard: "all done",
106
- },
107
- },
108
- },
109
- initial: "Building",
110
- invoke: {
111
- src: "javascript",
112
- id: "javascript",
113
- input: ({ self }) => ({ parentRef: self, write: true }),
114
- },
115
- },
116
- TypeScript: {
117
- states: {
118
- "Validating": {
119
- on: {
120
- "TypeScript Success": {
121
- target: "Waiting",
122
- actions: {
123
- type: "setSuccess",
124
- params: { process: "typescript" },
125
- },
126
- },
127
- "TypeScript Error": {
128
- target: "Waiting",
129
- actions: [
130
- {
131
- type: "setFailed",
132
- params: { process: "typescript" },
133
- },
134
- {
135
- type: "setTypeScriptErrors",
136
- params: ({ event }) => event,
137
- },
138
- ],
139
- },
140
- },
141
- invoke: {
142
- src: "typescript",
143
- id: "typescript",
144
- input: ({ self }) => ({ parentRef: self }),
145
- },
146
- },
147
- "Waiting": {
148
- always: {
149
- target: "#Build Machine.All Done",
150
- guard: "all done",
151
- },
152
- },
153
- "Code Generating": {
154
- on: {
155
- "Code Generation Done": "Validating",
156
- "Error": {
157
- target: "Waiting",
158
- actions: {
159
- type: "setFailed",
160
- params: { process: "typescript" },
161
- },
162
- reenter: true,
163
- },
164
- },
165
- invoke: {
166
- src: "code-gen",
167
- id: "code-gen",
168
- input: ({ self }) => ({ parentRef: self }),
169
- },
170
- },
171
- },
172
- initial: "Code Generating",
173
- },
174
- },
175
- entry: "buildingStart",
176
- },
177
- "All Done": {
178
- always: [
179
- {
180
- target: "Success",
181
- guard: "all success",
182
- },
183
- {
184
- target: "Errored",
185
- reenter: true,
186
- },
187
- ],
188
- },
189
- },
190
- initial: "Building",
191
- entry: "printLogo",
192
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,97 +0,0 @@
1
- import { readFileSync } from "fs";
2
- import { parse } from "graphql";
3
- import { sendTo, assign, setup, fromCallback } from "xstate";
4
- import { generateOperations } from "../graphql/generate-operations.js";
5
- import { findNodeModulesPath } from "../util/find-node-modules-path.js";
6
- export const codeGenMachine = setup({
7
- types: {
8
- context: {},
9
- events: {},
10
- input: {},
11
- },
12
- actors: {
13
- loadSchema: fromCallback(({ sendBack }) => {
14
- const loadSchema = async () => {
15
- try {
16
- const path = await findNodeModulesPath(["schema.graphql"]);
17
- if (!path) {
18
- sendBack({ type: "Error", error: new Error("No schema found") });
19
- return;
20
- }
21
- const schema = parse(readFileSync(path, "utf8"));
22
- sendBack({ type: "Schema Loaded", schema });
23
- }
24
- catch (error) {
25
- sendBack({ type: "Error", error });
26
- }
27
- };
28
- loadSchema();
29
- }),
30
- generateOperations: fromCallback(({ sendBack, input }) => {
31
- generateOperations(".", input.schema)
32
- .then(() => sendBack({ type: "Done" }))
33
- .catch((error) => sendBack({ type: "Error", error }));
34
- }),
35
- },
36
- actions: {
37
- clearError: assign({
38
- error: () => undefined,
39
- }),
40
- setError: assign({
41
- error: (_, params) => params.error,
42
- }),
43
- setSchema: assign({
44
- schema: (_, params) => params.schema,
45
- }),
46
- raiseDone: sendTo(({ context }) => context.parentRef, { type: "Code Generation Done" }),
47
- },
48
- }).createMachine({
49
- id: "GraphQL Code Generation Machine",
50
- context: ({ input }) => ({
51
- schema: null,
52
- parentRef: input.parentRef,
53
- }),
54
- states: {
55
- "Load Schema": {
56
- on: {
57
- "Error": {
58
- target: "Errored",
59
- actions: { type: "setError", params: ({ event }) => event },
60
- },
61
- "Schema Loaded": {
62
- target: "Generating Operations",
63
- actions: { type: "setSchema", params: ({ event }) => event },
64
- reenter: true,
65
- },
66
- },
67
- invoke: {
68
- src: "loadSchema",
69
- },
70
- },
71
- "Done": {
72
- entry: "raiseDone",
73
- },
74
- "Errored": {},
75
- "Generating Operations": {
76
- on: {
77
- Done: {
78
- target: "Done",
79
- actions: "clearError",
80
- },
81
- Error: {
82
- target: "Errored",
83
- actions: { type: "setError", params: ({ event }) => event },
84
- },
85
- },
86
- invoke: {
87
- src: "generateOperations",
88
- input: ({ context }) => ({ schema: context.schema }),
89
- },
90
- },
91
- },
92
- initial: "Load Schema",
93
- on: {
94
- Change: ".Load Schema",
95
- },
96
- description: `Generates operations typescript types`,
97
- });