@project-ajax/sdk 0.0.28

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 (145) hide show
  1. package/README.md +22 -0
  2. package/dist/block.d.ts +321 -0
  3. package/dist/block.d.ts.map +1 -0
  4. package/dist/block.js +0 -0
  5. package/dist/builder.d.ts +12 -0
  6. package/dist/builder.d.ts.map +1 -0
  7. package/dist/builder.js +22 -0
  8. package/dist/capabilities/slashCommand.d.ts +56 -0
  9. package/dist/capabilities/slashCommand.d.ts.map +1 -0
  10. package/dist/capabilities/slashCommand.js +32 -0
  11. package/dist/capabilities/sync.d.ts +58 -0
  12. package/dist/capabilities/sync.d.ts.map +1 -0
  13. package/dist/capabilities/sync.js +26 -0
  14. package/dist/capabilities/tool.d.ts +69 -0
  15. package/dist/capabilities/tool.d.ts.map +1 -0
  16. package/dist/capabilities/tool.js +75 -0
  17. package/dist/capabilities/tool.test.d.ts +2 -0
  18. package/dist/capabilities/tool.test.d.ts.map +1 -0
  19. package/dist/cli/api/client.d.ts +185 -0
  20. package/dist/cli/api/client.d.ts.map +1 -0
  21. package/dist/cli/api/client.js +315 -0
  22. package/dist/cli/api/result.d.ts +43 -0
  23. package/dist/cli/api/result.d.ts.map +1 -0
  24. package/dist/cli/api/result.js +43 -0
  25. package/dist/cli/bin/cli.d.ts +3 -0
  26. package/dist/cli/bin/cli.d.ts.map +1 -0
  27. package/dist/cli/bin/cli.js +5 -0
  28. package/dist/cli/commands/auth.d.ts +2 -0
  29. package/dist/cli/commands/auth.d.ts.map +1 -0
  30. package/dist/cli/commands/auth.impl.d.ts +10 -0
  31. package/dist/cli/commands/auth.impl.d.ts.map +1 -0
  32. package/dist/cli/commands/auth.impl.js +68 -0
  33. package/dist/cli/commands/auth.js +71 -0
  34. package/dist/cli/commands/bundle.d.ts +2 -0
  35. package/dist/cli/commands/bundle.d.ts.map +1 -0
  36. package/dist/cli/commands/bundle.impl.d.ts +2 -0
  37. package/dist/cli/commands/bundle.impl.d.ts.map +1 -0
  38. package/dist/cli/commands/bundle.impl.js +21 -0
  39. package/dist/cli/commands/bundle.js +23 -0
  40. package/dist/cli/commands/capabilities.d.ts +2 -0
  41. package/dist/cli/commands/capabilities.d.ts.map +1 -0
  42. package/dist/cli/commands/capabilities.impl.d.ts +3 -0
  43. package/dist/cli/commands/capabilities.impl.d.ts.map +1 -0
  44. package/dist/cli/commands/capabilities.impl.js +40 -0
  45. package/dist/cli/commands/capabilities.js +24 -0
  46. package/dist/cli/commands/deploy.d.ts +3 -0
  47. package/dist/cli/commands/deploy.d.ts.map +1 -0
  48. package/dist/cli/commands/deploy.impl.d.ts +2 -0
  49. package/dist/cli/commands/deploy.impl.d.ts.map +1 -0
  50. package/dist/cli/commands/deploy.impl.js +31 -0
  51. package/dist/cli/commands/deploy.js +16 -0
  52. package/dist/cli/commands/exec.d.ts +3 -0
  53. package/dist/cli/commands/exec.d.ts.map +1 -0
  54. package/dist/cli/commands/exec.impl.d.ts +7 -0
  55. package/dist/cli/commands/exec.impl.d.ts.map +1 -0
  56. package/dist/cli/commands/exec.impl.js +122 -0
  57. package/dist/cli/commands/exec.js +30 -0
  58. package/dist/cli/commands/runs.d.ts +2 -0
  59. package/dist/cli/commands/runs.d.ts.map +1 -0
  60. package/dist/cli/commands/runs.impl.d.ts +4 -0
  61. package/dist/cli/commands/runs.impl.d.ts.map +1 -0
  62. package/dist/cli/commands/runs.impl.js +71 -0
  63. package/dist/cli/commands/runs.js +45 -0
  64. package/dist/cli/commands/secrets.d.ts +2 -0
  65. package/dist/cli/commands/secrets.d.ts.map +1 -0
  66. package/dist/cli/commands/secrets.impl.d.ts +5 -0
  67. package/dist/cli/commands/secrets.impl.d.ts.map +1 -0
  68. package/dist/cli/commands/secrets.impl.js +93 -0
  69. package/dist/cli/commands/secrets.js +64 -0
  70. package/dist/cli/config.d.ts +38 -0
  71. package/dist/cli/config.d.ts.map +1 -0
  72. package/dist/cli/config.js +133 -0
  73. package/dist/cli/context.d.ts +15 -0
  74. package/dist/cli/context.d.ts.map +1 -0
  75. package/dist/cli/context.js +16 -0
  76. package/dist/cli/deploy.d.ts +25 -0
  77. package/dist/cli/deploy.d.ts.map +1 -0
  78. package/dist/cli/deploy.js +101 -0
  79. package/dist/cli/flags.d.ts +16 -0
  80. package/dist/cli/flags.d.ts.map +1 -0
  81. package/dist/cli/flags.js +24 -0
  82. package/dist/cli/handler.d.ts +14 -0
  83. package/dist/cli/handler.d.ts.map +1 -0
  84. package/dist/cli/handler.js +30 -0
  85. package/dist/cli/routes.d.ts +2 -0
  86. package/dist/cli/routes.d.ts.map +1 -0
  87. package/dist/cli/routes.js +44 -0
  88. package/dist/cli/utils/array.d.ts +2 -0
  89. package/dist/cli/utils/array.d.ts.map +1 -0
  90. package/dist/cli/utils/array.js +10 -0
  91. package/dist/cli/utils/string.d.ts +2 -0
  92. package/dist/cli/utils/string.d.ts.map +1 -0
  93. package/dist/cli/utils/string.js +12 -0
  94. package/dist/cli/writer.d.ts +48 -0
  95. package/dist/cli/writer.d.ts.map +1 -0
  96. package/dist/cli/writer.js +73 -0
  97. package/dist/error.d.ts +8 -0
  98. package/dist/error.d.ts.map +1 -0
  99. package/dist/error.js +11 -0
  100. package/dist/index.d.ts +4 -0
  101. package/dist/index.d.ts.map +1 -0
  102. package/dist/index.js +8 -0
  103. package/dist/schema.d.ts +45 -0
  104. package/dist/schema.d.ts.map +1 -0
  105. package/dist/schema.js +14 -0
  106. package/dist/types.d.ts +11 -0
  107. package/dist/types.d.ts.map +1 -0
  108. package/dist/types.js +0 -0
  109. package/package.json +79 -0
  110. package/src/block.ts +529 -0
  111. package/src/builder.ts +26 -0
  112. package/src/capabilities/slashCommand.ts +71 -0
  113. package/src/capabilities/sync.ts +76 -0
  114. package/src/capabilities/tool.test.ts +181 -0
  115. package/src/capabilities/tool.ts +145 -0
  116. package/src/cli/api/client.ts +588 -0
  117. package/src/cli/api/result.ts +71 -0
  118. package/src/cli/bin/cli.ts +7 -0
  119. package/src/cli/commands/auth.impl.ts +92 -0
  120. package/src/cli/commands/auth.ts +77 -0
  121. package/src/cli/commands/bundle.impl.ts +21 -0
  122. package/src/cli/commands/bundle.ts +23 -0
  123. package/src/cli/commands/capabilities.impl.ts +47 -0
  124. package/src/cli/commands/capabilities.ts +25 -0
  125. package/src/cli/commands/deploy.impl.ts +34 -0
  126. package/src/cli/commands/deploy.ts +16 -0
  127. package/src/cli/commands/exec.impl.ts +169 -0
  128. package/src/cli/commands/exec.ts +32 -0
  129. package/src/cli/commands/runs.impl.ts +87 -0
  130. package/src/cli/commands/runs.ts +49 -0
  131. package/src/cli/commands/secrets.impl.ts +124 -0
  132. package/src/cli/commands/secrets.ts +73 -0
  133. package/src/cli/config.ts +175 -0
  134. package/src/cli/context.ts +26 -0
  135. package/src/cli/deploy.ts +175 -0
  136. package/src/cli/flags.ts +43 -0
  137. package/src/cli/handler.ts +62 -0
  138. package/src/cli/routes.ts +43 -0
  139. package/src/cli/utils/array.ts +7 -0
  140. package/src/cli/utils/string.ts +9 -0
  141. package/src/cli/writer.ts +97 -0
  142. package/src/error.ts +12 -0
  143. package/src/index.ts +3 -0
  144. package/src/schema.ts +54 -0
  145. package/src/types.ts +10 -0
