attio 0.0.1-experimental.20241219 → 0.0.1-experimental.20250101

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 (54) hide show
  1. package/lib/api/create-version.js +2 -2
  2. package/lib/attio-logo.js +24 -0
  3. package/lib/attio.js +17 -8
  4. package/lib/commands/build.js +18 -35
  5. package/lib/commands/connection/add.js +51 -168
  6. package/lib/commands/connection/index.js +9 -1
  7. package/lib/commands/connection/list.js +17 -47
  8. package/lib/commands/connection/remove.js +17 -65
  9. package/lib/commands/create.js +27 -126
  10. package/lib/commands/dev.js +17 -106
  11. package/lib/commands/version/create.js +17 -68
  12. package/lib/commands/version/index.js +11 -1
  13. package/lib/commands/version/invite.js +40 -84
  14. package/lib/commands/version/list.js +18 -40
  15. package/lib/commands/version/publish.js +40 -64
  16. package/lib/machines/actions.js +7 -0
  17. package/lib/machines/actors.js +7 -1
  18. package/lib/machines/add-connection-machine.js +169 -201
  19. package/lib/machines/build-machine.js +35 -4
  20. package/lib/machines/create-machine.js +95 -70
  21. package/lib/machines/create-version-machine.js +121 -4
  22. package/lib/machines/dev-machine.js +173 -53
  23. package/lib/machines/generate-invite-machine.js +64 -10
  24. package/lib/machines/list-connections-machine.js +57 -2
  25. package/lib/machines/list-versions-machine.js +33 -0
  26. package/lib/machines/publish-version-machine.js +45 -16
  27. package/lib/machines/remove-connection-machine.js +64 -17
  28. package/lib/machines/ts-machine.js +4 -1
  29. package/lib/schema.js +2 -2
  30. package/lib/util/clear-terminal.js +4 -0
  31. package/lib/util/load-developer-config.js +2 -2
  32. package/lib/util/print-install-instructions.js +32 -0
  33. package/lib/util/print-message.js +9 -0
  34. package/lib/util/set-terminal-title.js +8 -0
  35. package/lib/util/text-gradient.js +28 -0
  36. package/lib/util/typescript.js +25 -0
  37. package/package.json +13 -12
  38. package/schema.graphql +8 -1
  39. package/lib/components/BuildError.js +0 -46
  40. package/lib/components/BuildLog.js +0 -6
  41. package/lib/components/CodeGenErrors.js +0 -22
  42. package/lib/components/Disclaimer.js +0 -9
  43. package/lib/components/InitialInstructions.js +0 -69
  44. package/lib/components/Log.js +0 -69
  45. package/lib/components/Logo.js +0 -10
  46. package/lib/components/MultiSelect.js +0 -65
  47. package/lib/components/ScrollBox.js +0 -87
  48. package/lib/components/ScrollBox.store.js +0 -36
  49. package/lib/components/ScrollBox.util.js +0 -27
  50. package/lib/components/Select.js +0 -6
  51. package/lib/components/Table.js +0 -33
  52. package/lib/components/TypeScriptErrors.js +0 -38
  53. package/lib/hooks/useFullScreen.js +0 -22
  54. package/lib/hooks/useTerminalTitle.js +0 -11
package/schema.graphql CHANGED
@@ -152,10 +152,11 @@ type ActorReferenceValue {
152
152
  }
153
153
 
154
154
  """An actor inside Attio."""
155
- union Actor = User | SystemActor | APITokenActor | Workflow
155
+ union Actor = User | SystemActor | APITokenActor | App | Workflow
156
156
 
157
157
  """An Attio user."""
158
158
  type User {
159
+ id: String!
159
160
  email: String!
160
161
  name: String!
161
162
  }
@@ -170,6 +171,11 @@ type APITokenActor {
170
171
  type: String!
171
172
  }
172
173
 
174
+ """An Attio app."""
175
+ type App {
176
+ type: String!
177
+ }
178
+
173
179
  """An Attio workflow."""
174
180
  type Workflow {
175
181
  type: String!
@@ -247,6 +253,7 @@ type Query {
247
253
  """Slug of the record's object."""
248
254
  object: String!
249
255
  ): Record
256
+ currentUser: User!
250
257
  }
251
258
 
252
259
  """The person object in the workspace."""
