@cipherstash/stack 0.15.1 → 0.15.3

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @cipherstash/stack
2
2
 
3
+ ## 0.15.3
4
+
5
+ ### Patch Changes
6
+
7
+ - afe6810: Bump protect-ffi version
8
+
9
+ ## 0.15.2
10
+
11
+ ### Patch Changes
12
+
13
+ - 510c485: Bundle `evlog` into the CJS output. `evlog` is pure ESM (no `require` condition in its `exports` map), so CJS consumers of `@cipherstash/stack` (e.g. webpack bundles) were failing with `ERR_PACKAGE_PATH_NOT_EXPORTED` when the stack's `index.cjs` tried to `require("evlog")`. `evlog` is now inlined at build time and no longer resolved at runtime.
14
+
3
15
  ## 0.15.1
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -47,7 +47,7 @@ pnpm add @cipherstash/stack
47
47
  ### 1. Initialize and authenticate your project
48
48
 
49
49
  ```bash
50
- npx @cipherstash/cli init
50
+ npx stash init
51
51
  ```
52
52
 
53
53
  The wizard will authenticate you, walk you through choosing a database connection method, build an encryption schema, and install the required dependencies.
@@ -438,25 +438,25 @@ await secrets.delete("DATABASE_URL")
438
438
 
439
439
  ## CLI Reference
440
440
 
441
- The CLI is available via `npx @cipherstash/cli` after install.
441
+ The CLI is available via `npx stash` after install.
442
442
 
443
- ### `npx @cipherstash/cli auth`
443
+ ### `npx stash auth`
444
444
 
445
445
  Authenticate with CipherStash.
446
446
 
447
447
  ```bash
448
- npx @cipherstash/cli auth login
448
+ npx stash auth login
449
449
  ```
450
450
 
451
451
  This runs the device code flow: it opens your browser, you confirm the code, and a token is saved to `~/.cipherstash/auth.json`. No environment variables or credentials files are needed for local development.
452
452
 
453
- ### `npx @cipherstash/cli init`
453
+ ### `npx stash init`
454
454
 
455
455
  Initialize CipherStash for your project with an interactive wizard.
456
456
 
457
457
  ```bash
458
- npx @cipherstash/cli init
459
- npx @cipherstash/cli init --supabase
458
+ npx stash init
459
+ npx stash init --supabase
460
460
  ```
461
461
 
462
462
  The wizard will:
@@ -464,31 +464,31 @@ The wizard will:
464
464
  2. Bind your device to the default Keyset
465
465
  3. Choose your database connection method (Drizzle ORM, Supabase JS, Prisma, or Raw SQL)
466
466
  4. Build an encryption schema interactively or use a placeholder, then generate the encryption client file
467
- 5. Install `@cipherstash/cli` as a dev dependency for database tooling
467
+ 5. Install `stash` as a dev dependency for database tooling
468
468
 
469
- After init, run `npx @cipherstash/cli db setup` to configure your database.
469
+ After init, run `npx stash db setup` to configure your database.
470
470
 
471
471
  | Flag | Description |
472
472
  |------|-------------|
473
473
  | `--supabase` | Use Supabase-specific setup flow |
474
474
 
475
- ### `npx @cipherstash/cli secrets`
475
+ ### `npx stash secrets`
476
476
 
477
477
  Manage encrypted secrets from the terminal.
478
478
 
479
479
  ```bash
480
- npx @cipherstash/cli secrets set -name DATABASE_URL -value "postgres://..." -environment production
481
- npx @cipherstash/cli secrets get -name DATABASE_URL -environment production
482
- npx @cipherstash/cli secrets list -environment production
483
- npx @cipherstash/cli secrets delete -name DATABASE_URL -environment production
480
+ npx stash secrets set -name DATABASE_URL -value "postgres://..." -environment production
481
+ npx stash secrets get -name DATABASE_URL -environment production
482
+ npx stash secrets list -environment production
483
+ npx stash secrets delete -name DATABASE_URL -environment production
484
484
  ```
485
485
 
486
486
  | Command | Flags | Aliases | Description |
487
487
  |-----|----|-----|-------|
488
- | `npx @cipherstash/cli secrets set` | `-name`, `-value`, `-environment` | `-n`, `-V`, `-e` | Encrypt and store a secret |
489
- | `npx @cipherstash/cli secrets get` | `-name`, `-environment` | `-n`, `-e` | Retrieve and decrypt a secret |
490
- | `npx @cipherstash/cli secrets list` | `-environment` | `-e` | List all secret names in an environment |
491
- | `npx @cipherstash/cli secrets delete` | `-name`, `-environment`, `-yes` | `-n`, `-e`, `-y` | Delete a secret (prompts for confirmation unless `-yes`) |
488
+ | `npx stash secrets set` | `-name`, `-value`, `-environment` | `-n`, `-V`, `-e` | Encrypt and store a secret |
489
+ | `npx stash secrets get` | `-name`, `-environment` | `-n`, `-e` | Retrieve and decrypt a secret |
490
+ | `npx stash secrets list` | `-environment` | `-e` | List all secret names in an environment |
491
+ | `npx stash secrets delete` | `-name`, `-environment`, `-yes` | `-n`, `-e`, `-y` | Delete a secret (prompts for confirmation unless `-yes`) |
492
492
 
493
493
  ## Configuration
494
494
 
@@ -676,7 +676,7 @@ If you are migrating from `@cipherstash/protect`, the following table maps the o
676
676
  | `csColumn(name)` | `encryptedColumn(name)` | `@cipherstash/stack/schema` |
677
677
  | `import { LockContext } from "@cipherstash/protect/identify"` | `import { LockContext } from "@cipherstash/stack/identity"` | `@cipherstash/stack/identity` |
678
678
  | N/A | `Secrets` class | `@cipherstash/stack/secrets` |
679
- | N/A | CLI | `npx @cipherstash/cli` |
679
+ | N/A | CLI | `npx stash` |
680
680
 
681
681
  All method signatures on the encryption client (`encrypt`, `decrypt`, `encryptModel`, etc.) remain the same. The `Result` pattern (`data` / `failure`) is unchanged.
682
682
 
@@ -14,7 +14,7 @@ import {
14
14
  import {
15
15
  createRequestLogger,
16
16
  logger
17
- } from "./chunk-Q5FTQLYG.js";
17
+ } from "./chunk-6FD7OBGM.js";
18
18
  import {
19
19
  EncryptionErrorTypes
20
20
  } from "./chunk-LBMC4D6D.js";
@@ -2325,4 +2325,4 @@ export {
2325
2325
  EncryptionClient,
2326
2326
  Encryption
2327
2327
  };