@@ -0,0 +1,588 @@
1
+ /**
2
+ * API client for making authenticated requests to the Workers API
3
+ */
4
+
5
+ import type { Writer } from "../writer.js";
6
+ import { Result } from "./result.js";
7
+
8
+ export type Environment = "local" | "staging" | "dev" | "prod";
9
+
10
+ interface ApiClientConfig {
11
+ token: string;
12
+ environment: Environment;
13
+ baseUrl?: string | undefined;
14
+ cellId: string;
15
+ writer: Writer;
16
+ }
17
+
18
+ type Endpoint = `/${string}`;
19
+
20
+ export interface ApiError {
21
+ status: number;
22
+ statusText: string;
23
+ message: string;
24
+ validationError?: {
25
+ errorId: string;
26
+ name: string;
27
+ debugMessage: string;
28
+ message: string;
29
+ };
30
+ }
31
+
32
+ /**
33
+ * Get the base URL for the given environment
34
+ */
35
+ export function baseUrl({
36
+ environment,
37
+ override,
38
+ }: {
39
+ environment: Environment;
40
+ override?: string | undefined;
41
+ }): string {
42
+ if (override) {
43
+ return override;
44
+ }
45
+
46
+ switch (environment) {
47
+ case "local":
48
+ return "http://localhost:3000";
49
+ case "staging":
50
+ return "https://staging.notion.so";
51
+ case "dev":
52
+ return "https://dev.notion.so";
53
+ case "prod":
54
+ return "https://www.notion.so";
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Get the base API URL for the given environment
60
+ */
61
+ function baseApiUrl({
62
+ environment,
63
+ override,
64
+ }: {
65
+ environment: Environment;
66
+ override?: string | undefined;
67
+ }): string {
68
+ return `${baseUrl({ environment, override })}/api/v3`;
69
+ }
70
+
71
+ /**
72
+ * API client for making authenticated requests to Workers endpoints
73
+ */
74
+ export class ApiClient {
75
+ readonly #token: string;
76
+ readonly #env: Environment;
77
+ readonly #baseUrl: string | undefined;
78
+ readonly #cellId: string;
79
+ readonly #writer: Writer;
80
+
81
+ constructor(config: ApiClientConfig) {
82
+ this.#token = config.token;
83
+ this.#env = config.environment;
84
+ this.#baseUrl = config.baseUrl;
85
+ this.#cellId = config.cellId;
86
+ this.#writer = config.writer;
87
+ }
88
+
89
+ private baseApiUrl() {
90
+ return baseApiUrl({ environment: this.#env, override: this.#baseUrl });
91
+ }
92
+
93
+ /**
94
+ * Make an authenticated fetch request to the Workers API
95
+ */
96
+ private async fetch(
97
+ endpoint: Endpoint,
98
+ requestOptions: Omit<RequestInit, "body"> & { body?: unknown },
99
+ options: { stream: true },
100
+ ): Promise<Result<ReadableStream<Uint8Array<ArrayBufferLike>>, ApiError>>;
101
+ private async fetch<TResponse>(
102
+ endpoint: Endpoint,
103
+ requestOptions?: Omit<RequestInit, "body"> & { body?: unknown },
104
+ ): Promise<Result<TResponse, ApiError>>;
105
+ private async fetch<TResponse>(
106
+ endpoint: Endpoint,
107
+ requestOptions: Omit<RequestInit, "body"> & { body?: unknown } = {},
108
+ options?: { stream: true },
109
+ ): Promise<
110
+ Result<TResponse | ReadableStream<Uint8Array<ArrayBufferLike>>, ApiError>
111
+ > {
112
+ if (!endpoint.startsWith("/")) {
113
+ throw new Error("Endpoint must start with a slash (/)");
114
+ }
115
+
116
+ const url = `${this.baseApiUrl()}${endpoint}`;
117
+
118
+ this.#writer.debug(`Fetching ${url}`);
119
+ this.#writer.debug(
120
+ `Options: ${JSON.stringify(requestOptions, null, "\t")}`,
121
+ );
122
+
123
+ const headers = new Headers({
124
+ Authorization: `Bearer ${this.#token}`,
125
+ "Content-Type": "application/json",
126
+ "X-Notion-Cell": this.#cellId,
127
+ });
128
+
129
+ const addlHeaders = headersInitToEntries(requestOptions.headers);
130
+
131
+ for (const [key, value] of addlHeaders) {
132
+ headers.append(key, value);
133
+ }
134
+
135
+ const response = await fetch(url, {
136
+ method: requestOptions.method ?? "GET",
137
+ headers,
138
+ body: requestOptions.body ? JSON.stringify(requestOptions.body) : null,
139
+ });
140
+
141
+ this.#writer.debug(`Response: ${response.status} ${response.statusText}`);
142
+
143
+ if (!response.ok) {
144
+ const error = await parseApiError(response);
145
+ return Result.fail(error);
146
+ }
147
+
148
+ if (options?.stream) {
149
+ if (!response.body) {
150
+ return Result.fail({
151
+ status: response.status,
152
+ statusText: response.statusText,
153
+ message: "No body in response",
154
+ });
155
+ }
156
+
157
+ return Result.success(response.body);
158
+ } else {
159
+ const data = (await response.json()) as TResponse;
160
+ return Result.success(data);
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Create a new worker
166
+ */
167
+ async createWorker(name: string): Promise<
168
+ Result<
169
+ {
170
+ worker: {
171
+ workerId: string;
172
+ name: string;
173
+ spaceId: string;
174
+ createdAt: string;
175
+ updatedAt: string;
176
+ state: unknown;
177
+ };
178
+ url: string;
179
+ fields: Record<string, string>;
180
+ },
181
+ ApiError
182
+ >
183
+ > {
184
+ return this.fetch("/workersCreateWorker", {
185
+ method: "POST",
186
+ body: {
187
+ name,
188
+ },
189
+ });
190
+ }
191
+
192
+ /**
193
+ * Update an existing worker's bundle
194
+ */
195
+ async updateWorkerBundle(workerId: string): Promise<
196
+ Result<
197
+ {
198
+ url: string;
199
+ fields: Record<string, string>;
200
+ },
201
+ ApiError
202
+ >
203
+ > {
204
+ return this.fetch("/workersUpdateWorker", {
205
+ method: "POST",
206
+ body: {
207
+ workerId,
208
+ },
209
+ });
210
+ }
211
+
212
+ /**
213
+ * Get a worker by ID
214
+ */
215
+ async getWorker(workerId: string): Promise<
216
+ Result<
217
+ {
218
+ worker: {
219
+ workerId: string;
220
+ name: string;
221
+ spaceId: string;
222
+ state: unknown;
223
+ tools: unknown[];
224
+ createdAt: string;
225
+ updatedAt: string;
226
+ };
227
+ },
228
+ ApiError
229
+ >
230
+ > {
231
+ return this.fetch("/workersGetWorker", {
232
+ method: "POST",
233
+ body: {
234
+ workerId,
235
+ },
236
+ });
237
+ }
238
+
239
+ /**
240
+ * List all workers in the space
241
+ */
242
+ async listWorkers(): Promise<
243
+ Result<
244
+ {
245
+ workers: Array<{
246
+ workerId: string;
247
+ name: string;
248
+ spaceId: string;
249
+ state: unknown;
250
+ createdAt: string;
251
+ updatedAt: string;
252
+ }>;
253
+ },
254
+ ApiError
255
+ >
256
+ > {
257
+ return this.fetch("/workersListWorkers", {
258
+ method: "POST",
259
+ body: {},
260
+ });
261
+ }
262
+
263
+ /**
264
+ * Delete a worker
265
+ */
266
+ async deleteWorker(
267
+ workerId: string,
268
+ ): Promise<Result<Record<string, never>, ApiError>> {
269
+ return this.fetch("/workersDeleteWorker", {
270
+ method: "POST",
271
+ body: {
272
+ workerId,
273
+ },
274
+ });
275
+ }
276
+
277
+ /**
278
+ * Fetch and save worker capabilities
279
+ */
280
+ async fetchAndSaveCapabilities(workerId: string): Promise<
281
+ Result<
282
+ {
283
+ capabilities: ReadonlyArray<{
284
+ _tag: "sync" | "slashCommand";
285
+ spaceId: string;
286
+ workerId: string;
287
+ key: string;
288
+ config: unknown;
289
+ }>;
290
+ },
291
+ ApiError
292
+ >
293
+ > {
294
+ return this.fetch("/workersFetchAndSaveCapabilities", {
295
+ method: "POST",
296
+ body: {
297
+ workerId,
298
+ },
299
+ });
300
+ }
301
+
302
+ /**
303
+ * Upsert secrets (create or update multiple secrets)
304
+ */
305
+ async upsertSecrets(
306
+ workerId: string,
307
+ secrets: Array<{ key: string; value: string }>,
308
+ ): Promise<
309
+ Result<
310
+ {
311
+ secrets: Array<{
312
+ spaceId: string;
313
+ workerId: string;
314
+ key: string;
315
+ createdAt: string;
316
+ }>;
317
+ },
318
+ ApiError
319
+ >
320
+ > {
321
+ return this.fetch("/workersUpsertSecrets", {
322
+ method: "POST",
323
+ body: {
324
+ workerId,
325
+ secrets,
326
+ },
327
+ });
328
+ }
329
+
330
+ /**
331
+ * List all secrets for a worker (keys only, not values)
332
+ */
333
+ async listSecrets(workerId: string): Promise<
334
+ Result<
335
+ {
336
+ secrets: Array<{
337
+ spaceId: string;
338
+ workerId: string;
339
+ key: string;
340
+ createdAt: string;
341
+ }>;
342
+ },
343
+ ApiError
344
+ >
345
+ > {
346
+ return this.fetch("/workersListSecrets", {
347
+ method: "POST",
348
+ body: {
349
+ workerId,
350
+ },
351
+ });
352
+ }
353
+
354
+ /**
355
+ * Delete a secret
356
+ */
357
+ async deleteSecret(
358
+ workerId: string,
359
+ key: string,
360
+ ): Promise<Result<Record<string, never>, ApiError>> {
361
+ return this.fetch("/workersDeleteSecret", {
362
+ method: "POST",
363
+ body: {
364
+ workerId,
365
+ key,
366
+ },
367
+ });
368
+ }
369
+
370
+ /**
371
+ * List all capabilities for a worker
372
+ */
373
+ async listCapabilities(workerId: string): Promise<
374
+ Result<
375
+ {
376
+ capabilities: Array<{
377
+ _tag: "sync" | "slashCommand";
378
+ key: string;
379
+ }>;
380
+ },
381
+ ApiError
382
+ >
383
+ > {
384
+ return this.fetch("/workersListCapabilities", {
385
+ method: "POST",
386
+ body: {
387
+ workerId,
388
+ },
389
+ });
390
+ }
391
+
392
+ /**
393
+ * Run a capability
394
+ */
395
+ async runCapability(
396
+ workerId: string,
397
+ capabilityKey: string,
398
+ functionName: string | null,
399
+ args: Array<{ name: string; value: string }>,
400
+ stream: true,
401
+ ): Promise<Result<ReadableStream<Uint8Array<ArrayBufferLike>>, ApiError>>;
402
+ async runCapability(
403
+ workerId: string,
404
+ capabilityKey: string,
405
+ functionName: string | null,
406
+ args: Array<{ name: string; value: string }>,
407
+ stream?: false | undefined,
408
+ ): Promise<Result<{ result: unknown }, ApiError>>;
409
+ async runCapability(
410
+ workerId: string,
411
+ capabilityKey: string,
412
+ functionName: string | null,
413
+ args: Array<{ name: string; value: string }>,
414
+ stream?: boolean | undefined,
415
+ ): Promise<
416
+ Result<
417
+ { result: unknown } | ReadableStream<Uint8Array<ArrayBufferLike>>,
418
+ ApiError
419
+ >
420
+ > {
421
+ if (stream) {
422
+ return this.fetch(
423
+ "/workersRunCapability",
424
+ {
425
+ method: "POST",
426
+ body: {
427
+ workerId,
428
+ capabilityKey,
429
+ functionName,
430
+ args,
431
+ stream,
432
+ },
433
+ },
434
+ { stream },
435
+ );
436
+ } else {
437
+ return this.fetch("/workersRunCapability", {
438
+ method: "POST",
439
+ body: {
440
+ workerId,
441
+ capabilityKey,
442
+ functionName,
443
+ args,
444
+ stream,
445
+ },
446
+ });
447
+ }
448
+ }
449
+
450
+ /**
451
+ * Download the bundle for a worker
452
+ */
453
+ async downloadWorkerBundle(
454
+ workerId: string,
455
+ ): Promise<Result<ReadableStream<Uint8Array<ArrayBufferLike>>, ApiError>> {
456
+ return this.fetch(
457
+ "/workersGetBundle",
458
+ {
459
+ method: "POST",
460
+ body: {
461
+ workerId,
462
+ },
463
+ },
464
+ { stream: true },
465
+ );
466
+ }
467
+
468
+ /**
469
+ * List all runs for a worker
470
+ */
471
+ async listRunsForWorker(workerId: string): Promise<
472
+ Result<
473
+ {
474
+ runs: Array<{
475
+ workerId: string;
476
+ spaceId: string;
477
+ runId: string;
478
+ name: string;
479
+ exitCode: number | null;
480
+ startedAt: string;
481
+ endedAt: string | null;
482
+ }>;
483
+ },
484
+ ApiError
485
+ >
486
+ > {
487
+ return this.fetch("/workersListRunsForWorker", {
488
+ method: "POST",
489
+ body: {
490
+ workerId,
491
+ },
492
+ });
493
+ }
494
+
495
+ /**
496
+ * Get logs for a specific run
497
+ */
498
+ async getRunLogs(
499
+ workerId: string,
500
+ runId: string,
501
+ ): Promise<
502
+ Result<
503
+ {
504
+ logs: string;
505
+ },
506
+ ApiError
507
+ >
508
+ > {
509
+ return this.fetch("/workersGetRunLogs", {
510
+ method: "POST",
511
+ body: {
512
+ workerId,
513
+ runId,
514
+ },
515
+ });
516
+ }
517
+ }
518
+
519
+ function headersInitToEntries(
520
+ headersInit: RequestInit["headers"],
521
+ ): [string, string][] {
522
+ if (headersInit instanceof Headers) {
523
+ return Array.from(headersInit.entries());
524
+ }
525
+
526
+ if (Array.isArray(headersInit)) {
527
+ return headersInit;
528
+ }
529
+
530
+ if (headersInit === undefined) {
531
+ return [];
532
+ }
533
+
534
+ const entries: [string, string][] = [];
535
+ for (const [key, value] of Object.entries(headersInit)) {
536
+ if (value === undefined) {
537
+ continue;
538
+ }
539
+ entries.push([key, value]);
540
+ }
541
+
542
+ return entries;
543
+ }
544
+
545
+ async function parseApiError(response: Response): Promise<ApiError> {
546
+ const errorText = await response.text();
547
+ const message = `[${response.status}] ${response.statusText}: ${errorText}`;
548
+ const error: ApiError = {
549
+ status: response.status,
550
+ statusText: response.statusText,
551
+ message,
552
+ };
553
+
554
+ if (response.status === 400) {
555
+ const validationError = parseValidationError(errorText);
556
+ if (validationError) {
557
+ error.validationError = validationError;
558
+ }
559
+ }
560
+
561
+ return error;
562
+ }
563
+
564
+ /**
565
+ * Try to parse a ValidationError from error response text
566
+ */
567
+ function parseValidationError(
568
+ errorText: string,
569
+ ): ApiError["validationError"] | undefined {
570
+ try {
571
+ const errorJson = JSON.parse(errorText);
572
+ if (
573
+ errorJson.name === "ValidationError" &&
574
+ errorJson.debugMessage &&
575
+ errorJson.errorId
576
+ ) {
577
+ return {
578
+ errorId: errorJson.errorId,
579
+ name: errorJson.name,
580
+ debugMessage: errorJson.debugMessage,
581
+ message: errorJson.message,
582
+ };
583
+ }
584
+ } catch {
585
+ // If parsing fails, return undefined
586
+ }
587
+ return undefined;
588
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Represents the union of *either* the value returned
3
+ * from some function *or* an arbitrary error emitted during computation.
4
+ */
5
+
6
+ /**
7
+ * The left side of the Result type, the value.
8
+ */
9
+ export interface Success<T> {
10
+ _tag: "success";
11
+ value: T;
12
+ }
13
+
14
+ /**
15
+ * The right side of the Result type, the error.
16
+ */
17
+ export interface Fail<E> {
18
+ _tag: "fail";
19
+ error: E;
20
+ }
21
+
22
+ export type Result<S, E> = Success<S> | Fail<E>;
23
+
24
+ /**
25
+ * Type predicates and helpers for the Result type.
26
+ */
27
+ export const Result = {
28
+ success<S>(value: S): Success<S> {
29
+ return { _tag: "success", value };
30
+ },
31
+
32
+ fail<E>(error: E): Fail<E> {
33
+ return { _tag: "fail", error };
34
+ },
35
+
36
+ /**
37
+ * Success (left side) type predicate for the Result type.
38
+ */
39
+ isSuccess<S, E>(result: Result<S, E>): result is Success<S> {
40
+ return result._tag === "success";
41
+ },
42
+
43
+ /**
44
+ * Fail (right side) type predicate for the Result type.
45
+ */
46
+ isFail<S, E>(result: Result<S, E>): result is Fail<E> {
47
+ return result._tag === "fail";
48
+ },
49
+
50
+ /**
51
+ * Unwrap a Result value, throwing the error if it's set.
52
+ */
53
+ unwrap<S, E>(result: Result<S, E>): S {
54
+ if (Result.isFail(result)) {
55
+ throw result.error;
56
+ } else {
57
+ return result.value;
58
+ }
59
+ },
60
+
61
+ /**
62
+ * Unwrap a Result value, or return a default value if an error is set.
63
+ */
64
+ unwrapOr<S, E>(result: Result<S, E>, defaultValue: S): S {
65
+ if (Result.isFail(result)) {
66
+ return defaultValue;
67
+ } else {
68
+ return result.value;
69
+ }
70
+ },
71
+ };
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "@stricli/core";
3
+ import { buildContext } from "../context.js";
4
+ import { app } from "../routes.js";
5
+
6
+ // @ts-expect-error // stricli violates exactOptionalPropertyTypes
7
+ await run(app, process.argv.slice(2), buildContext(process));