@tinkerlandai/indiana-cli 0.0.0-stage → 0.3.9

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.
@@ -0,0 +1,319 @@
1
+ // src/io.ts
2
+ import { createReadStream } from "fs";
3
+ import { stat } from "fs/promises";
4
+
5
+ // src/errors.ts
6
+ import { ZodError } from "zod";
7
+
8
+ // ../contracts/src/errors.ts
9
+ import { z } from "zod";
10
+ var apiErrorCodeSchema = z.enum([
11
+ "INVALID_PROTOCOL_VERSION",
12
+ "UNSUPPORTED_PROTOCOL_VERSION",
13
+ "PROTOCOL_RETIRED",
14
+ "UNAUTHENTICATED",
15
+ "FORBIDDEN",
16
+ "SCOPE_MISMATCH",
17
+ "INVALID_REQUEST",
18
+ "NOT_FOUND",
19
+ "CONFLICT",
20
+ "PAYLOAD_TOO_LARGE",
21
+ "RATE_LIMITED",
22
+ "SERVICE_UNAVAILABLE",
23
+ "NOT_CONFIGURED",
24
+ "CAPABILITY_UNAVAILABLE",
25
+ "INTERNAL_ERROR"
26
+ ]);
27
+ var managementErrorCodeSchema = z.enum([
28
+ ...apiErrorCodeSchema.options,
29
+ "INVALID_SERVER_RESPONSE",
30
+ "RESPONSE_TOO_LARGE",
31
+ "AMBIGUOUS_AUTHENTICATION",
32
+ "BROWSER_REQUIRED",
33
+ "INVALID_REDIRECT_URI",
34
+ "AUTHORIZATION_UNAVAILABLE",
35
+ "UNREGISTERED_CLIENT",
36
+ "MANAGEMENT_OPERATION_FAILED"
37
+ ]);
38
+ var consoleErrorCodeSchema = z.enum([
39
+ ...apiErrorCodeSchema.options,
40
+ "stale_revision"
41
+ ]);
42
+ var errorRecoverySchema = z.enum([
43
+ "fix_request",
44
+ "authenticate",
45
+ "check_permissions",
46
+ "check_scope",
47
+ "resolve_conflict",
48
+ "reload_state",
49
+ "retry_same_request",
50
+ "configure_integration",
51
+ "check_availability",
52
+ "upgrade_sdk",
53
+ "recover_operation",
54
+ "contact_support"
55
+ ]);
56
+ var errorReasonSchema = z.enum([
57
+ "CAPABILITY_NOT_ENABLED",
58
+ "INTEGRATION_MISSING",
59
+ "PROVIDER_CREDENTIAL_REJECTED",
60
+ "PRICE_BINDING_REQUIRED",
61
+ "IDEMPOTENCY_CONFLICT",
62
+ "RESULT_UNKNOWN",
63
+ "STATE_CHANGED",
64
+ "OPERATION_IN_PROGRESS",
65
+ /** The pinned published Version uses a retired format and can no longer run; publish a new Version. */
66
+ "FUNNEL_VERSION_RETIRED"
67
+ ]);
68
+ var apiErrorCatalog = {
69
+ INVALID_PROTOCOL_VERSION: { status: 400, recovery: "fix_request" },
70
+ UNSUPPORTED_PROTOCOL_VERSION: { status: 400, recovery: "upgrade_sdk" },
71
+ PROTOCOL_RETIRED: { status: 410, recovery: "upgrade_sdk" },
72
+ UNAUTHENTICATED: { status: 401, recovery: "authenticate" },
73
+ FORBIDDEN: { status: 403, recovery: "check_permissions" },
74
+ SCOPE_MISMATCH: { status: 403, recovery: "check_scope" },
75
+ INVALID_REQUEST: { status: 400, recovery: "fix_request" },
76
+ NOT_FOUND: { status: 404, recovery: "fix_request" },
77
+ CONFLICT: { status: 409, recovery: "resolve_conflict" },
78
+ PAYLOAD_TOO_LARGE: { status: 413, recovery: "fix_request" },
79
+ RATE_LIMITED: { status: 429, recovery: "retry_same_request" },
80
+ SERVICE_UNAVAILABLE: { status: 503, recovery: "retry_same_request" },
81
+ NOT_CONFIGURED: { status: 501, recovery: "configure_integration" },
82
+ CAPABILITY_UNAVAILABLE: { status: 501, recovery: "check_availability" },
83
+ INTERNAL_ERROR: { status: 500, recovery: "recover_operation" }
84
+ };
85
+ function apiErrorCodeForStatus(status) {
86
+ if ([400, 405, 415, 422].includes(status)) return "INVALID_REQUEST";
87
+ if (status === 401) return "UNAUTHENTICATED";
88
+ if (status === 403) return "FORBIDDEN";
89
+ if (status === 404) return "NOT_FOUND";
90
+ if ([409, 412, 425].includes(status)) return "CONFLICT";
91
+ if (status === 413) return "PAYLOAD_TOO_LARGE";
92
+ if (status === 429) return "RATE_LIMITED";
93
+ if (status === 501) return "NOT_CONFIGURED";
94
+ if ([408, 502, 503, 504].includes(status)) return "SERVICE_UNAVAILABLE";
95
+ return "INTERNAL_ERROR";
96
+ }
97
+ function errorPolicy(code, status) {
98
+ if (code === "CONFLICT" && status === 425)
99
+ return { retryable: true, recovery: "retry_same_request" };
100
+ if (code === "CONFLICT" && status === 412)
101
+ return { retryable: false, recovery: "reload_state" };
102
+ if ([
103
+ "TIMEOUT",
104
+ "NETWORK_ERROR",
105
+ "HTTP_ERROR",
106
+ "INVALID_RESPONSE",
107
+ "INVALID_SERVER_RESPONSE"
108
+ ].includes(code))
109
+ return { retryable: false, recovery: "recover_operation" };
110
+ if (code === "NOT_IDENTIFIED" || code === "INVALID_TOKEN")
111
+ return { retryable: false, recovery: "authenticate" };
112
+ if ([
113
+ "INVALID_URL",
114
+ "INVALID_TIMEOUT",
115
+ "SERVER_ONLY",
116
+ "AMBIGUOUS_AUTHENTICATION"
117
+ ].includes(code))
118
+ return { retryable: false, recovery: "fix_request" };
119
+ if (code === "PROTOCOL_MISMATCH")
120
+ return { retryable: false, recovery: "upgrade_sdk" };
121
+ if (code === "IDENTITY_CHANGED")
122
+ return { retryable: false, recovery: "reload_state" };
123
+ if (code === "CAPABILITY_UNAVAILABLE")
124
+ return { retryable: false, recovery: "check_availability" };
125
+ const known = apiErrorCodeSchema.safeParse(code);
126
+ if (!known.success) return { retryable: false, recovery: "contact_support" };
127
+ return {
128
+ retryable: code === "RATE_LIMITED" || code === "SERVICE_UNAVAILABLE",
129
+ recovery: apiErrorCatalog[known.data].recovery
130
+ };
131
+ }
132
+ function errorCodeMatchesStatus(code, status) {
133
+ const known = apiErrorCodeSchema.safeParse(code);
134
+ if (known.success) {
135
+ if (code === "CONFLICT") return [409, 412, 425].includes(status);
136
+ if (code === "SERVICE_UNAVAILABLE")
137
+ return [408, 502, 503, 504].includes(status);
138
+ if (code === "INVALID_REQUEST")
139
+ return [400, 405, 415, 422].includes(status);
140
+ if (code === "NOT_CONFIGURED") return [501, 503].includes(status);
141
+ return apiErrorCatalog[known.data].status === status;
142
+ }
143
+ const extraStatuses = {
144
+ INVALID_SERVER_RESPONSE: [502],
145
+ RESPONSE_TOO_LARGE: [502],
146
+ AMBIGUOUS_AUTHENTICATION: [400],
147
+ BROWSER_REQUIRED: [403],
148
+ INVALID_REDIRECT_URI: [403],
149
+ AUTHORIZATION_UNAVAILABLE: [400],
150
+ UNREGISTERED_CLIENT: [403],
151
+ MANAGEMENT_OPERATION_FAILED: [400, 422, 500]
152
+ };
153
+ return Object.hasOwn(extraStatuses, code) && (extraStatuses[code]?.includes(status) ?? false);
154
+ }
155
+ function parseRetryAfter(value, now = Date.now()) {
156
+ if (value === null) return void 0;
157
+ const text = value.trim();
158
+ if (/^\d+$/.test(text)) {
159
+ const seconds = Number(text);
160
+ return Number.isSafeInteger(seconds) ? seconds : void 0;
161
+ }
162
+ if (!/^[A-Za-z]{3}, \d{2} [A-Za-z]{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/.test(text))
163
+ return void 0;
164
+ const date = Date.parse(text);
165
+ return Number.isFinite(date) ? Math.max(0, Math.ceil((date - now) / 1e3)) : void 0;
166
+ }
167
+ var errorMetadataSchema = z.object({
168
+ retryable: z.boolean(),
169
+ recovery: errorRecoverySchema,
170
+ reason: errorReasonSchema.optional(),
171
+ retryAfterSeconds: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional()
172
+ });
173
+ var errorResponseSchema = z.object({
174
+ requestId: z.uuid().optional(),
175
+ error: z.object({
176
+ code: z.string().regex(/^[A-Z][A-Z0-9_]{0,95}$/),
177
+ message: z.string(),
178
+ ...errorMetadataSchema.partial().shape
179
+ })
180
+ });
181
+ var managementErrorResponseSchema = z.object({
182
+ error: errorResponseSchema.shape.error.extend({
183
+ requestId: z.uuid().optional()
184
+ })
185
+ });
186
+ var consoleErrorResponseSchema = z.object({
187
+ error: z.string(),
188
+ // Console keeps area-specific editor discriminators; management normalizes them.
189
+ code: z.string().regex(/^[A-Za-z][A-Za-z0-9_]{0,95}$/),
190
+ requestId: z.uuid(),
191
+ ...errorMetadataSchema.shape
192
+ });
193
+ function errorMetadata(code, status, options = {}) {
194
+ const policy = errorPolicy(code, status);
195
+ const recovery = options.reason === "RESULT_UNKNOWN" ? "recover_operation" : options.recovery ?? policy.recovery;
196
+ const retryable = policy.retryable && options.retryable !== false && recovery !== "recover_operation";
197
+ const retryAfterSeconds = retryable ? parseRetryAfter(options.retryAfter ?? null) : void 0;
198
+ return {
199
+ ...policy,
200
+ retryable,
201
+ recovery,
202
+ ...retryAfterSeconds === void 0 ? {} : { retryAfterSeconds },
203
+ ...options.reason ? { reason: options.reason } : {}
204
+ };
205
+ }
206
+
207
+ // src/errors.ts
208
+ var CliError = class extends Error {
209
+ constructor(code, message, exitCode = 2, details, retryable = false, metadata = {}) {
210
+ super(message);
211
+ this.code = code;
212
+ this.exitCode = exitCode;
213
+ this.details = details;
214
+ this.retryable = retryable;
215
+ this.metadata = metadata;
216
+ }
217
+ code;
218
+ exitCode;
219
+ details;
220
+ retryable;
221
+ metadata;
222
+ };
223
+ function cliErrorCause(error) {
224
+ const seen = /* @__PURE__ */ new Set();
225
+ for (let depth = 0; depth < 16; depth++) {
226
+ if (error instanceof CliError) return error;
227
+ if (!error || typeof error !== "object" || seen.has(error)) return;
228
+ seen.add(error);
229
+ error = error.cause;
230
+ }
231
+ return void 0;
232
+ }
233
+ function schemaError(error, code, message) {
234
+ if (error instanceof ZodError)
235
+ return new CliError(code, message, 2, {
236
+ fields: error.issues.slice(0, 50).map(({ code: code2, path, message: message2 }) => ({ code: code2, path, message: message2 })),
237
+ truncated: error.issues.length > 50
238
+ });
239
+ return error;
240
+ }
241
+ function errorResult(error) {
242
+ const safe = error instanceof CliError ? error : new CliError(
243
+ "INTERNAL_ERROR",
244
+ "The command failed. No credentials or document contents have been logged.",
245
+ 6
246
+ );
247
+ return {
248
+ exitCode: safe.exitCode,
249
+ body: {
250
+ error: {
251
+ code: safe.code,
252
+ message: safe.message,
253
+ retryable: safe.retryable,
254
+ recovery: safe.metadata.recovery ?? errorPolicy(safe.code, safe.metadata.status).recovery,
255
+ ...safe.metadata.reason ? { reason: safe.metadata.reason } : {},
256
+ ...safe.metadata.requestId ? { requestId: safe.metadata.requestId } : {},
257
+ ...safe.metadata.status === void 0 ? {} : { status: safe.metadata.status },
258
+ ...safe.retryable && safe.metadata.retryAfterSeconds !== void 0 ? { retryAfterSeconds: safe.metadata.retryAfterSeconds } : {},
259
+ ...safe.details === void 0 ? {} : { details: safe.details }
260
+ }
261
+ }
262
+ };
263
+ }
264
+
265
+ // src/io.ts
266
+ async function readJsonStream(source, limit) {
267
+ const chunks = [];
268
+ let size = 0;
269
+ for await (const chunk of source) {
270
+ size += chunk.byteLength;
271
+ if (size > limit)
272
+ throw new CliError(
273
+ "PAYLOAD_TOO_LARGE",
274
+ `JSON input exceeds ${limit} bytes.`
275
+ );
276
+ chunks.push(chunk);
277
+ }
278
+ try {
279
+ return JSON.parse(
280
+ new TextDecoder("utf-8", { fatal: true }).decode(Buffer.concat(chunks))
281
+ );
282
+ } catch {
283
+ throw new CliError("INVALID_JSON", "Input must contain valid UTF-8 JSON.");
284
+ }
285
+ }
286
+ async function readJsonFile(path, limit, stdin = process.stdin) {
287
+ if (path === "-") return readJsonStream(stdin, limit);
288
+ try {
289
+ const info = await stat(path);
290
+ if (!info.isFile())
291
+ throw new CliError("INVALID_FILE", "Input must be a regular JSON file.");
292
+ if (info.size > limit)
293
+ throw new CliError(
294
+ "PAYLOAD_TOO_LARGE",
295
+ `JSON input exceeds ${limit} bytes.`
296
+ );
297
+ return await readJsonStream(createReadStream(path), limit);
298
+ } catch (error) {
299
+ if (error instanceof CliError) throw error;
300
+ throw new CliError(
301
+ "FILE_UNAVAILABLE",
302
+ "Cannot read the requested JSON file."
303
+ );
304
+ }
305
+ }
306
+
307
+ export {
308
+ managementErrorCodeSchema,
309
+ apiErrorCodeForStatus,
310
+ errorCodeMatchesStatus,
311
+ managementErrorResponseSchema,
312
+ errorMetadata,
313
+ CliError,
314
+ cliErrorCause,
315
+ schemaError,
316
+ errorResult,
317
+ readJsonStream,
318
+ readJsonFile
319
+ };
@@ -0,0 +1,8 @@
1
+ import {
2
+ readJsonFile,
3
+ readJsonStream
4
+ } from "./chunk-4MAMIKAR.js";
5
+ export {
6
+ readJsonFile,
7
+ readJsonStream
8
+ };