2328
- //# sourceMappingURL=chunk-YPAPL3IC.js.map
2328
+ //# sourceMappingURL=chunk-46S3YFRK.js.map
@@ -0,0 +1,365 @@
1
+ // ../../node_modules/.pnpm/evlog@1.9.0/node_modules/evlog/dist/utils.mjs
2
+ function formatDuration(ms) {
3
+ if (ms < 1e3) return `${Math.round(ms)}ms`;
4
+ return `${(ms / 1e3).toFixed(2)}s`;
5
+ }
6
+ function isDev() {
7
+ if (typeof process !== "undefined") return process.env.NODE_ENV !== "production";
8
+ if (typeof window !== "undefined") return true;
9
+ return false;
10
+ }
11
+ function detectEnvironment() {
12
+ const env = typeof process !== "undefined" ? process.env : {};
13
+ const defaultEnvironment = isDev() ? "development" : "production";
14
+ return {
15
+ environment: env.NODE_ENV || defaultEnvironment,
16
+ service: env.SERVICE_NAME || "app",
17
+ version: env.APP_VERSION,
18
+ commitHash: env.COMMIT_SHA || env.GITHUB_SHA || env.VERCEL_GIT_COMMIT_SHA || env.CF_PAGES_COMMIT_SHA,
19
+ region: env.VERCEL_REGION || env.AWS_REGION || env.FLY_REGION || env.CF_REGION
20
+ };
21
+ }
22
+ function getConsoleMethod(level) {
23
+ return level;
24
+ }
25
+ var colors = {
26
+ reset: "\x1B[0m",
27
+ bold: "\x1B[1m",
28
+ dim: "\x1B[2m",
29
+ red: "\x1B[31m",
30
+ green: "\x1B[32m",
31
+ yellow: "\x1B[33m",
32
+ blue: "\x1B[34m",
33
+ magenta: "\x1B[35m",
34
+ cyan: "\x1B[36m",
35
+ white: "\x1B[37m",
36
+ gray: "\x1B[90m"
37
+ };
38
+ function getLevelColor(level) {
39
+ switch (level) {
40
+ case "error":
41
+ return colors.red;
42
+ case "warn":
43
+ return colors.yellow;
44
+ case "info":
45
+ return colors.cyan;
46
+ case "debug":
47
+ return colors.gray;
48
+ default:
49
+ return colors.white;
50
+ }
51
+ }
52
+ function matchesPattern(path, pattern) {
53
+ const regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/{{GLOBSTAR}}/g, ".*").replace(/\?/g, "[^/]");
54
+ return new RegExp(`^${regexPattern}$`).test(path);
55
+ }
56
+
57
+ // ../../node_modules/.pnpm/evlog@1.9.0/node_modules/evlog/dist/logger.mjs
58
+ function isPlainObject(val) {
59
+ return val !== null && typeof val === "object" && !Array.isArray(val);
60
+ }
61
+ function deepDefaults(base, defaults) {
62
+ const result = { ...base };
63
+ for (const key in defaults) {
64
+ const baseVal = result[key];
65
+ const defaultVal = defaults[key];
66
+ if (baseVal === void 0 || baseVal === null) result[key] = defaultVal;
67
+ else if (isPlainObject(baseVal) && isPlainObject(defaultVal)) result[key] = deepDefaults(baseVal, defaultVal);
68
+ }
69
+ return result;
70
+ }
71
+ var globalEnv = {
72
+ service: "app",
73
+ environment: "development"
74
+ };
75
+ var globalPretty = isDev();
76
+ var globalSampling = {};
77
+ var globalStringify = true;
78
+ var globalDrain;
79
+ var globalEnabled = true;
80
+ function initLogger(config = {}) {
81
+ globalEnabled = config.enabled ?? true;
82
+ const detected = detectEnvironment();
83
+ globalEnv = {
84
+ service: config.env?.service ?? detected.service ?? "app",
85
+ environment: config.env?.environment ?? detected.environment ?? "development",
86
+ version: config.env?.version ?? detected.version,
87
+ commitHash: config.env?.commitHash ?? detected.commitHash,
88
+ region: config.env?.region ?? detected.region
89
+ };
90
+ globalPretty = config.pretty ?? isDev();
91
+ globalSampling = config.sampling ?? {};
92
+ globalStringify = config.stringify ?? true;
93
+ globalDrain = config.drain;
94
+ }
95
+ function shouldSample(level) {
96
+ const { rates } = globalSampling;
97
+ if (!rates) return true;
98
+ const percentage = level === "error" && rates.error === void 0 ? 100 : rates[level] ?? 100;
99
+ if (percentage <= 0) return false;
100
+ if (percentage >= 100) return true;
101
+ return Math.random() * 100 < percentage;
102
+ }
103
+ function shouldKeep(ctx) {
104
+ const { keep } = globalSampling;
105
+ if (!keep?.length) return false;
106
+ return keep.some((condition) => {
107
+ if (condition.status !== void 0 && ctx.status !== void 0 && ctx.status >= condition.status) return true;
108
+ if (condition.duration !== void 0 && ctx.duration !== void 0 && ctx.duration >= condition.duration) return true;
109
+ if (condition.path && ctx.path && matchesPattern(ctx.path, condition.path)) return true;
110
+ return false;
111
+ });
112
+ }
113
+ function emitWideEvent(level, event, skipSamplingCheck = false) {
114
+ if (!globalEnabled) return null;
115
+ if (!skipSamplingCheck && !shouldSample(level)) return null;
116
+ const formatted = {
117
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
118
+ level,
119
+ ...globalEnv,
120
+ ...event
121
+ };
122
+ if (globalPretty) prettyPrintWideEvent(formatted);
123
+ else if (globalStringify) console[getConsoleMethod(level)](JSON.stringify(formatted));
124
+ else console[getConsoleMethod(level)](formatted);
125
+ if (globalDrain) Promise.resolve(globalDrain({ event: formatted })).catch((err) => {
126
+ console.error("[evlog] drain failed:", err);
127
+ });
128
+ return formatted;
129
+ }
130
+ function emitTaggedLog(level, tag, message) {
131
+ if (!globalEnabled) return;
132
+ if (globalPretty) {
133
+ if (!shouldSample(level)) return;
134
+ const color = getLevelColor(level);
135
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
136
+ console.log(`${colors.dim}${timestamp}${colors.reset} ${color}[${tag}]${colors.reset} ${message}`);
137
+ return;
138
+ }
139
+ emitWideEvent(level, {
140
+ tag,
141
+ message
142
+ });
143
+ }
144
+ function formatValue(value) {
145
+ if (value === null || value === void 0) return String(value);
146
+ if (typeof value === "object") {
147
+ const pairs = [];
148
+ for (const [k, v] of Object.entries(value)) if (v !== void 0 && v !== null) if (typeof v === "object") pairs.push(`${k}=${JSON.stringify(v)}`);
149
+ else pairs.push(`${k}=${v}`);
150
+ return pairs.join(" ");
151
+ }
152
+ return String(value);
153
+ }
154
+ function prettyPrintWideEvent(event) {
155
+ const { timestamp, level, service, environment, version, ...rest } = event;
156
+ const levelColor = getLevelColor(level);
157
+ const ts = timestamp.slice(11, 23);
158
+ let header = `${colors.dim}${ts}${colors.reset} ${levelColor}${level.toUpperCase()}${colors.reset}`;
159
+ header += ` ${colors.cyan}[${service}]${colors.reset}`;
160
+ if (rest.method && rest.path) {
161
+ header += ` ${rest.method} ${rest.path}`;
162
+ delete rest.method;
163
+ delete rest.path;
164
+ }
165
+ if (rest.status) {
166
+ const statusColor = rest.status >= 400 ? colors.red : colors.green;
167
+ header += ` ${statusColor}${rest.status}${colors.reset}`;
168
+ delete rest.status;
169
+ }
170
+ if (rest.duration) {
171
+ header += ` ${colors.dim}in ${rest.duration}${colors.reset}`;
172
+ delete rest.duration;
173
+ }
174
+ console.log(header);
175
+ const entries = Object.entries(rest).filter(([_, v]) => v !== void 0);
176
+ const lastIndex = entries.length - 1;
177
+ entries.forEach(([key, value], index) => {
178
+ const prefix = index === lastIndex ? "\u2514\u2500" : "\u251C\u2500";
179
+ const formatted = formatValue(value);
180
+ console.log(` ${colors.dim}${prefix}${colors.reset} ${colors.cyan}${key}:${colors.reset} ${formatted}`);
181
+ });
182
+ }
183
+ function createLogMethod(level) {
184
+ return function logMethod(tagOrEvent, message) {
185
+ if (typeof tagOrEvent === "string" && message !== void 0) emitTaggedLog(level, tagOrEvent, message);
186
+ else if (typeof tagOrEvent === "object") emitWideEvent(level, tagOrEvent);
187
+ else emitTaggedLog(level, "log", String(tagOrEvent));
188
+ };
189
+ }
190
+ var _log = {
191
+ info: createLogMethod("info"),
192
+ error: createLogMethod("error"),
193
+ warn: createLogMethod("warn"),
194
+ debug: createLogMethod("debug")
195
+ };
196
+ var noopLogger = {
197
+ set() {
198
+ },
199
+ error() {
200
+ },
201
+ info() {
202
+ },
203
+ warn() {
204
+ },
205
+ emit() {
206
+ return null;
207
+ },
208
+ getContext() {
209
+ return {};
210
+ }
211
+ };
212
+ function createRequestLogger(options = {}) {
213
+ if (!globalEnabled) return noopLogger;
214
+ const startTime = Date.now();
215
+ let context = {
216
+ method: options.method,
217
+ path: options.path,
218
+ requestId: options.requestId
219
+ };
220
+ let hasError = false;
221
+ let hasWarn = false;
222
+ function addRequestLog(level, message) {
223
+ const entry = {
224
+ level,
225
+ message,
226
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
227
+ };
228
+ const requestLogs = Array.isArray(context.requestLogs) ? [...context.requestLogs, entry] : [entry];
229
+ context = {
230
+ ...context,
231
+ requestLogs
232
+ };
233
+ }
234
+ return {
235
+ set(data) {
236
+ context = deepDefaults(data, context);
237
+ },
238
+ error(error, errorContext) {
239
+ hasError = true;
240
+ const err = typeof error === "string" ? new Error(error) : error;
241
+ context = deepDefaults({
242
+ ...errorContext,
243
+ error: {
244
+ name: err.name,
245
+ message: err.message,
246
+ stack: err.stack,
247
+ ..."status" in err && { status: err.status },
248
+ ..."statusText" in err && { statusText: err.statusText },
249
+ ..."statusCode" in err && { statusCode: err.statusCode },
250
+ ..."statusMessage" in err && { statusMessage: err.statusMessage },
251
+ ..."data" in err && { data: err.data },
252
+ ..."cause" in err && { cause: err.cause }
253
+ }
254
+ }, context);
255
+ },
256
+ info(message, infoContext) {
257
+ addRequestLog("info", message);
258
+ if (infoContext) {
259
+ const { requestLogs: _, ...rest } = infoContext;
260
+ context = deepDefaults(rest, context);
261
+ }
262
+ },
263
+ warn(message, warnContext) {
264
+ hasWarn = true;
265
+ addRequestLog("warn", message);
266
+ if (warnContext) {
267
+ const { requestLogs: _, ...rest } = warnContext;
268
+ context = deepDefaults(rest, context);
269
+ }
270
+ },
271
+ emit(overrides) {
272
+ const durationMs = Date.now() - startTime;
273
+ const duration = formatDuration(durationMs);
274
+ const level = hasError ? "error" : hasWarn ? "warn" : "info";
275
+ const { _forceKeep, ...restOverrides } = overrides ?? {};
276
+ const tailCtx = {
277
+ status: context.status ?? restOverrides.status,
278
+ duration: durationMs,
279
+ path: context.path,
280
+ method: context.method,
281
+ context: {
282
+ ...context,
283
+ ...restOverrides
284
+ }
285
+ };
286
+ if (!(_forceKeep || shouldKeep(tailCtx)) && !shouldSample(level)) return null;
287
+ return emitWideEvent(level, {
288
+ ...context,
289
+ ...restOverrides,
290
+ duration
291
+ }, true);
292
+ },
293
+ getContext() {
294
+ return { ...context };
295
+ }
296
+ };
297
+ }
298
+
299
+ // src/utils/logger/index.ts
300
+ var validLevels = ["debug", "info", "error"];
301
+ function levelFromEnv() {
302
+ const env = process.env.STASH_STACK_LOG;
303
+ if (env && validLevels.includes(env)) return env;
304
+ return "error";
305
+ }
306
+ function samplingRatesForLevel(level) {
307
+ switch (level) {
308
+ case "debug":
309
+ return { debug: 100, info: 100, warn: 100, error: 100 };
310
+ case "info":
311
+ return { debug: 0, info: 100, warn: 100, error: 100 };
312
+ case "error":
313
+ default:
314
+ return { debug: 0, info: 0, warn: 0, error: 100 };
315
+ }
316
+ }
317
+ var initialized = false;
318
+ function initStackLogger() {
319
+ if (initialized) return;
320
+ initialized = true;
321
+ const level = levelFromEnv();
322
+ const rates = samplingRatesForLevel(level);
323
+ initLogger({
324
+ env: { service: "@cipherstash/stack" },
325
+ enabled: true,
326
+ sampling: { rates }
327
+ });
328
+ }
329
+ initStackLogger();
330
+ function safeMessage(args) {
331
+ return typeof args[0] === "string" ? args[0] : "";
332
+ }
333
+ var logger = {
334
+ debug(...args) {
335
+ const log = createRequestLogger();
336
+ log.set({
337
+ level: "debug",
338
+ source: "@cipherstash/stack",
339
+ message: safeMessage(args)
340
+ });
341
+ log.emit();
342
+ },
343
+ info(...args) {
344
+ const log = createRequestLogger();
345
+ log.set({ source: "@cipherstash/stack" });
346
+ log.info(safeMessage(args));
347
+ log.emit();
348
+ },
349
+ warn(...args) {
350
+ const log = createRequestLogger();
351
+ log.warn(safeMessage(args));
352
+ log.emit();
353
+ },
354
+ error(...args) {
355
+ const log = createRequestLogger();
356
+ log.error(safeMessage(args));
357
+ log.emit();
358
+ }
359
+ };
360
+
361
+ export {
362
+ createRequestLogger,
363
+ logger
364
+ };
365
+ //# sourceMappingURL=chunk-6FD7OBGM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/evlog@1.9.0/node_modules/evlog/src/utils.ts","../../../node_modules/.pnpm/evlog@1.9.0/node_modules/evlog/src/logger.ts","../src/utils/logger/index.ts"],"sourcesContent":["import type { EnvironmentContext, LogLevel } from './types'\n\nexport function formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${Math.round(ms)}ms`\n }\n return `${(ms / 1000).toFixed(2)}s`\n}\n\nexport function isServer(): boolean {\n return typeof window === 'undefined'\n}\n\nexport function isClient(): boolean {\n return typeof window !== 'undefined'\n}\n\nexport function isDev(): boolean {\n if (typeof process !== 'undefined') {\n return process.env.NODE_ENV !== 'production'\n }\n if (typeof window !== 'undefined') {\n return true\n }\n return false\n}\n\nexport function detectEnvironment(): Partial<EnvironmentContext> {\n const env = typeof process !== 'undefined' ? process.env : {}\n const defaultEnvironment = isDev() ? 'development' : 'production'\n\n return {\n environment: env.NODE_ENV || defaultEnvironment,\n service: env.SERVICE_NAME || 'app',\n version: env.APP_VERSION,\n commitHash: env.COMMIT_SHA\n || env.GITHUB_SHA\n || env.VERCEL_GIT_COMMIT_SHA\n || env.CF_PAGES_COMMIT_SHA,\n region: env.VERCEL_REGION\n || env.AWS_REGION\n || env.FLY_REGION\n || env.CF_REGION,\n }\n}\n\nexport function getConsoleMethod(level: LogLevel): LogLevel {\n return level\n}\n\nexport const colors = {\n reset: '\\x1B[0m',\n bold: '\\x1B[1m',\n dim: '\\x1B[2m',\n red: '\\x1B[31m',\n green: '\\x1B[32m',\n yellow: '\\x1B[33m',\n blue: '\\x1B[34m',\n magenta: '\\x1B[35m',\n cyan: '\\x1B[36m',\n white: '\\x1B[37m',\n gray: '\\x1B[90m',\n} as const\n\nexport function getLevelColor(level: string): string {\n switch (level) {\n case 'error':\n return colors.red\n case 'warn':\n return colors.yellow\n case 'info':\n return colors.cyan\n case 'debug':\n return colors.gray\n default:\n return colors.white\n }\n}\n\n/** Headers that should never be passed to hooks for security */\nexport const SENSITIVE_HEADERS = [\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'x-auth-token',\n 'proxy-authorization',\n]\n\nexport function filterSafeHeaders(headers: Record<string, string>): Record<string, string> {\n const safeHeaders: Record<string, string> = {}\n\n for (const [key, value] of Object.entries(headers)) {\n if (!SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n safeHeaders[key] = value\n }\n }\n\n return safeHeaders\n}\n\n/**\n * Match a path against a glob pattern.\n * Supports * (any chars except /) and ** (any chars including /).\n */\nexport function matchesPattern(path: string, pattern: string): boolean {\n const regexPattern = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&') // Escape special regex chars except * and ?\n .replace(/\\*\\*/g, '{{GLOBSTAR}}') // Temp placeholder for **\n .replace(/\\*/g, '[^/]*') // * matches anything except /\n .replace(/{{GLOBSTAR}}/g, '.*') // ** matches anything including /\n .replace(/\\?/g, '[^/]') // ? matches single char except /\n\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(path)\n}\n","import type { DrainContext, EnvironmentContext, FieldContext, Log, LogLevel, LoggerConfig, RequestLogger, RequestLoggerOptions, SamplingConfig, TailSamplingContext, WideEvent } from './types'\nimport { colors, detectEnvironment, formatDuration, getConsoleMethod, getLevelColor, isDev, matchesPattern } from './utils'\n\nfunction isPlainObject(val: unknown): val is Record<string, unknown> {\n return val !== null && typeof val === 'object' && !Array.isArray(val)\n}\n\nfunction deepDefaults(base: Record<string, unknown>, defaults: Record<string, unknown>): Record<string, unknown> {\n const result = { ...base }\n for (const key in defaults) {\n const baseVal = result[key]\n const defaultVal = defaults[key]\n if (baseVal === undefined || baseVal === null) {\n result[key] = defaultVal\n } else if (isPlainObject(baseVal) && isPlainObject(defaultVal)) {\n result[key] = deepDefaults(baseVal, defaultVal)\n }\n }\n return result\n}\n\nlet globalEnv: EnvironmentContext = {\n service: 'app',\n environment: 'development',\n}\n\nlet globalPretty = isDev()\nlet globalSampling: SamplingConfig = {}\nlet globalStringify = true\nlet globalDrain: ((ctx: DrainContext) => void | Promise<void>) | undefined\nlet globalEnabled = true\n\n/**\n * Initialize the logger with configuration.\n * Call this once at application startup.\n */\nexport function initLogger(config: LoggerConfig = {}): void {\n globalEnabled = config.enabled ?? true\n const detected = detectEnvironment()\n\n globalEnv = {\n service: config.env?.service ?? detected.service ?? 'app',\n environment: config.env?.environment ?? detected.environment ?? 'development',\n version: config.env?.version ?? detected.version,\n commitHash: config.env?.commitHash ?? detected.commitHash,\n region: config.env?.region ?? detected.region,\n }\n\n globalPretty = config.pretty ?? isDev()\n globalSampling = config.sampling ?? {}\n globalStringify = config.stringify ?? true\n globalDrain = config.drain\n}\n\n/**\n * Check if logging is globally enabled.\n */\nexport function isEnabled(): boolean {\n return globalEnabled\n}\n\n/**\n * Determine if a log at the given level should be emitted based on sampling config.\n * Error level defaults to 100% (always logged) unless explicitly configured otherwise.\n */\nfunction shouldSample(level: LogLevel): boolean {\n const { rates } = globalSampling\n if (!rates) {\n return true // No sampling configured, log everything\n }\n\n // Error defaults to 100% unless explicitly set\n const percentage = level === 'error' && rates.error === undefined\n ? 100\n : rates[level] ?? 100\n\n // 0% = never log, 100% = always log\n if (percentage <= 0) return false\n if (percentage >= 100) return true\n\n return Math.random() * 100 < percentage\n}\n\n/**\n * Evaluate tail sampling conditions to determine if a log should be force-kept.\n * Returns true if ANY condition matches (OR logic).\n */\nexport function shouldKeep(ctx: TailSamplingContext): boolean {\n const { keep } = globalSampling\n if (!keep?.length) return false\n\n return keep.some((condition) => {\n if (condition.status !== undefined && ctx.status !== undefined && ctx.status >= condition.status) {\n return true\n }\n if (condition.duration !== undefined && ctx.duration !== undefined && ctx.duration >= condition.duration) {\n return true\n }\n if (condition.path && ctx.path && matchesPattern(ctx.path, condition.path)) {\n return true\n }\n return false\n })\n}\n\nfunction emitWideEvent(level: LogLevel, event: Record<string, unknown>, skipSamplingCheck = false): WideEvent | null {\n if (!globalEnabled) return null\n\n if (!skipSamplingCheck && !shouldSample(level)) {\n return null\n }\n\n const formatted: WideEvent = {\n timestamp: new Date().toISOString(),\n level,\n ...globalEnv,\n ...event,\n }\n\n if (globalPretty) {\n prettyPrintWideEvent(formatted)\n } else if (globalStringify) {\n console[getConsoleMethod(level)](JSON.stringify(formatted))\n } else {\n console[getConsoleMethod(level)](formatted)\n }\n\n if (globalDrain) {\n Promise.resolve(globalDrain({ event: formatted })).catch((err) => {\n console.error('[evlog] drain failed:', err)\n })\n }\n\n return formatted\n}\n\nfunction emitTaggedLog(level: LogLevel, tag: string, message: string): void {\n if (!globalEnabled) return\n\n if (globalPretty) {\n if (!shouldSample(level)) {\n return\n }\n const color = getLevelColor(level)\n const timestamp = new Date().toISOString().slice(11, 23)\n console.log(`${colors.dim}${timestamp}${colors.reset} ${color}[${tag}]${colors.reset} ${message}`)\n return\n }\n emitWideEvent(level, { tag, message })\n}\n\nfunction formatValue(value: unknown): string {\n if (value === null || value === undefined) {\n return String(value)\n }\n if (typeof value === 'object') {\n // Flatten object to key=value pairs\n const pairs: string[] = []\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (v !== undefined && v !== null) {\n if (typeof v === 'object') {\n // For nested objects, show as JSON\n pairs.push(`${k}=${JSON.stringify(v)}`)\n } else {\n pairs.push(`${k}=${v}`)\n }\n }\n }\n return pairs.join(' ')\n }\n return String(value)\n}\n\nfunction prettyPrintWideEvent(event: Record<string, unknown>): void {\n const { timestamp, level, service, environment, version, ...rest } = event\n const levelColor = getLevelColor(level as string)\n const ts = (timestamp as string).slice(11, 23)\n\n let header = `${colors.dim}${ts}${colors.reset} ${levelColor}${(level as string).toUpperCase()}${colors.reset}`\n header += ` ${colors.cyan}[${service}]${colors.reset}`\n\n if (rest.method && rest.path) {\n header += ` ${rest.method} ${rest.path}`\n delete rest.method\n delete rest.path\n }\n\n if (rest.status) {\n const statusColor = (rest.status as number) >= 400 ? colors.red : colors.green\n header += ` ${statusColor}${rest.status}${colors.reset}`\n delete rest.status\n }\n\n if (rest.duration) {\n header += ` ${colors.dim}in ${rest.duration}${colors.reset}`\n delete rest.duration\n }\n\n console.log(header)\n\n const entries = Object.entries(rest).filter(([_, v]) => v !== undefined)\n const lastIndex = entries.length - 1\n\n entries.forEach(([key, value], index) => {\n const isLast = index === lastIndex\n const prefix = isLast ? '└─' : '├─'\n const formatted = formatValue(value)\n console.log(` ${colors.dim}${prefix}${colors.reset} ${colors.cyan}${key}:${colors.reset} ${formatted}`)\n })\n}\n\nfunction createLogMethod(level: LogLevel) {\n return function logMethod(tagOrEvent: string | Record<string, unknown>, message?: string): void {\n if (typeof tagOrEvent === 'string' && message !== undefined) {\n emitTaggedLog(level, tagOrEvent, message)\n } else if (typeof tagOrEvent === 'object') {\n emitWideEvent(level, tagOrEvent)\n } else {\n emitTaggedLog(level, 'log', String(tagOrEvent))\n }\n }\n}\n\n/**\n * Simple logging API - as easy as console.log\n *\n * @example\n * ```ts\n * log.info('auth', 'User logged in')\n * log.error({ action: 'payment', error: 'failed' })\n * ```\n */\nconst _log: Log = {\n info: createLogMethod('info'),\n error: createLogMethod('error'),\n warn: createLogMethod('warn'),\n debug: createLogMethod('debug'),\n}\n\nexport { _log as log }\n\nconst noopLogger: RequestLogger = {\n set() {},\n error() {},\n info() {},\n warn() {},\n emit() {\n return null\n },\n getContext() {\n return {}\n },\n}\n\n/**\n * Create a request-scoped logger for building wide events.\n *\n * @example\n * ```ts\n * const log = createRequestLogger({ method: 'POST', path: '/checkout' })\n * log.set({ user: { id: '123' } })\n * log.set({ cart: { items: 3 } })\n * log.emit()\n * ```\n */\nexport function createRequestLogger<T extends object = Record<string, unknown>>(options: RequestLoggerOptions = {}): RequestLogger<T> {\n if (!globalEnabled) return noopLogger as RequestLogger<T>\n\n const startTime = Date.now()\n let context: Record<string, unknown> = {\n method: options.method,\n path: options.path,\n requestId: options.requestId,\n }\n let hasError = false\n let hasWarn = false\n\n function addRequestLog(level: 'info' | 'warn', message: string): void {\n const entry = {\n level,\n message,\n timestamp: new Date().toISOString(),\n }\n\n const requestLogs = Array.isArray(context.requestLogs)\n ? [...context.requestLogs, entry]\n : [entry]\n\n context = {\n ...context,\n requestLogs,\n }\n }\n\n return {\n set(data: FieldContext<T>): void {\n context = deepDefaults(data as Record<string, unknown>, context) as Record<string, unknown>\n },\n\n error(error: Error | string, errorContext?: FieldContext<T>): void {\n hasError = true\n const err = typeof error === 'string' ? new Error(error) : error\n\n const errorData = {\n ...(errorContext as Record<string, unknown>),\n error: {\n name: err.name,\n message: err.message,\n stack: err.stack,\n ...('status' in err && { status: (err as Record<string, unknown>).status }),\n ...('statusText' in err && { statusText: (err as Record<string, unknown>).statusText }),\n ...('statusCode' in err && { statusCode: (err as Record<string, unknown>).statusCode }),\n ...('statusMessage' in err && { statusMessage: (err as Record<string, unknown>).statusMessage }),\n ...('data' in err && { data: (err as Record<string, unknown>).data }),\n ...('cause' in err && { cause: (err as unknown as Record<string, unknown>).cause }),\n },\n }\n context = deepDefaults(errorData, context) as Record<string, unknown>\n },\n\n info(message: string, infoContext?: FieldContext<T>): void {\n addRequestLog('info', message)\n if (infoContext) {\n const { requestLogs: _, ...rest } = infoContext as Record<string, unknown>\n context = deepDefaults(rest, context) as Record<string, unknown>\n }\n },\n\n warn(message: string, warnContext?: FieldContext<T>): void {\n hasWarn = true\n addRequestLog('warn', message)\n if (warnContext) {\n const { requestLogs: _, ...rest } = warnContext as Record<string, unknown>\n context = deepDefaults(rest, context) as Record<string, unknown>\n }\n },\n\n emit(overrides?: FieldContext<T> & { _forceKeep?: boolean }): WideEvent | null {\n const durationMs = Date.now() - startTime\n const duration = formatDuration(durationMs)\n const level: LogLevel = hasError ? 'error' : hasWarn ? 'warn' : 'info'\n\n // Extract _forceKeep from overrides (set by evlog:emit:keep hook)\n const { _forceKeep, ...restOverrides } = (overrides ?? {}) as Record<string, unknown> & { _forceKeep?: boolean }\n\n // Build tail sampling context\n const tailCtx: TailSamplingContext = {\n status: (context.status ?? restOverrides.status) as number | undefined,\n duration: durationMs,\n path: context.path as string | undefined,\n method: context.method as string | undefined,\n context: { ...context, ...restOverrides },\n }\n\n // Tail sampling: force keep if hook or built-in conditions match\n const forceKeep = _forceKeep || shouldKeep(tailCtx)\n\n // Apply head sampling only if not force-kept\n if (!forceKeep && !shouldSample(level)) {\n return null\n }\n\n return emitWideEvent(level, {\n ...context,\n ...restOverrides,\n duration,\n }, true)\n },\n\n getContext(): FieldContext<T> & Record<string, unknown> {\n return { ...context }\n },\n }\n}\n\n/**\n * Get the current environment context.\n */\nexport function getEnvironment(): EnvironmentContext {\n return { ...globalEnv }\n}\n","import { createRequestLogger, initLogger } from 'evlog'\n\n/**\n * Log level for the Stack logger.\n *\n * Configured via the `STASH_STACK_LOG` environment variable.\n *\n * - `'error'` — Only errors (default when `STASH_STACK_LOG` is not set).\n * - `'info'` — Info and errors.\n * - `'debug'` — Debug, info, and errors.\n */\nexport type LogLevel = 'debug' | 'info' | 'error'\n\nconst validLevels: readonly LogLevel[] = ['debug', 'info', 'error'] as const\n\nfunction levelFromEnv(): LogLevel {\n const env = process.env.STASH_STACK_LOG\n if (env && validLevels.includes(env as LogLevel)) return env as LogLevel\n return 'error'\n}\n\nfunction samplingRatesForLevel(level: LogLevel): Record<string, number> {\n // evlog uses sampling rates: 100 = always emit, 0 = never emit\n switch (level) {\n case 'debug':\n return { debug: 100, info: 100, warn: 100, error: 100 }\n case 'info':\n return { debug: 0, info: 100, warn: 100, error: 100 }\n case 'error':\n default:\n return { debug: 0, info: 0, warn: 0, error: 100 }\n }\n}\n\nlet initialized = false\n\n/**\n * Initialize the Stack logger.\n *\n * The log level is read from the `STASH_STACK_LOG` environment variable.\n * When the variable is not set, the default is `'error'` (errors only).\n *\n * @internal\n */\nexport function initStackLogger(): void {\n if (initialized) return\n initialized = true\n\n const level = levelFromEnv()\n const rates = samplingRatesForLevel(level)\n\n initLogger({\n env: { service: '@cipherstash/stack' },\n enabled: true,\n sampling: { rates },\n })\n}\n\n// Auto-init with defaults on first import\ninitStackLogger()\n\nexport { createRequestLogger }\n\n// Stringify only the first arg (the message string); drop subsequent args\n// which may contain sensitive objects (e.g. encryptConfig, plaintext).\nfunction safeMessage(args: unknown[]): string {\n return typeof args[0] === 'string' ? args[0] : ''\n}\n\n// Logger for simple one-off logs used across Stack interfaces.\nexport const logger = {\n debug(...args: unknown[]) {\n const log = createRequestLogger()\n log.set({\n level: 'debug',\n source: '@cipherstash/stack',\n message: safeMessage(args),\n })\n log.emit()\n },\n info(...args: unknown[]) {\n const log = createRequestLogger()\n log.set({ source: '@cipherstash/stack' })\n log.info(safeMessage(args))\n log.emit()\n },\n warn(...args: unknown[]) {\n const log = createRequestLogger()\n log.warn(safeMessage(args))\n log.emit()\n },\n error(...args: unknown[]) {\n const log = createRequestLogger()\n log.error(safeMessage(args))\n log.emit()\n },\n}\n"],"mappings":";AAEA,SAAgB,eAAe,IAAoB;AACjD,MAAI,KAAK,IACP,QAAO,GAAG,KAAK,MAAM,EAAA,CAAG;AAE1B,SAAO,IAAI,KAAK,KAAM,QAAQ,CAAA,CAAE;;AAWlC,SAAgB,QAAiB;AAC/B,MAAI,OAAO,YAAY,YACrB,QAAO,QAAQ,IAAI,aAAa;AAElC,MAAI,OAAO,WAAW,YACpB,QAAO;AAET,SAAO;;AAGT,SAAgB,oBAAiD;AAC/D,QAAM,MAAM,OAAO,YAAY,cAAc,QAAQ,MAAM,CAAA;AAC3D,QAAM,qBAAqB,MAAA,IAAU,gBAAgB;AAErD,SAAO;IACL,aAAa,IAAI,YAAY;IAC7B,SAAS,IAAI,gBAAgB;IAC7B,SAAS,IAAI;IACb,YAAY,IAAI,cACX,IAAI,cACJ,IAAI,yBACJ,IAAI;IACT,QAAQ,IAAI,iBACP,IAAI,cACJ,IAAI,cACJ,IAAI;;;AAIb,SAAgB,iBAAiB,OAA2B;AAC1D,SAAO;;AAGT,IAAa,SAAS;EACpB,OAAO;EACP,MAAM;EACN,KAAK;EACL,KAAK;EACL,OAAO;EACP,QAAQ;EACR,MAAM;EACN,SAAS;EACT,MAAM;EACN,OAAO;EACP,MAAM;;AAGR,SAAgB,cAAc,OAAuB;AACnD,UAAQ,OAAR;IACE,KAAK;AACH,aAAO,OAAO;IAChB,KAAK;AACH,aAAO,OAAO;IAChB,KAAK;AACH,aAAO,OAAO;IAChB,KAAK;AACH,aAAO,OAAO;IAChB;AACE,aAAO,OAAO;;;AA8BpB,SAAgB,eAAe,MAAc,SAA0B;AACrE,QAAM,eAAe,QAClB,QAAQ,qBAAqB,MAAA,EAC7B,QAAQ,SAAS,cAAA,EACjB,QAAQ,OAAO,OAAA,EACf,QAAQ,iBAAiB,IAAA,EACzB,QAAQ,OAAO,MAAA;AAGlB,SADc,IAAI,OAAO,IAAI,YAAA,GAAa,EAC7B,KAAK,IAAA;;;;AC/GpB,SAAS,cAAc,KAA8C;AACnE,SAAO,QAAQ,QAAQ,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAA;;AAGnE,SAAS,aAAa,MAA+B,UAA4D;AAC/G,QAAM,SAAS,EAAE,GAAG,KAAA;AACpB,aAAW,OAAO,UAAU;AAC1B,UAAM,UAAU,OAAO,GAAA;AACvB,UAAM,aAAa,SAAS,GAAA;AAC5B,QAAI,YAAY,UAAa,YAAY,KACvC,QAAO,GAAA,IAAO;aACL,cAAc,OAAA,KAAY,cAAc,UAAA,EACjD,QAAO,GAAA,IAAO,aAAa,SAAS,UAAA;;AAGxC,SAAO;;AAGT,IAAI,YAAgC;EAClC,SAAS;EACT,aAAa;;AAGf,IAAI,eAAe,MAAA;AACnB,IAAI,iBAAiC,CAAA;AACrC,IAAI,kBAAkB;AACtB,IAAI;AACJ,IAAI,gBAAgB;AAMpB,SAAgB,WAAW,SAAuB,CAAA,GAAU;AAC1D,kBAAgB,OAAO,WAAW;AAClC,QAAM,WAAW,kBAAA;AAEjB,cAAY;IACV,SAAS,OAAO,KAAK,WAAW,SAAS,WAAW;IACpD,aAAa,OAAO,KAAK,eAAe,SAAS,eAAe;IAChE,SAAS,OAAO,KAAK,WAAW,SAAS;IACzC,YAAY,OAAO,KAAK,cAAc,SAAS;IAC/C,QAAQ,OAAO,KAAK,UAAU,SAAS;;AAGzC,iBAAe,OAAO,UAAU,MAAA;AAChC,mBAAiB,OAAO,YAAY,CAAA;AACpC,oBAAkB,OAAO,aAAa;AACtC,gBAAc,OAAO;;AAcvB,SAAS,aAAa,OAA0B;AAC9C,QAAM,EAAE,MAAA,IAAU;AAClB,MAAI,CAAC,MACH,QAAO;AAIT,QAAM,aAAa,UAAU,WAAW,MAAM,UAAU,SACpD,MACA,MAAM,KAAA,KAAU;AAGpB,MAAI,cAAc,EAAG,QAAO;AAC5B,MAAI,cAAc,IAAK,QAAO;AAE9B,SAAO,KAAK,OAAA,IAAW,MAAM;;AAO/B,SAAgB,WAAW,KAAmC;AAC5D,QAAM,EAAE,KAAA,IAAS;AACjB,MAAI,CAAC,MAAM,OAAQ,QAAO;AAE1B,SAAO,KAAK,KAAA,CAAM,cAAc;AAC9B,QAAI,UAAU,WAAW,UAAa,IAAI,WAAW,UAAa,IAAI,UAAU,UAAU,OACxF,QAAO;AAET,QAAI,UAAU,aAAa,UAAa,IAAI,aAAa,UAAa,IAAI,YAAY,UAAU,SAC9F,QAAO;AAET,QAAI,UAAU,QAAQ,IAAI,QAAQ,eAAe,IAAI,MAAM,UAAU,IAAA,EACnE,QAAO;AAET,WAAO;;;AAIX,SAAS,cAAc,OAAiB,OAAgC,oBAAoB,OAAyB;AACnH,MAAI,CAAC,cAAe,QAAO;AAE3B,MAAI,CAAC,qBAAqB,CAAC,aAAa,KAAA,EACtC,QAAO;AAGT,QAAM,YAAuB;IAC3B,YAAW,oBAAI,KAAA,GAAO,YAAA;IACtB;IACA,GAAG;IACH,GAAG;;AAGL,MAAI,aACF,sBAAqB,SAAA;WACZ,gBACT,SAAQ,iBAAiB,KAAA,CAAM,EAAE,KAAK,UAAU,SAAA,CAAU;MAE1D,SAAQ,iBAAiB,KAAA,CAAM,EAAE,SAAA;AAGnC,MAAI,YACF,SAAQ,QAAQ,YAAY,EAAE,OAAO,UAAA,CAAW,CAAC,EAAE,MAAA,CAAO,QAAQ;AAChE,YAAQ,MAAM,yBAAyB,GAAA;;AAI3C,SAAO;;AAGT,SAAS,cAAc,OAAiB,KAAa,SAAuB;AAC1E,MAAI,CAAC,cAAe;AAEpB,MAAI,cAAc;AAChB,QAAI,CAAC,aAAa,KAAA,EAChB;AAEF,UAAM,QAAQ,cAAc,KAAA;AAC5B,UAAM,aAAY,oBAAI,KAAA,GAAO,YAAA,EAAc,MAAM,IAAI,EAAA;AACrD,YAAQ,IAAI,GAAG,OAAO,GAAA,GAAM,SAAA,GAAY,OAAO,KAAA,IAAS,KAAA,IAAS,GAAA,IAAO,OAAO,KAAA,IAAS,OAAA,EAAA;AACxF;;AAEF,gBAAc,OAAO;IAAE;IAAK;GAAS;;AAGvC,SAAS,YAAY,OAAwB;AAC3C,MAAI,UAAU,QAAQ,UAAU,OAC9B,QAAO,OAAO,KAAA;AAEhB,MAAI,OAAO,UAAU,UAAU;AAE7B,UAAM,QAAkB,CAAA;AACxB,eAAW,CAAC,GAAG,CAAA,KAAM,OAAO,QAAQ,KAAA,EAClC,KAAI,MAAM,UAAa,MAAM,KAC3B,KAAI,OAAO,MAAM,SAEf,OAAM,KAAK,GAAG,CAAA,IAAK,KAAK,UAAU,CAAA,CAAE,EAAA;QAEpC,OAAM,KAAK,GAAG,CAAA,IAAK,CAAA,EAAA;AAIzB,WAAO,MAAM,KAAK,GAAA;;AAEpB,SAAO,OAAO,KAAA;;AAGhB,SAAS,qBAAqB,OAAsC;AAClE,QAAM,EAAE,WAAW,OAAO,SAAS,aAAa,SAAS,GAAG,KAAA,IAAS;AACrE,QAAM,aAAa,cAAc,KAAA;AACjC,QAAM,KAAM,UAAqB,MAAM,IAAI,EAAA;AAE3C,MAAI,SAAS,GAAG,OAAO,GAAA,GAAM,EAAA,GAAK,OAAO,KAAA,IAAS,UAAA,GAAc,MAAiB,YAAA,CAAa,GAAG,OAAO,KAAA;AACxG,YAAU,IAAI,OAAO,IAAA,IAAQ,OAAA,IAAW,OAAO,KAAA;AAE/C,MAAI,KAAK,UAAU,KAAK,MAAM;AAC5B,cAAU,IAAI,KAAK,MAAA,IAAU,KAAK,IAAA;AAClC,WAAO,KAAK;AACZ,WAAO,KAAK;;AAGd,MAAI,KAAK,QAAQ;AACf,UAAM,cAAe,KAAK,UAAqB,MAAM,OAAO,MAAM,OAAO;AACzE,cAAU,IAAI,WAAA,GAAc,KAAK,MAAA,GAAS,OAAO,KAAA;AACjD,WAAO,KAAK;;AAGd,MAAI,KAAK,UAAU;AACjB,cAAU,IAAI,OAAO,GAAA,MAAS,KAAK,QAAA,GAAW,OAAO,KAAA;AACrD,WAAO,KAAK;;AAGd,UAAQ,IAAI,MAAA;AAEZ,QAAM,UAAU,OAAO,QAAQ,IAAA,EAAM,OAAA,CAAQ,CAAC,GAAG,CAAA,MAAO,MAAM,MAAA;AAC9D,QAAM,YAAY,QAAQ,SAAS;AAEnC,UAAQ,QAAA,CAAS,CAAC,KAAK,KAAA,GAAQ,UAAU;AAEvC,UAAM,SADS,UAAU,YACD,iBAAO;AAC/B,UAAM,YAAY,YAAY,KAAA;AAC9B,YAAQ,IAAI,KAAK,OAAO,GAAA,GAAM,MAAA,GAAS,OAAO,KAAA,IAAS,OAAO,IAAA,GAAO,GAAA,IAAO,OAAO,KAAA,IAAS,SAAA,EAAA;;;AAIhG,SAAS,gBAAgB,OAAiB;AACxC,SAAO,SAAS,UAAU,YAA8C,SAAwB;AAC9F,QAAI,OAAO,eAAe,YAAY,YAAY,OAChD,eAAc,OAAO,YAAY,OAAA;aACxB,OAAO,eAAe,SAC/B,eAAc,OAAO,UAAA;QAErB,eAAc,OAAO,OAAO,OAAO,UAAA,CAAW;;;AAcpD,IAAM,OAAY;EAChB,MAAM,gBAAgB,MAAA;EACtB,OAAO,gBAAgB,OAAA;EACvB,MAAM,gBAAgB,MAAA;EACtB,OAAO,gBAAgB,OAAA;;AAKzB,IAAM,aAA4B;EAChC,MAAM;EAAA;EACN,QAAQ;EAAA;EACR,OAAO;EAAA;EACP,OAAO;EAAA;EACP,OAAO;AACL,WAAO;;EAET,aAAa;AACX,WAAO,CAAA;;;AAeX,SAAgB,oBAAgE,UAAgC,CAAA,GAAsB;AACpI,MAAI,CAAC,cAAe,QAAO;AAE3B,QAAM,YAAY,KAAK,IAAA;AACvB,MAAI,UAAmC;IACrC,QAAQ,QAAQ;IAChB,MAAM,QAAQ;IACd,WAAW,QAAQ;;AAErB,MAAI,WAAW;AACf,MAAI,UAAU;AAEd,WAAS,cAAc,OAAwB,SAAuB;AACpE,UAAM,QAAQ;MACZ;MACA;MACA,YAAW,oBAAI,KAAA,GAAO,YAAA;;AAGxB,UAAM,cAAc,MAAM,QAAQ,QAAQ,WAAA,IACtC,CAAC,GAAG,QAAQ,aAAa,KAAA,IACzB,CAAC,KAAA;AAEL,cAAU;MACR,GAAG;MACH;;;AAIJ,SAAO;IACL,IAAI,MAA6B;AAC/B,gBAAU,aAAa,MAAiC,OAAA;;IAG1D,MAAM,OAAuB,cAAsC;AACjE,iBAAW;AACX,YAAM,MAAM,OAAO,UAAU,WAAW,IAAI,MAAM,KAAA,IAAS;AAgB3D,gBAAU,aAdQ;QAChB,GAAI;QACJ,OAAO;UACL,MAAM,IAAI;UACV,SAAS,IAAI;UACb,OAAO,IAAI;UACX,GAAI,YAAY,OAAO,EAAE,QAAS,IAAgC,OAAA;UAClE,GAAI,gBAAgB,OAAO,EAAE,YAAa,IAAgC,WAAA;UAC1E,GAAI,gBAAgB,OAAO,EAAE,YAAa,IAAgC,WAAA;UAC1E,GAAI,mBAAmB,OAAO,EAAE,eAAgB,IAAgC,cAAA;UAChF,GAAI,UAAU,OAAO,EAAE,MAAO,IAAgC,KAAA;UAC9D,GAAI,WAAW,OAAO,EAAE,OAAQ,IAA2C,MAAA;;SAG7C,OAAA;;IAGpC,KAAK,SAAiB,aAAqC;AACzD,oBAAc,QAAQ,OAAA;AACtB,UAAI,aAAa;AACf,cAAM,EAAE,aAAa,GAAG,GAAG,KAAA,IAAS;AACpC,kBAAU,aAAa,MAAM,OAAA;;;IAIjC,KAAK,SAAiB,aAAqC;AACzD,gBAAU;AACV,oBAAc,QAAQ,OAAA;AACtB,UAAI,aAAa;AACf,cAAM,EAAE,aAAa,GAAG,GAAG,KAAA,IAAS;AACpC,kBAAU,aAAa,MAAM,OAAA;;;IAIjC,KAAK,WAA0E;AAC7E,YAAM,aAAa,KAAK,IAAA,IAAQ;AAChC,YAAM,WAAW,eAAe,UAAA;AAChC,YAAM,QAAkB,WAAW,UAAU,UAAU,SAAS;AAGhE,YAAM,EAAE,YAAY,GAAG,cAAA,IAAmB,aAAa,CAAA;AAGvD,YAAM,UAA+B;QACnC,QAAS,QAAQ,UAAU,cAAc;QACzC,UAAU;QACV,MAAM,QAAQ;QACd,QAAQ,QAAQ;QAChB,SAAS;UAAE,GAAG;UAAS,GAAG;;;AAO5B,UAAI,EAHc,cAAc,WAAW,OAAA,MAGzB,CAAC,aAAa,KAAA,EAC9B,QAAO;AAGT,aAAO,cAAc,OAAO;QAC1B,GAAG;QACH,GAAG;QACH;SACC,IAAA;;IAGL,aAAwD;AACtD,aAAO,EAAE,GAAG,QAAA;;;;;;ACrWlB,IAAM,cAAmC,CAAC,SAAS,QAAQ,OAAO;AAElE,SAAS,eAAyB;AAChC,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,OAAO,YAAY,SAAS,GAAe,EAAG,QAAO;AACzD,SAAO;AACT;AAEA,SAAS,sBAAsB,OAAyC;AAEtE,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO,EAAE,OAAO,KAAK,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI;AAAA,IACxD,KAAK;AACH,aAAO,EAAE,OAAO,GAAG,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI;AAAA,IACtD,KAAK;AAAA,IACL;AACE,aAAO,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,IAAI;AAAA,EACpD;AACF;AAEA,IAAI,cAAc;AAUX,SAAS,kBAAwB;AACtC,MAAI,YAAa;AACjB,gBAAc;AAEd,QAAM,QAAQ,aAAa;AAC3B,QAAM,QAAQ,sBAAsB,KAAK;AAEzC,aAAW;AAAA,IACT,KAAK,EAAE,SAAS,qBAAqB;AAAA,IACrC,SAAS;AAAA,IACT,UAAU,EAAE,MAAM;AAAA,EACpB,CAAC;AACH;AAGA,gBAAgB;AAMhB,SAAS,YAAY,MAAyB;AAC5C,SAAO,OAAO,KAAK,CAAC,MAAM,WAAW,KAAK,CAAC,IAAI;AACjD;AAGO,IAAM,SAAS;AAAA,EACpB,SAAS,MAAiB;AACxB,UAAM,MAAM,oBAAoB;AAChC,QAAI,IAAI;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS,YAAY,IAAI;AAAA,IAC3B,CAAC;AACD,QAAI,KAAK;AAAA,EACX;AAAA,EACA,QAAQ,MAAiB;AACvB,UAAM,MAAM,oBAAoB;AAChC,QAAI,IAAI,EAAE,QAAQ,qBAAqB,CAAC;AACxC,QAAI,KAAK,YAAY,IAAI,CAAC;AAC1B,QAAI,KAAK;AAAA,EACX;AAAA,EACA,QAAQ,MAAiB;AACvB,UAAM,MAAM,oBAAoB;AAChC,QAAI,KAAK,YAAY,IAAI,CAAC;AAC1B,QAAI,KAAK;AAAA,EACX;AAAA,EACA,SAAS,MAAiB;AACxB,UAAM,MAAM,oBAAoB;AAChC,QAAI,MAAM,YAAY,IAAI,CAAC;AAC3B,QAAI,KAAK;AAAA,EACX;AACF;","names":[]}