zinkee 0.1.0

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 (61) hide show
  1. package/AGENTS.md +46 -0
  2. package/README.md +395 -0
  3. package/dist/index.d.ts +13 -0
  4. package/dist/index.js +7142 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +32 -0
  7. package/src/api/automations.ts +403 -0
  8. package/src/api/comments.ts +51 -0
  9. package/src/api/displays.ts +276 -0
  10. package/src/api/files.ts +50 -0
  11. package/src/api/navigation.ts +71 -0
  12. package/src/api/records.ts +167 -0
  13. package/src/api/schemas.ts +130 -0
  14. package/src/api/teamspace.ts +110 -0
  15. package/src/cli-examples.ts +175 -0
  16. package/src/cli-runner.ts +73 -0
  17. package/src/client.test.ts +128 -0
  18. package/src/client.ts +243 -0
  19. package/src/command-registry.ts +749 -0
  20. package/src/commands/automations.test.ts +728 -0
  21. package/src/commands/automations.ts +2013 -0
  22. package/src/commands/comments.test.ts +214 -0
  23. package/src/commands/comments.ts +303 -0
  24. package/src/commands/config.test.ts +81 -0
  25. package/src/commands/config.ts +150 -0
  26. package/src/commands/displays.test.ts +266 -0
  27. package/src/commands/displays.ts +755 -0
  28. package/src/commands/files.test.ts +284 -0
  29. package/src/commands/files.ts +280 -0
  30. package/src/commands/navigation.test.ts +214 -0
  31. package/src/commands/navigation.ts +348 -0
  32. package/src/commands/profiles.test.ts +82 -0
  33. package/src/commands/profiles.ts +281 -0
  34. package/src/commands/records.test.ts +367 -0
  35. package/src/commands/records.ts +726 -0
  36. package/src/commands/schemas.test.ts +748 -0
  37. package/src/commands/schemas.ts +746 -0
  38. package/src/commands/teamspace.test.ts +229 -0
  39. package/src/commands/teamspace.ts +540 -0
  40. package/src/config.test.ts +165 -0
  41. package/src/config.ts +248 -0
  42. package/src/index.test.ts +140 -0
  43. package/src/index.ts +8 -0
  44. package/src/parsers/expressions.test.ts +50 -0
  45. package/src/parsers/expressions.ts +111 -0
  46. package/src/parsers/kv.test.ts +35 -0
  47. package/src/parsers/kv.ts +49 -0
  48. package/src/parsers/selectors.test.ts +23 -0
  49. package/src/parsers/selectors.ts +29 -0
  50. package/src/program.ts +56 -0
  51. package/src/runtime-context.ts +18 -0
  52. package/src/types.ts +71 -0
  53. package/src/utils/errors.test.ts +48 -0
  54. package/src/utils/errors.ts +183 -0
  55. package/src/utils/examples.test.ts +67 -0
  56. package/src/utils/examples.ts +855 -0
  57. package/src/utils/output.test.ts +39 -0
  58. package/src/utils/output.ts +124 -0
  59. package/src/utils/schema-fields.ts +529 -0
  60. package/tsconfig.json +20 -0
  61. package/tsup.config.ts +13 -0
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "zinkee",
3
+ "version": "0.1.0",
4
+ "description": "CLI for Zinkee API v2",
5
+ "type": "module",
6
+ "bin": {
7
+ "zinkee": "dist/index.js"
8
+ },
9
+ "engines": {
10
+ "node": ">=20"
11
+ },
12
+ "scripts": {
13
+ "build": "tsup",
14
+ "dev": "tsx src/index.ts",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest",
17
+ "typecheck": "tsc --noEmit"
18
+ },
19
+ "dependencies": {
20
+ "chalk": "^5.6.2",
21
+ "cli-table3": "^0.6.5",
22
+ "commander": "^14.0.3",
23
+ "confbox": "^0.1.8"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^24.5.2",
27
+ "tsup": "^8.5.1",
28
+ "tsx": "^4.20.5",
29
+ "typescript": "^5.9.3",
30
+ "vitest": "^4.1.0"
31
+ }
32
+ }
@@ -0,0 +1,403 @@
1
+ import { ApiClient } from "../client.js";
2
+ import type { NormalizedUuidOrSlug } from "../parsers/selectors.js";
3
+ import type { JsonObject, JsonValue } from "../types.js";
4
+
5
+ export interface ApiAutomationFolder {
6
+ [key: string]: unknown;
7
+ id?: string;
8
+ name?: string;
9
+ automationCount?: number;
10
+ }
11
+
12
+ export interface ApiAutomation {
13
+ [key: string]: unknown;
14
+ id?: string;
15
+ name?: string;
16
+ description?: string;
17
+ status?: string;
18
+ folderId?: string;
19
+ trigger?: ApiAutomationTrigger;
20
+ actions?: ApiAutomationAction[];
21
+ }
22
+
23
+ export interface ApiAutomationTrigger {
24
+ [key: string]: unknown;
25
+ type?: string;
26
+ config?: JsonObject;
27
+ }
28
+
29
+ export interface ApiAutomationAction {
30
+ [key: string]: unknown;
31
+ id?: string;
32
+ name?: string;
33
+ type?: string;
34
+ config?: JsonObject;
35
+ }
36
+
37
+ export interface ApiAutomationPlugin {
38
+ [key: string]: unknown;
39
+ id?: string;
40
+ name?: string;
41
+ version?: string;
42
+ }
43
+
44
+ export interface ApiAutomationConnection {
45
+ [key: string]: unknown;
46
+ id?: string;
47
+ name?: string;
48
+ type?: string;
49
+ scope?: string;
50
+ active?: boolean;
51
+ }
52
+
53
+ export interface ListAutomationsQuery {
54
+ folderId?: string;
55
+ status?: string;
56
+ triggerType?: string;
57
+ actionType?: string;
58
+ pluginId?: string;
59
+ search?: string;
60
+ }
61
+
62
+ export interface MoveAutomationInput {
63
+ automationId: string;
64
+ targetFolderId: string;
65
+ }
66
+
67
+ export interface CreateAutomationInput {
68
+ [key: string]: unknown;
69
+ name: string;
70
+ description?: string;
71
+ folderId?: string;
72
+ trigger?: ApiAutomationTrigger;
73
+ }
74
+
75
+ export interface UpdateAutomationInput {
76
+ [key: string]: unknown;
77
+ name?: string;
78
+ description?: string;
79
+ folderId?: string;
80
+ }
81
+
82
+ export interface SetAutomationTriggerInput {
83
+ [key: string]: unknown;
84
+ type?: string;
85
+ config?: JsonObject;
86
+ }
87
+
88
+ export interface MutationAutomationActionInput {
89
+ [key: string]: unknown;
90
+ type?: string;
91
+ name?: string;
92
+ config?: JsonObject;
93
+ }
94
+
95
+ export interface SetAutomationFlowInput {
96
+ [key: string]: unknown;
97
+ entryActionIds?: string[];
98
+ transitions?: Array<{ from: string; to: string }>;
99
+ }
100
+
101
+ export interface SetAutomationWebhookInput {
102
+ [key: string]: unknown;
103
+ active?: boolean;
104
+ idempotencyKeyPath?: string;
105
+ eventTypePath?: string;
106
+ allowedEventTypes?: string[];
107
+ fieldMappings?: JsonValue[];
108
+ }
109
+
110
+ export interface CreateAutomationConnectionInput {
111
+ [key: string]: unknown;
112
+ name: string;
113
+ type: string;
114
+ scope: string;
115
+ ownerMemberId?: string;
116
+ config?: JsonObject;
117
+ secret?: Record<string, string>;
118
+ active?: boolean;
119
+ }
120
+
121
+ export interface UpdateAutomationConnectionInput {
122
+ [key: string]: unknown;
123
+ set?: Record<string, unknown>;
124
+ unset?: string[];
125
+ }
126
+
127
+ function jsonOptions(body: unknown, method: string): RequestInit {
128
+ return {
129
+ method,
130
+ headers: {
131
+ "content-type": "application/json",
132
+ },
133
+ body: JSON.stringify(body),
134
+ };
135
+ }
136
+
137
+ function selectorValue(selector: NormalizedUuidOrSlug): string {
138
+ return encodeURIComponent(selector.value);
139
+ }
140
+
141
+ function segment(value: string): string {
142
+ return encodeURIComponent(value);
143
+ }
144
+
145
+ function appendQuery(path: string, query: URLSearchParams): string {
146
+ const queryString = query.toString();
147
+ return queryString.length > 0 ? `${path}?${queryString}` : path;
148
+ }
149
+
150
+ export class AutomationsApi {
151
+ constructor(private readonly client: ApiClient) {}
152
+
153
+ listFolders(): Promise<ApiAutomationFolder[]> {
154
+ return this.client.getJson<ApiAutomationFolder[]>("/api/v2/automation-folders");
155
+ }
156
+
157
+ createFolder(body: Record<string, unknown>): Promise<ApiAutomationFolder> {
158
+ return this.client.requestJson<ApiAutomationFolder>(
159
+ "/api/v2/automation-folders",
160
+ jsonOptions(body, "POST"),
161
+ );
162
+ }
163
+
164
+ updateFolder(
165
+ folder: NormalizedUuidOrSlug,
166
+ body: Record<string, unknown>,
167
+ ): Promise<ApiAutomationFolder> {
168
+ return this.client.requestJson<ApiAutomationFolder>(
169
+ `/api/v2/automation-folders/${selectorValue(folder)}`,
170
+ jsonOptions(body, "PATCH"),
171
+ );
172
+ }
173
+
174
+ deleteFolder(folder: NormalizedUuidOrSlug): Promise<Record<string, unknown>> {
175
+ return this.client.requestJson<Record<string, unknown>>(
176
+ `/api/v2/automation-folders/${selectorValue(folder)}`,
177
+ { method: "DELETE" },
178
+ );
179
+ }
180
+
181
+ moveAutomation(input: MoveAutomationInput): Promise<Record<string, unknown>> {
182
+ return this.client.requestJson<Record<string, unknown>>(
183
+ `/api/v2/automation-folders/${segment(input.targetFolderId)}/automations:move`,
184
+ jsonOptions(input, "POST"),
185
+ );
186
+ }
187
+
188
+ listAutomations(query: ListAutomationsQuery = {}): Promise<ApiAutomation[]> {
189
+ const params = new URLSearchParams();
190
+
191
+ if (query.folderId) {
192
+ params.set("folderId", query.folderId);
193
+ }
194
+
195
+ if (query.status) {
196
+ params.set("status", query.status);
197
+ }
198
+
199
+ if (query.triggerType) {
200
+ params.set("triggerType", query.triggerType);
201
+ }
202
+
203
+ if (query.actionType) {
204
+ params.set("actionType", query.actionType);
205
+ }
206
+
207
+ if (query.pluginId) {
208
+ params.set("pluginId", query.pluginId);
209
+ }
210
+
211
+ if (query.search) {
212
+ params.set("search", query.search);
213
+ }
214
+
215
+ return this.client.getJson<ApiAutomation[]>(
216
+ appendQuery("/api/v2/automations", params),
217
+ );
218
+ }
219
+
220
+ getAutomation(automation: NormalizedUuidOrSlug): Promise<ApiAutomation> {
221
+ return this.client.getJson<ApiAutomation>(
222
+ `/api/v2/automations/${selectorValue(automation)}`,
223
+ );
224
+ }
225
+
226
+ createAutomation(input: CreateAutomationInput): Promise<ApiAutomation> {
227
+ return this.client.requestJson<ApiAutomation>(
228
+ "/api/v2/automations",
229
+ jsonOptions(input, "POST"),
230
+ );
231
+ }
232
+
233
+ updateAutomation(
234
+ automation: NormalizedUuidOrSlug,
235
+ input: UpdateAutomationInput,
236
+ ): Promise<ApiAutomation> {
237
+ return this.client.requestJson<ApiAutomation>(
238
+ `/api/v2/automations/${selectorValue(automation)}`,
239
+ jsonOptions(input, "PATCH"),
240
+ );
241
+ }
242
+
243
+ deleteAutomation(automation: NormalizedUuidOrSlug): Promise<Record<string, unknown>> {
244
+ return this.client.requestJson<Record<string, unknown>>(
245
+ `/api/v2/automations/${selectorValue(automation)}`,
246
+ { method: "DELETE" },
247
+ );
248
+ }
249
+
250
+ activateAutomation(automation: NormalizedUuidOrSlug): Promise<Record<string, unknown>> {
251
+ return this.client.requestJson<Record<string, unknown>>(
252
+ `/api/v2/automations/${selectorValue(automation)}:activate`,
253
+ { method: "POST" },
254
+ );
255
+ }
256
+
257
+ deactivateAutomation(automation: NormalizedUuidOrSlug): Promise<Record<string, unknown>> {
258
+ return this.client.requestJson<Record<string, unknown>>(
259
+ `/api/v2/automations/${selectorValue(automation)}:deactivate`,
260
+ { method: "POST" },
261
+ );
262
+ }
263
+
264
+ getTrigger(automation: NormalizedUuidOrSlug): Promise<ApiAutomationTrigger> {
265
+ return this.client.getJson<ApiAutomationTrigger>(
266
+ `/api/v2/automations/${selectorValue(automation)}/trigger`,
267
+ );
268
+ }
269
+
270
+ setTrigger(
271
+ automation: NormalizedUuidOrSlug,
272
+ input: SetAutomationTriggerInput,
273
+ ): Promise<ApiAutomationTrigger> {
274
+ return this.client.requestJson<ApiAutomationTrigger>(
275
+ `/api/v2/automations/${selectorValue(automation)}/trigger`,
276
+ jsonOptions(input, "PUT"),
277
+ );
278
+ }
279
+
280
+ listActions(automation: NormalizedUuidOrSlug): Promise<ApiAutomationAction[]> {
281
+ return this.client.getJson<ApiAutomationAction[]>(
282
+ `/api/v2/automations/${selectorValue(automation)}/actions`,
283
+ );
284
+ }
285
+
286
+ addAction(
287
+ automation: NormalizedUuidOrSlug,
288
+ input: MutationAutomationActionInput,
289
+ ): Promise<ApiAutomationAction> {
290
+ return this.client.requestJson<ApiAutomationAction>(
291
+ `/api/v2/automations/${selectorValue(automation)}/actions`,
292
+ jsonOptions(input, "POST"),
293
+ );
294
+ }
295
+
296
+ updateAction(
297
+ automation: NormalizedUuidOrSlug,
298
+ actionId: string,
299
+ input: MutationAutomationActionInput,
300
+ ): Promise<ApiAutomationAction> {
301
+ return this.client.requestJson<ApiAutomationAction>(
302
+ `/api/v2/automations/${selectorValue(automation)}/actions/${segment(actionId)}`,
303
+ jsonOptions(input, "PATCH"),
304
+ );
305
+ }
306
+
307
+ deleteAction(
308
+ automation: NormalizedUuidOrSlug,
309
+ actionId: string,
310
+ ): Promise<Record<string, unknown>> {
311
+ return this.client.requestJson<Record<string, unknown>>(
312
+ `/api/v2/automations/${selectorValue(automation)}/actions/${segment(actionId)}`,
313
+ { method: "DELETE" },
314
+ );
315
+ }
316
+
317
+ getFlow(automation: NormalizedUuidOrSlug): Promise<Record<string, unknown>> {
318
+ return this.client.getJson<Record<string, unknown>>(
319
+ `/api/v2/automations/${selectorValue(automation)}/flow`,
320
+ );
321
+ }
322
+
323
+ setFlow(
324
+ automation: NormalizedUuidOrSlug,
325
+ input: SetAutomationFlowInput,
326
+ ): Promise<Record<string, unknown>> {
327
+ return this.client.requestJson<Record<string, unknown>>(
328
+ `/api/v2/automations/${selectorValue(automation)}/flow`,
329
+ jsonOptions(input, "PUT"),
330
+ );
331
+ }
332
+
333
+ getWebhook(automation: NormalizedUuidOrSlug): Promise<Record<string, unknown>> {
334
+ return this.client.getJson<Record<string, unknown>>(
335
+ `/api/v2/automations/${selectorValue(automation)}/webhook-endpoint`,
336
+ );
337
+ }
338
+
339
+ setWebhook(
340
+ automation: NormalizedUuidOrSlug,
341
+ input: SetAutomationWebhookInput,
342
+ ): Promise<Record<string, unknown>> {
343
+ return this.client.requestJson<Record<string, unknown>>(
344
+ `/api/v2/automations/${selectorValue(automation)}/webhook-endpoint`,
345
+ jsonOptions(input, "PUT"),
346
+ );
347
+ }
348
+
349
+ deleteWebhook(automation: NormalizedUuidOrSlug): Promise<Record<string, unknown>> {
350
+ return this.client.requestJson<Record<string, unknown>>(
351
+ `/api/v2/automations/${selectorValue(automation)}/webhook-endpoint`,
352
+ { method: "DELETE" },
353
+ );
354
+ }
355
+
356
+ listPlugins(): Promise<ApiAutomationPlugin[]> {
357
+ return this.client.getJson<ApiAutomationPlugin[]>("/api/v2/automation-plugins");
358
+ }
359
+
360
+ getPlugin(pluginId: string): Promise<ApiAutomationPlugin> {
361
+ return this.client.getJson<ApiAutomationPlugin>(
362
+ `/api/v2/automation-plugins/${segment(pluginId)}`,
363
+ );
364
+ }
365
+
366
+ listConnections(): Promise<ApiAutomationConnection[]> {
367
+ return this.client.getJson<ApiAutomationConnection[]>(
368
+ "/api/v2/automation-connections",
369
+ );
370
+ }
371
+
372
+ getConnection(connection: NormalizedUuidOrSlug): Promise<ApiAutomationConnection> {
373
+ return this.client.getJson<ApiAutomationConnection>(
374
+ `/api/v2/automation-connections/${selectorValue(connection)}`,
375
+ );
376
+ }
377
+
378
+ createConnection(
379
+ input: CreateAutomationConnectionInput,
380
+ ): Promise<ApiAutomationConnection> {
381
+ return this.client.requestJson<ApiAutomationConnection>(
382
+ "/api/v2/automation-connections",
383
+ jsonOptions(input, "POST"),
384
+ );
385
+ }
386
+
387
+ updateConnection(
388
+ connection: NormalizedUuidOrSlug,
389
+ input: UpdateAutomationConnectionInput,
390
+ ): Promise<ApiAutomationConnection> {
391
+ return this.client.requestJson<ApiAutomationConnection>(
392
+ `/api/v2/automation-connections/${selectorValue(connection)}`,
393
+ jsonOptions(input, "PATCH"),
394
+ );
395
+ }
396
+
397
+ deleteConnection(connection: NormalizedUuidOrSlug): Promise<Record<string, unknown>> {
398
+ return this.client.requestJson<Record<string, unknown>>(
399
+ `/api/v2/automation-connections/${selectorValue(connection)}`,
400
+ { method: "DELETE" },
401
+ );
402
+ }
403
+ }
@@ -0,0 +1,51 @@
1
+ import { ApiClient } from "../client.js";
2
+ import type { NormalizedUuidOrSlug } from "../parsers/selectors.js";
3
+
4
+ export interface ApiComment {
5
+ [key: string]: unknown;
6
+ id?: string;
7
+ text?: string;
8
+ }
9
+
10
+ export interface CreateCommentInput {
11
+ [key: string]: unknown;
12
+ text?: string;
13
+ }
14
+
15
+ function jsonOptions(body: unknown, method: string): RequestInit {
16
+ return {
17
+ method,
18
+ headers: {
19
+ "content-type": "application/json",
20
+ },
21
+ body: JSON.stringify(body),
22
+ };
23
+ }
24
+
25
+ function selectorValue(selector: NormalizedUuidOrSlug): string {
26
+ return selector.value;
27
+ }
28
+
29
+ export class CommentsApi {
30
+ constructor(private readonly client: ApiClient) {}
31
+
32
+ listComments(
33
+ schema: NormalizedUuidOrSlug,
34
+ recordId: string,
35
+ ): Promise<ApiComment[]> {
36
+ return this.client.getJson<ApiComment[]>(
37
+ `/api/v2/schemas/${selectorValue(schema)}/records/${recordId}/comments`,
38
+ );
39
+ }
40
+
41
+ createComment(
42
+ schema: NormalizedUuidOrSlug,
43
+ recordId: string,
44
+ input: CreateCommentInput,
45
+ ): Promise<ApiComment> {
46
+ return this.client.requestJson<ApiComment>(
47
+ `/api/v2/schemas/${selectorValue(schema)}/records/${recordId}/comments`,
48
+ jsonOptions(input, "POST"),
49
+ );
50
+ }
51
+ }