@@ -1,46 +0,0 @@
1
- import { Box, Text } from "ink";
2
- import React from "react";
3
- const Error = React.forwardRef(({ message, level }, ref) => (React.createElement(Box, { flexDirection: "column", ref: ref },
4
- React.createElement(Box, null,
5
- React.createElement(Text, { color: level === "error" ? "red" : "yellow" },
6
- level === "error" ? "❌" : "⚠️",
7
- " ",
8
- React.createElement(Text, { backgroundColor: level === "error" ? "red" : "yellow", color: "white" },
9
- " ",
10
- level === "error" ? "ERROR" : "WARNING",
11
- " ")),
12
- React.createElement(Text, { bold: true }, message.text)),
13
- React.createElement(Box, { paddingTop: 1, flexDirection: "column" },
14
- React.createElement(Box, { marginLeft: 4 },
15
- React.createElement(Text, null,
16
- message.location.file,
17
- ":",
18
- message.location.line,
19
- ":",
20
- message.location.column)),
21
- React.createElement(Box, { marginLeft: 4, marginTop: 1 },
22
- React.createElement(Box, { flexDirection: "column", marginRight: 1 },
23
- React.createElement(Text, null, message.location.line)),
24
- React.createElement(Box, { flexDirection: "column" },
25
- React.createElement(Text, null,
26
- "| ",
27
- message.location.lineText.trim()),
28
- React.createElement(Box, null,
29
- React.createElement(Text, null, "|"),
30
- React.createElement(Box, { paddingLeft: message.location.column +
31
- message.location.lineText.trim().length -
32
- message.location.lineText.length +
33
- 1 },
34
- React.createElement(Text, { color: "greenBright" }, "^"))))),
35
- message.location.additionalLines &&
36
- message.location.additionalLines.slice(0, 2).map((line, index) => (React.createElement(Box, { key: `additional-line-${index}`, marginLeft: 4 },
37
- React.createElement(Text, null,
38
- message.location.line + index + 1,
39
- " | ",
40
- line))))))));
41
- export function renderBuildErrors({ errors, warnings }) {
42
- return [
43
- ...(errors ?? []).map((error, index) => (React.createElement(Error, { key: `BuildError-${index}`, message: error, level: "error" }))),
44
- ...(warnings ?? []).map((error, index) => (React.createElement(Error, { key: `BuildError-${index}`, message: error, level: "warning" }))),
45
- ];
46
- }
@@ -1,6 +0,0 @@
1
- import { Box, Text } from "ink";
2
- import React from "react";
3
- export function BuildLog({ log }) {
4
- return (React.createElement(Box, { flexDirection: "column" }, log.map((msg, index) => (React.createElement(Box, { key: index },
5
- React.createElement(Text, null, msg))))));
6
- }
@@ -1,22 +0,0 @@
1
- import { codeFrameColumns } from "@babel/code-frame";
2
- import { Box, Text } from "ink";
3
- import React from "react";
4
- export const CodeGenError = React.forwardRef(({ error }, ref) => {
5
- return (React.createElement(Box, { flexDirection: "column", ref: ref },
6
- React.createElement(Box, null,
7
- React.createElement(Text, { color: "red" },
8
- React.createElement(Text, { backgroundColor: "red", color: "white" },
9
- " ",
10
- "GRAPHQL ERROR",
11
- " "),
12
- " ",
13
- React.createElement(Text, null, error.message))),
14
- error.locations && (React.createElement(Box, { paddingTop: 1, flexDirection: "column" },
15
- React.createElement(Box, null,
16
- React.createElement(Text, null, codeFrameColumns(error.source, {
17
- start: {
18
- line: error.locations[0].line,
19
- column: error.locations[0].column,
20
- },
21
- })))))));
22
- });
@@ -1,9 +0,0 @@
1
- import { Box, Text } from "ink";
2
- import React from "react";
3
- const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_PROMOTED = "You found something that isn't quite ready yet.";
4
- export const Disclaimer = () => (React.createElement(Box, { marginBottom: 2, marginX: 1, padding: 1, borderStyle: "bold", width: 61 },
5
- React.createElement(Box, { flexDirection: "column" },
6
- React.createElement(Box, null,
7
- React.createElement(Text, { color: "yellowBright" }, "You are using the Private Alpha version of this CLI tool.")),
8
- React.createElement(Box, { marginTop: 2, alignSelf: "center" },
9
- React.createElement(Text, { color: "magentaBright" }, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_PROMOTED)))));
@@ -1,69 +0,0 @@
1
- import { stringify } from "ini";
2
- import { Box, Text } from "ink";
3
- import Link from "ink-link";
4
- import React from "react";
5
- import { APP, APP_NO_PROTOCOL, IS_DEV } from "../env.js";
6
- import { configFileName } from "../util/load-developer-config.js";
7
- const exampleConfig = {
8
- token: "YOUR TOKEN HERE",
9
- developer_slug: "ANY UNIQUE SLUG YOU WANT",
10
- target_workspace_id: "YOUR WORKSPACE ID HERE",
11
- };
12
- export const InitialInstructions = ({ reason }) => (React.createElement(Box, { flexDirection: "column", gap: 1 },
13
- reason && (React.createElement(Box, { flexDirection: "column" },
14
- React.createElement(Box, null,
15
- React.createElement(Text, null, "Failed to load config file.")),
16
- React.createElement(Box, null,
17
- React.createElement(Text, { color: "redBright" }, reason)))),
18
- React.createElement(Box, null,
19
- React.createElement(Text, null, "You will need to:")),
20
- React.createElement(Box, { flexDirection: "column", marginLeft: 2, marginBottom: 1 },
21
- React.createElement(Box, null,
22
- React.createElement(Text, null,
23
- "1. Log into",
24
- IS_DEV && (React.createElement(React.Fragment, null,
25
- " ",
26
- React.createElement(Text, { italic: true }, "DEVELOPMENT"))),
27
- " ",
28
- "Attio web app:",
29
- " ",
30
- React.createElement(Link, { url: APP, fallback: false }, APP),
31
- ".")),
32
- React.createElement(Box, null,
33
- React.createElement(Text, null,
34
- "2. Open ",
35
- React.createElement(Text, { color: "cyan" }, "Dev Tools"),
36
- " >",
37
- " ",
38
- React.createElement(Text, { color: "cyan" }, "Application"),
39
- " > ",
40
- React.createElement(Text, { color: "cyan" }, "Cookies"),
41
- " ",
42
- "> ",
43
- React.createElement(Text, { color: "cyan" }, APP_NO_PROTOCOL))),
44
- React.createElement(Box, null,
45
- React.createElement(Text, null,
46
- "3. Copy the value for ",
47
- React.createElement(Text, { color: "cyan" }, "attio-session"),
48
- ". That's your \"token\".")),
49
- React.createElement(Box, null,
50
- React.createElement(Text, null,
51
- "4. Create a file in your home directory called",
52
- " ",
53
- React.createElement(Text, { color: "cyan" },
54
- "~/",
55
- configFileName),
56
- ".")),
57
- React.createElement(Box, { flexDirection: "column" },
58
- React.createElement(Text, null,
59
- "5. It should have the following [",
60
- React.createElement(Link, { url: "https://en.wikipedia.org/wiki/INI_file" }, "INI"),
61
- "] format:"),
62
- React.createElement(Box, { marginLeft: 3, borderStyle: "single", width: 60 },
63
- React.createElement(Text, null, stringify(exampleConfig).trim()))),
64
- React.createElement(Box, null,
65
- React.createElement(Text, null, "6. Run this command again.")),
66
- React.createElement(Box, { marginY: 1 },
67
- React.createElement(Text, null, "...")),
68
- React.createElement(Box, null,
69
- React.createElement(Text, null, "N. PROFIT!")))));
@@ -1,69 +0,0 @@
1
- import { Box, Text } from "ink";
2
- import React from "react";
3
- const emojis = {
4
- log: "📝",
5
- info: "💬",
6
- warn: "🔸",
7
- error: "🚨",
8
- };
9
- class GlobalLog {
10
- constructor() {
11
- this._messages = [];
12
- this._listeners = new Map();
13
- this._nextListenerId = 0;
14
- }
15
- notifyListeners() {
16
- this._listeners.forEach((listener) => listener());
17
- }
18
- addMessage(level, messages) {
19
- this._messages.push({
20
- level,
21
- message: messages
22
- .map((message) => typeof message === "string"
23
- ? message
24
- : typeof message === "number"
25
- ? message.toString()
26
- : JSON.stringify(message, null, 2))
27
- .join(" "),
28
- });
29
- this.notifyListeners();
30
- }
31
- log(...messages) {
32
- this.addMessage("log", messages);
33
- }
34
- info(...messages) {
35
- this.addMessage("info", messages);
36
- }
37
- warn(...messages) {
38
- this.addMessage("warn", messages);
39
- }
40
- error(...messages) {
41
- this.addMessage("error", messages);
42
- }
43
- clear() {
44
- this._messages = [];
45
- this.notifyListeners();
46
- }
47
- getMessages() {
48
- return this._messages;
49
- }
50
- listen(listener) {
51
- const id = this._nextListenerId++;
52
- this._listeners.set(id, listener);
53
- return () => this._listeners.delete(id);
54
- }
55
- }
56
- const globalLog = new GlobalLog();
57
- export const log = (...messages) => globalLog.log(...messages);
58
- export const info = (...messages) => globalLog.info(...messages);
59
- export const warn = (...messages) => globalLog.warn(...messages);
60
- export const error = (...messages) => globalLog.error(...messages);
61
- export const Log = () => {
62
- const messages = React.useSyncExternalStore(() => globalLog.listen(() => {
63
- }), () => globalLog.getMessages(), () => []);
64
- if (messages.length === 0)
65
- return null;
66
- return (React.createElement(Box, { flexDirection: "column", paddingY: 1 }, messages.map((message, index) => (React.createElement(Box, { key: index, flexDirection: "row", gap: 1 },
67
- React.createElement(Text, null, emojis[message.level]),
68
- React.createElement(Text, null, message.message))))));
69
- };
@@ -1,10 +0,0 @@
1
- import { Box } from "ink";
2
- import BigText from "ink-big-text";
3
- import Gradient from "ink-gradient";
4
- import React from "react";
5
- import { Disclaimer } from "./Disclaimer.js";
6
- export const Logo = () => (React.createElement(Box, { flexDirection: "column" },
7
- React.createElement(Box, null,
8
- React.createElement(Gradient, { name: "morning" },
9
- React.createElement(BigText, { text: "/. Attio" }))),
10
- React.createElement(Disclaimer, null)));
@@ -1,65 +0,0 @@
1
- import figures from "figures";
2
- import { Box, Text, useStdin } from "ink";
3
- import React from "react";
4
- const ARROW_UP = "\u001B[A";
5
- const ARROW_DOWN = "\u001B[B";
6
- const ENTER = "\r";
7
- const SPACE = " ";
8
- export function MultiSelect({ items, requiredMin = 0, onSubmit, }) {
9
- const [activeIndex, setActiveIndex] = React.useState(0);
10
- const [selectedValues, setSelectedValues] = React.useState(new Set());
11
- const { stdin, setRawMode } = useStdin();
12
- React.useEffect(() => {
13
- setRawMode(true);
14
- return () => setRawMode(false);
15
- }, [setRawMode]);
16
- React.useEffect(() => {
17
- const handleInput = (data) => {
18
- switch (data) {
19
- case ARROW_UP:
20
- case "k":
21
- setActiveIndex((prev) => (prev - 1 + items.length) % items.length);
22
- break;
23
- case ARROW_DOWN:
24
- case "j":
25
- setActiveIndex((prev) => (prev + 1) % items.length);
26
- break;
27
- case SPACE:
28
- setSelectedValues((prev) => {
29
- const newSelectedValues = new Set(prev);
30
- const item = items[activeIndex];
31
- if (newSelectedValues.has(item.value)) {
32
- newSelectedValues.delete(item.value);
33
- }
34
- else {
35
- newSelectedValues.add(item.value);
36
- }
37
- return newSelectedValues;
38
- });
39
- break;
40
- case ENTER:
41
- if (selectedValues.size < requiredMin)
42
- break;
43
- onSubmit(Array.from(selectedValues));
44
- break;
45
- }
46
- };
47
- stdin.on("data", handleInput);
48
- return () => {
49
- stdin.removeListener("data", handleInput);
50
- };
51
- }, [activeIndex, items, onSubmit, requiredMin, selectedValues, stdin]);
52
- return (React.createElement(Box, { flexDirection: "column" }, items.map((item, index) => {
53
- const isHighlighted = index === activeIndex;
54
- const isSelected = selectedValues.has(item.value);
55
- return (React.createElement(Box, { key: item.value },
56
- React.createElement(Text, { color: isSelected ? "yellow" : isHighlighted ? "green" : "white" },
57
- React.createElement(Text, null,
58
- isHighlighted ? figures.pointer : " ",
59
- " "),
60
- React.createElement(Text, { color: isSelected ? "yellow" : undefined },
61
- isSelected ? figures.circleFilled : figures.circle,
62
- " "),
63
- React.createElement(Text, null, item.label))));
64
- })));
65
- }
@@ -1,87 +0,0 @@
1
- import { useSelector } from "@xstate/react";
2
- import { Box, Text, measureElement, useInput } from "ink";
3
- import React from "react";
4
- import { useFullScreen } from "../hooks/useFullScreen.js";
5
- import { useScrollBoxStore } from "./ScrollBox.store.js";
6
- import { calculateChildRange } from "./ScrollBox.util.js";
7
- const GAP = 1;
8
- export const ScrollBox = React.memo(({ padding, ...props }) => {
9
- const { height: screenHeight, width } = useFullScreen();
10
- const [top, setTop] = React.useState(0);
11
- const height = Number(screenHeight) - top;
12
- const availableHeight = height - (props.borderStyle ? 2 : 0) - (padding ?? 0) * 2;
13
- const children = React.useMemo(() => React.Children.toArray(props.children).filter((element) => Boolean(element) && React.isValidElement(element)), [props.children]);
14
- const store = useScrollBoxStore(children.length, availableHeight, Number(width ?? ""));
15
- const boxRef = React.useCallback((element) => setTop(element?.yogaNode?.getComputedTop() ?? 0), []);
16
- const heights = useSelector(store, (state) => state.context.heights);
17
- const offset = useSelector(store, (state) => state.context.offset);
18
- const allMeasured = heights.length === children.length;
19
- const haveOverflow = allMeasured && heights.reduce((a, b) => a + b, 0) > availableHeight;
20
- const childRange = calculateChildRange(heights, offset, availableHeight);
21
- const itemsShown = childRange[1] - childRange[0];
22
- const hiddenAbove = offset;
23
- const hiddenBelow = children.length - (offset + itemsShown);
24
- useInput((input, key) => {
25
- if (input === "j" || key.downArrow) {
26
- if (key.meta) {
27
- store.send({ type: "Page Down" });
28
- }
29
- else {
30
- store.send({ type: "Down" });
31
- }
32
- }
33
- else if (input === "k" || key.upArrow) {
34
- if (key.meta) {
35
- store.send({ type: "Page Up" });
36
- }
37
- else {
38
- store.send({ type: "Up" });
39
- }
40
- }
41
- else if (input === " " || (input === "d" && key.ctrl)) {
42
- store.send({ type: "Page Down" });
43
- }
44
- else if (input === "b" || (input === "u" && key.ctrl)) {
45
- store.send({ type: "Page Up" });
46
- }
47
- else if (input === "G") {
48
- store.send({ type: "Bottom" });
49
- }
50
- });
51
- return (React.createElement(Box, { ...props, height: height, ref: boxRef, flexDirection: "column" },
52
- haveOverflow && (React.createElement(Box, { flexDirection: "column", alignItems: "center", marginBottom: -1 }, hiddenAbove > 0 ? (React.createElement(Text, null,
53
- "+ ",
54
- hiddenAbove,
55
- " item",
56
- hiddenAbove === 1 ? "" : "s",
57
- " ... press \u2191 to scroll",
58
- " ")) : (React.createElement(Text, null, " ")))),
59
- React.createElement(Box, { flexDirection: "column", gap: GAP, flexGrow: 1, padding: padding }, allMeasured
60
- ? children.map((child, index) => index >= childRange[0] && index < childRange[1]
61
- ? React.cloneElement(child, {
62
- ref: (element) => {
63
- const height = element
64
- ? measureElement(element).height + GAP
65
- : 0;
66
- if (!height)
67
- return;
68
- store.send({ type: "Item Measured", index, height });
69
- },
70
- })
71
- : null)
72
- :
73
- React.cloneElement(children[heights.length], {
74
- ref: (element) => {
75
- const height = element ? measureElement(element).height + GAP : 0;
76
- if (!height)
77
- return;
78
- store.send({ type: "Item Measured", index: heights.length, height });
79
- },
80
- })),
81
- haveOverflow && (React.createElement(Box, { flexDirection: "column", alignItems: "center", marginTop: -1 }, hiddenBelow > 0 ? (React.createElement(Text, null,
82
- "+ ",
83
- hiddenBelow,
84
- " item",
85
- hiddenBelow === 1 ? "" : "s",
86
- " ... press \u2193 to scroll")) : (React.createElement(Text, null, " "))))));
87
- });
@@ -1,36 +0,0 @@
1
- import { createStoreWithProducer } from "@xstate/store";
2
- import { produce } from "immer";
3
- import React from "react";
4
- import { calculateChildRange, calculateLastPageOffset, calculatePreviousPageOffset, } from "./ScrollBox.util.js";
5
- const initial = {
6
- offset: 0,
7
- heights: [],
8
- };
9
- export function useScrollBoxStore(numChildren, availableHeight, width) {
10
- return React.useMemo(() => createStoreWithProducer(produce, initial, {
11
- "Down": (context) => {
12
- const [, end] = calculateChildRange(context.heights, context.offset, availableHeight);
13
- if (end < numChildren) {
14
- context.offset = Math.min(context.offset + 1, numChildren - 1);
15
- }
16
- },
17
- "Up": (context) => {
18
- context.offset = Math.max(context.offset - 1, 0);
19
- },
20
- "Page Down": (context) => {
21
- const [, end] = calculateChildRange(context.heights, context.offset, availableHeight);
22
- if (end < numChildren - 1) {
23
- context.offset = end;
24
- }
25
- },
26
- "Page Up": (context) => {
27
- context.offset = calculatePreviousPageOffset(context.heights, context.offset, availableHeight);
28
- },
29
- "Bottom": (context) => {
30
- context.offset = calculateLastPageOffset(context.heights, context.offset, availableHeight);
31
- },
32
- "Item Measured": (context, { index, height }) => {
33
- context.heights[index] = height;
34
- },
35
- }), [availableHeight, numChildren, width]);
36
- }
@@ -1,27 +0,0 @@
1
- export function calculateChildRange(heights, offset, availableHeight) {
2
- let heightUsed = 0;
3
- for (let index = offset; index < heights.length; index++) {
4
- heightUsed += heights[index];
5
- if (heightUsed > availableHeight)
6
- return [offset, Math.max(index, 1)];
7
- }
8
- return [offset, heights.length];
9
- }
10
- export function calculatePreviousPageOffset(heights, offset, availableHeight) {
11
- let heightUsed = 0;
12
- for (let index = offset - 1; index > 0; index--) {
13
- heightUsed += heights[index];
14
- if (heightUsed > availableHeight)
15
- return index + 1;
16
- }
17
- return 0;
18
- }
19
- export function calculateLastPageOffset(heights, offset, availableHeight) {
20
- let heightUsed = 0;
21
- for (let index = heights.length - 1; index > 0; index--) {
22
- heightUsed += heights[index];
23
- if (heightUsed > availableHeight)
24
- return index + 1;
25
- }
26
- return 0;
27
- }
@@ -1,6 +0,0 @@
1
- import { Text } from "ink";
2
- import SelectInput from "ink-select-input";
3
- import React from "react";
4
- export function Select({ initialValue, items, onSelect }) {
5
- return (React.createElement(SelectInput, { items: items.map((item) => ({ ...item, key: item.label })), onSelect: ({ value }) => onSelect(value), initialIndex: initialValue ? items.findIndex((item) => item.value === initialValue) : 0, indicatorComponent: ({ isSelected }) => isSelected ? React.createElement(Text, { color: "green" }, "> ") : React.createElement(Text, null, " "), itemComponent: ({ isSelected, label }) => (React.createElement(Text, { color: isSelected ? "green" : "white" }, label)) }));
6
- }
@@ -1,33 +0,0 @@
1
- import { Box, Text } from "ink";
2
- import React from "react";
3
- export function Table({ rows, }) {
4
- const columns = React.useMemo(() => (rows.length > 0 ? Object.keys(rows[0]) : []), [rows]);
5
- const widths = React.useMemo(() => {
6
- return rows.reduce((acc, row) => {
7
- columns.forEach((column) => {
8
- acc[column] = Math.max(acc[column] ?? 0, row[column].length);
9
- });
10
- return acc;
11
- }, columns.reduce((acc, column) => {
12
- acc[column] = column.length;
13
- return acc;
14
- }, {}));
15
- }, [rows, columns]);
16
- const flexWidths = React.useMemo(() => {
17
- return columns.reduce((acc, column) => {
18
- acc[column] = {
19
- flexDirection: "row",
20
- flexGrow: widths[column],
21
- flexShrink: widths[column],
22
- flexBasis: widths[column],
23
- justifyContent: "center",
24
- };
25
- return acc;
26
- }, {});
27
- }, [columns, widths]);
28
- return (React.createElement(Box, { flexDirection: "column", width: "100%" },
29
- React.createElement(Box, { flexDirection: "row", width: "100%" }, columns.map((column, index) => (React.createElement(Box, { key: index, ...flexWidths[column], borderTop: false, borderLeft: false, borderRight: false, borderStyle: "single" },
30
- React.createElement(Text, { color: "blue" }, column))))),
31
- rows.map((row, rowIndex) => (React.createElement(Box, { key: rowIndex, flexDirection: "row", width: "100%", borderStyle: "single", borderTop: rowIndex > 0, borderLeft: false, borderRight: false, borderBottom: rowIndex === rows.length - 1 }, columns.map((column, columnIndex) => (React.createElement(Box, { key: columnIndex, ...flexWidths[column] },
32
- React.createElement(Text, null, row[column])))))))));
33
- }
@@ -1,38 +0,0 @@
1
- import { Box, Text } from "ink";
2
- import React from "react";
3
- const Error = React.forwardRef(({ error }, ref) => {
4
- return (React.createElement(Box, { flexDirection: "column", ref: ref },
5
- React.createElement(Box, null,
6
- React.createElement(Text, { color: "red" },
7
- React.createElement(Text, { backgroundColor: "red", color: "white" },
8
- " ",
9
- "TYPESCRIPT ERROR",
10
- " "),
11
- " "),
12
- React.createElement(Text, { bold: true }, error.text)),
13
- error.location && (React.createElement(Box, { paddingTop: 1, flexDirection: "column" },
14
- React.createElement(Box, { marginLeft: 4 },
15
- React.createElement(Text, null,
16
- error.location.file,
17
- ":",
18
- error.location.line,
19
- ":",
20
- error.location.character)),
21
- React.createElement(Box, { marginLeft: 4, marginTop: 1 },
22
- React.createElement(Box, { flexDirection: "column", marginRight: 1 },
23
- React.createElement(Text, null, error.location.line)),
24
- React.createElement(Box, { flexDirection: "column" },
25
- React.createElement(Text, null,
26
- "| ",
27
- error.location.lineText.trim()),
28
- React.createElement(Box, null,
29
- React.createElement(Text, null, "|"),
30
- React.createElement(Box, { paddingLeft: error.location.character +
31
- error.location.lineText.trim().length -
32
- error.location.lineText.length +
33
- 1 },
34
- React.createElement(Text, { color: "greenBright" }, "^")))))))));
35
- });
36
- export function renderTypeScriptErrors(errors) {
37
- return errors.map((error, index) => React.createElement(Error, { key: `TypeScriptError-${index}`, error: error }));
38
- }
@@ -1,22 +0,0 @@
1
- import { useStdout } from "ink";
2
- import React from "react";
3
- export const useFullScreen = () => {
4
- const { stdout } = useStdout();
5
- const [columns, setColumns] = React.useState(stdout.columns);
6
- const [rows, setRows] = React.useState(stdout.rows);
7
- React.useEffect(() => {
8
- const handleResize = () => {
9
- setColumns(stdout.columns);
10
- setRows(stdout.rows);
11
- };
12
- stdout.addListener("resize", handleResize);
13
- stdout.write("\x1b[?1049h");
14
- process.on("beforeExit", () => {
15
- stdout.write("\x1b[?1049l");
16
- });
17
- return () => {
18
- stdout.removeListener("resize", handleResize);
19
- };
20
- }, []);
21
- return { width: columns, height: rows };
22
- };
@@ -1,11 +0,0 @@
1
- import React from "react";
2
- export function useTerminalTitle(title) {
3
- React.useEffect(() => {
4
- if (process.platform === "win32") {
5
- process.title = title;
6
- }
7
- else {
8
- process.stdout.write(`\x1B]2;${title}\x1B\x5C`);
9
- }
10
- }, [title]);
11
- }