@cipherstash/stack 0.4.0 → 0.5.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 (80) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +9 -36
  3. package/dist/bin/stash.js +215 -179
  4. package/dist/bin/stash.js.map +1 -1
  5. package/dist/{chunk-OAPLZLR5.js → chunk-GXGEW6T4.js} +2 -76
  6. package/dist/chunk-GXGEW6T4.js.map +1 -0
  7. package/dist/{chunk-KOU2MHXJ.js → chunk-HCL75LXQ.js} +1 -1
  8. package/dist/chunk-HCL75LXQ.js.map +1 -0
  9. package/dist/chunk-LBMC4D6D.js +19 -0
  10. package/dist/chunk-LBMC4D6D.js.map +1 -0
  11. package/dist/chunk-Q5FTQLYG.js +68 -0
  12. package/dist/chunk-Q5FTQLYG.js.map +1 -0
  13. package/dist/{chunk-WUZGKTMG.js → chunk-TGUELLJS.js} +16 -19
  14. package/dist/chunk-TGUELLJS.js.map +1 -0
  15. package/dist/chunk-YLISU7FD.js +357 -0
  16. package/dist/chunk-YLISU7FD.js.map +1 -0
  17. package/dist/{client-CUGXheRq.d.cts → client-BFrHTgC6.d.ts} +36 -3
  18. package/dist/{client-CrGQnSlk.d.ts → client-BVQvgvdY.d.cts} +36 -3
  19. package/dist/client.d.cts +4 -4
  20. package/dist/client.d.ts +4 -4
  21. package/dist/drizzle/index.cjs.map +1 -1
  22. package/dist/drizzle/index.d.cts +14 -6
  23. package/dist/drizzle/index.d.ts +14 -6
  24. package/dist/drizzle/index.js +3 -3
  25. package/dist/drizzle/index.js.map +1 -1
  26. package/dist/dynamodb/index.cjs +68 -0
  27. package/dist/dynamodb/index.cjs.map +1 -1
  28. package/dist/dynamodb/index.d.cts +4 -4
  29. package/dist/dynamodb/index.d.ts +4 -4
  30. package/dist/dynamodb/index.js +9 -0
  31. package/dist/dynamodb/index.js.map +1 -1
  32. package/dist/encryption/index.cjs +2572 -0
  33. package/dist/encryption/index.cjs.map +1 -0
  34. package/dist/encryption/index.d.cts +7 -0
  35. package/dist/encryption/index.d.ts +7 -0
  36. package/dist/encryption/index.js +17 -0
  37. package/dist/encryption/index.js.map +1 -0
  38. package/dist/errors/index.cjs +44 -0
  39. package/dist/errors/index.cjs.map +1 -0
  40. package/dist/errors/index.d.cts +94 -0
  41. package/dist/errors/index.d.ts +94 -0
  42. package/dist/errors/index.js +9 -0
  43. package/dist/errors/index.js.map +1 -0
  44. package/dist/identity/index.cjs +21 -13
  45. package/dist/identity/index.cjs.map +1 -1
  46. package/dist/identity/index.d.cts +78 -2
  47. package/dist/identity/index.d.ts +78 -2
  48. package/dist/identity/index.js +7 -3
  49. package/dist/identity/index.js.map +1 -1
  50. package/dist/index.cjs +379 -41
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +21 -19
  53. package/dist/index.d.ts +21 -19
  54. package/dist/index.js +14 -8
  55. package/dist/schema/index.d.cts +1 -2
  56. package/dist/schema/index.d.ts +1 -2
  57. package/dist/secrets/index.cjs +70 -39
  58. package/dist/secrets/index.cjs.map +1 -1
  59. package/dist/secrets/index.d.cts +4 -6
  60. package/dist/secrets/index.d.ts +4 -6
  61. package/dist/secrets/index.js +9 -318
  62. package/dist/secrets/index.js.map +1 -1
  63. package/dist/supabase/index.cjs +84 -1
  64. package/dist/supabase/index.cjs.map +1 -1
  65. package/dist/supabase/index.d.cts +4 -4
  66. package/dist/supabase/index.d.ts +4 -4
  67. package/dist/supabase/index.js +24 -1
  68. package/dist/supabase/index.js.map +1 -1
  69. package/dist/{types-public-Wj6tB_ux.d.ts → types-public-dKxDzTIL.d.cts} +1 -9
  70. package/dist/{types-public-Wj6tB_ux.d.cts → types-public-dKxDzTIL.d.ts} +1 -9
  71. package/dist/types-public.cjs.map +1 -1
  72. package/dist/types-public.d.cts +1 -2
  73. package/dist/types-public.d.ts +1 -2
  74. package/dist/types-public.js +1 -1
  75. package/package.json +29 -1
  76. package/dist/chunk-KOU2MHXJ.js.map +0 -1
  77. package/dist/chunk-OAPLZLR5.js.map +0 -1
  78. package/dist/chunk-WUZGKTMG.js.map +0 -1
  79. package/dist/index-9-Ya3fDK.d.cts +0 -169
  80. package/dist/index-9-Ya3fDK.d.ts +0 -169
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @cipherstash/stack
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a645115: ### Documentation
8
+
9
+ - **TypeDoc**: Improved JSDoc for `Encryption()`, `EncryptOptions`, schema builders (`encryptedTable`, `encryptedColumn`, `encryptedField`, `EncryptedField`, `EncryptedTableColumn`), and `encrypt` / `bulkEncrypt` with clearer `@param`, `@returns`, `@throws`, `@example`, and `@see` links.
10
+ - **README**: Refreshed main repo README and Stack package readme; basic example README now uses `npm install @cipherstash/stack`, CipherStash account and dashboard credentials, and drops Stash CLI references. Added docs badge linking to cipherstash.com/docs.
11
+
12
+ ### Features
13
+
14
+ - **Logging**: Logger is now used consistently across Stack client interfaces for initialization and operations.
15
+
3
16
  ## 0.4.0
4
17
 
5
18
  ### Minor Changes
package/README.md CHANGED
@@ -502,48 +502,21 @@ const client2 = await Encryption({
502
502
 
503
503
  ### Logging
504
504
 
505
- The SDK uses [evlog](https://github.com/HugoRCD/evlog) for structured logging. Each encryption operation emits a single wide event with context such as the operation type, table, column, lock context status, and duration.
505
+ The SDK uses structured logging across all interfaces (Encryption, Secrets, Supabase, DynamoDB). Each operation emits a single wide event with context such as the operation type, table, column, lock context status, and duration.
506
506
 
507
- #### Environment variable
507
+ Configure the log level with the `STASH_STACK_LOG` environment variable:
508
508
 
509
509
  ```bash
510
- STASH_LOG_LEVEL=debug # debug | info | warn | error (default: info)
510
+ STASH_STACK_LOG=error # debug | info | error (default: error)
511
511
  ```
512
512
 
513
- #### Programmatic configuration
513
+ | Value | What is logged |
514
+ | ------- | ---------------------- |
515
+ | `error` | Errors only (default) |
516
+ | `info` | Info and errors |
517
+ | `debug` | Debug, info, and errors |
514
518
 
515
- Pass a `logging` option when initializing the client:
516
-
517
- ```typescript
518
- const client = await Encryption({
519
- schemas: [users],
520
- logging: {
521
- enabled: true, // toggle logging on/off (default: true)
522
- pretty: true, // pretty-print in development (default: auto-detected)
523
- },
524
- })
525
- ```
526
-
527
- #### Log draining
528
-
529
- Send structured logs to an external observability platform by providing a `drain` callback:
530
-
531
- ```typescript
532
- import { Encryption } from "@cipherstash/stack"
533
-
534
- const client = await Encryption({
535
- schemas: [users],
536
- logging: {
537
- drain: (ctx) => {
538
- // Forward to Axiom, Datadog, OTLP, etc.
539
- fetch("https://your-service.com/logs", {
540
- method: "POST",
541
- body: JSON.stringify(ctx.event),
542
- })
543
- },
544
- },
545
- })
546
- ```
519
+ When `STASH_STACK_LOG` is not set, the SDK defaults to `error` (errors only).
547
520
 
548
521
  The SDK never logs plaintext data.
549
522
 
package/dist/bin/stash.js CHANGED
@@ -1125,13 +1125,71 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
1125
1125
  } };
1126
1126
  };
1127
1127
 
1128
- // src/bin/commands/init/types.ts
1129
- var CancelledError = class extends Error {
1130
- constructor() {
1131
- super("cancelled");
1132
- this.name = "CancelledError";
1133
- }
1134
- };
1128
+ // src/bin/commands/init/providers/base.ts
1129
+ function createBaseProvider() {
1130
+ return {
1131
+ name: "base",
1132
+ introMessage: "Setting up CipherStash for your project...",
1133
+ connectionOptions: [
1134
+ { value: "drizzle", label: "Drizzle ORM", hint: "recommended" },
1135
+ { value: "prisma", label: "Prisma" },
1136
+ { value: "raw-sql", label: "Raw SQL / pg" }
1137
+ ],
1138
+ getNextSteps(state) {
1139
+ const steps = [
1140
+ "Install @cipherstash/stack: npm install @cipherstash/stack"
1141
+ ];
1142
+ if (state.connectionMethod === "drizzle") {
1143
+ steps.push("Import encryptedType from @cipherstash/stack/drizzle");
1144
+ } else if (state.connectionMethod === "prisma") {
1145
+ steps.push("Set up Prisma with @cipherstash/stack");
1146
+ }
1147
+ steps.push(
1148
+ "Define your encrypted schema",
1149
+ "Read the docs: https://docs.cipherstash.com"
1150
+ );
1151
+ return steps;
1152
+ }
1153
+ };
1154
+ }
1155
+
1156
+ // src/bin/commands/init/providers/supabase.ts
1157
+ function createSupabaseProvider() {
1158
+ return {
1159
+ name: "supabase",
1160
+ introMessage: "Setting up CipherStash for your Supabase project...",
1161
+ connectionOptions: [
1162
+ {
1163
+ value: "supabase-js",
1164
+ label: "Supabase JS Client",
1165
+ hint: "recommended"
1166
+ },
1167
+ { value: "drizzle", label: "Drizzle ORM" },
1168
+ { value: "prisma", label: "Prisma" },
1169
+ { value: "raw-sql", label: "Raw SQL / pg" }
1170
+ ],
1171
+ getNextSteps(state) {
1172
+ const steps = [
1173
+ "Install @cipherstash/stack: npm install @cipherstash/stack"
1174
+ ];
1175
+ if (state.connectionMethod === "supabase-js") {
1176
+ steps.push("Import encryptedSupabase from @cipherstash/stack/supabase");
1177
+ } else if (state.connectionMethod === "drizzle") {
1178
+ steps.push("Import encryptedType from @cipherstash/stack/drizzle");
1179
+ } else if (state.connectionMethod === "prisma") {
1180
+ steps.push("Set up Prisma with @cipherstash/stack");
1181
+ }
1182
+ steps.push(
1183
+ "Define your encrypted schema",
1184
+ "Supabase guides: https://cipherstash.com/docs/supabase/encrypt-user-data",
1185
+ "Multi-tenant encryption: https://docs.cipherstash.com/docs/multi-tenant",
1186
+ "Migrating existing data: https://docs.cipherstash.com/docs/migration",
1187
+ "Need help? #supabase in Discord or support@cipherstash.com"
1188
+ );
1189
+ return steps;
1190
+ }
1191
+ };
1192
+ }
1135
1193
 
1136
1194
  // src/bin/commands/init/stubs.ts
1137
1195
  function delay(ms) {
@@ -1174,6 +1232,14 @@ async function installEqlExtension(databaseUrl) {
1174
1232
  await delay(1500);
1175
1233
  }
1176
1234
 
1235
+ // src/bin/commands/init/types.ts
1236
+ var CancelledError = class extends Error {
1237
+ constructor() {
1238
+ super("cancelled");
1239
+ this.name = "CancelledError";
1240
+ }
1241
+ };
1242
+
1177
1243
  // src/bin/commands/init/steps/authenticate.ts
1178
1244
  var authenticateStep = {
1179
1245
  id: "authenticate",
@@ -1195,78 +1261,6 @@ Code: ${userCode}`,
1195
1261
  }
1196
1262
  };
1197
1263
 
1198
- // src/bin/commands/init/steps/select-workspace.ts
1199
- var selectWorkspaceStep = {
1200
- id: "select-workspace",
1201
- name: "Select workspace",
1202
- async run(state, _provider) {
1203
- const s = Y2();
1204
- s.start("Loading workspaces...");
1205
- const workspaces = await fetchWorkspaces(state.accessToken);
1206
- s.stop("Workspaces loaded");
1207
- const options = [
1208
- ...workspaces.map((ws2) => ({ value: ws2.id, label: ws2.name })),
1209
- { value: "__create__", label: "Create new workspace" }
1210
- ];
1211
- const selected = await ve({
1212
- message: "Select a workspace",
1213
- options
1214
- });
1215
- if (pD(selected)) throw new CancelledError();
1216
- if (selected === "__create__") {
1217
- const name = await he({
1218
- message: "What should we call your new workspace?",
1219
- placeholder: "my-project",
1220
- validate: (val) => {
1221
- if (!val.trim()) return "Workspace name is required";
1222
- }
1223
- });
1224
- if (pD(name)) throw new CancelledError();
1225
- const s2 = Y2();
1226
- s2.start("Creating workspace...");
1227
- const ws2 = await createWorkspace(state.accessToken, name);
1228
- s2.stop(`Workspace created: ${ws2.name}`);
1229
- return { ...state, workspaceId: ws2.id, workspaceName: ws2.name };
1230
- }
1231
- const ws = workspaces.find((w2) => w2.id === selected);
1232
- return { ...state, workspaceId: ws.id, workspaceName: ws.name };
1233
- }
1234
- };
1235
-
1236
- // src/bin/commands/init/steps/select-region.ts
1237
- var REGIONS = [
1238
- { value: "ap-southeast-2", label: "Asia Pacific (Sydney)" },
1239
- { value: "us-east-1", label: "US East (N. Virginia)" },
1240
- { value: "us-west-2", label: "US West (Oregon)" },
1241
- { value: "eu-west-1", label: "Europe (Ireland)" }
1242
- ];
1243
- var selectRegionStep = {
1244
- id: "select-region",
1245
- name: "Select region",
1246
- async run(state, _provider) {
1247
- const region = await ve({
1248
- message: "Where should we create your workspace?",
1249
- options: REGIONS
1250
- });
1251
- if (pD(region)) throw new CancelledError();
1252
- return { ...state, region };
1253
- }
1254
- };
1255
-
1256
- // src/bin/commands/init/steps/select-connection.ts
1257
- var selectConnectionStep = {
1258
- id: "select-connection",
1259
- name: "Select connection method",
1260
- async run(state, provider) {
1261
- const method = await ve({
1262
- message: "How will you connect to your database?",
1263
- options: provider.connectionOptions
1264
- });
1265
- if (pD(method)) throw new CancelledError();
1266
- return { ...state, connectionMethod: method };
1267
- }
1268
- };
1269
-
1270
1264
  // src/bin/commands/init/steps/detect-database-url.ts
1271
1265
  function maskUrl(url) {
1272
1266
  return url.replace(/:\/\/([^:]+):([^@]+)@/, "://***@");
@@ -1296,7 +1290,8 @@ var detectDatabaseUrlStep = {
1296
1290
  placeholder: "postgresql://user:password@host:5432/database",
1297
1291
  validate: (val) => {
1298
1292
  if (!val.trim()) return "Database URL is required";
1299
- if (!val.startsWith("postgres")) return "Must be a PostgreSQL connection string";
1293
+ if (!val.startsWith("postgres"))
1294
+ return "Must be a PostgreSQL connection string";
1300
1295
  }
1301
1296
  });
1302
1297
  if (pD(url)) throw new CancelledError();
@@ -1358,67 +1353,77 @@ var nextStepsStep = {
1358
1353
  }
1359
1354
  };
1360
1355
 
1361
- // src/bin/commands/init/providers/supabase.ts
1362
- function createSupabaseProvider() {
1363
- return {
1364
- name: "supabase",
1365
- introMessage: "Setting up CipherStash for your Supabase project...",
1366
- connectionOptions: [
1367
- { value: "supabase-js", label: "Supabase JS Client", hint: "recommended" },
1368
- { value: "drizzle", label: "Drizzle ORM" },
1369
- { value: "prisma", label: "Prisma" },
1370
- { value: "raw-sql", label: "Raw SQL / pg" }
1371
- ],
1372
- getNextSteps(state) {
1373
- const steps = [
1374
- "Install @cipherstash/stack: npm install @cipherstash/stack"
1375
- ];
1376
- if (state.connectionMethod === "supabase-js") {
1377
- steps.push("Import encryptedSupabase from @cipherstash/stack/supabase");
1378
- } else if (state.connectionMethod === "drizzle") {
1379
- steps.push("Import encryptedType from @cipherstash/stack/drizzle");
1380
- } else if (state.connectionMethod === "prisma") {
1381
- steps.push("Set up Prisma with @cipherstash/stack");
1382
- }
1383
- steps.push(
1384
- "Define your encrypted schema",
1385
- "Supabase guides: https://cipherstash.com/docs/supabase/encrypt-user-data",
1386
- "Multi-tenant encryption: https://docs.cipherstash.com/docs/multi-tenant",
1387
- "Migrating existing data: https://docs.cipherstash.com/docs/migration",
1388
- "Need help? #supabase in Discord or support@cipherstash.com"
1389
- );
1390
- return steps;
1391
- }
1392
- };
1393
- }
1356
+ // src/bin/commands/init/steps/select-connection.ts
1357
+ var selectConnectionStep = {
1358
+ id: "select-connection",
1359
+ name: "Select connection method",
1360
+ async run(state, provider) {
1361
+ const method = await ve({
1362
+ message: "How will you connect to your database?",
1363
+ options: provider.connectionOptions
1364
+ });
1365
+ if (pD(method)) throw new CancelledError();
1366
+ return { ...state, connectionMethod: method };
1367
+ }
1368
+ };
1394
1369
 
1395
- // src/bin/commands/init/providers/base.ts
1396
- function createBaseProvider() {
1397
- return {
1398
- name: "base",
1399
- introMessage: "Setting up CipherStash for your project...",
1400
- connectionOptions: [
1401
- { value: "drizzle", label: "Drizzle ORM", hint: "recommended" },
1402
- { value: "prisma", label: "Prisma" },
1403
- { value: "raw-sql", label: "Raw SQL / pg" }
1404
- ],
1405
- getNextSteps(state) {
1406
- const steps = [
1407
- "Install @cipherstash/stack: npm install @cipherstash/stack"
1408
- ];
1409
- if (state.connectionMethod === "drizzle") {
1410
- steps.push("Import encryptedType from @cipherstash/stack/drizzle");
1411
- } else if (state.connectionMethod === "prisma") {
1412
- steps.push("Set up Prisma with @cipherstash/stack");
1413
- }
1414
- steps.push(
1415
- "Define your encrypted schema",
1416
- "Read the docs: https://docs.cipherstash.com"
1417
- );
1418
- return steps;
1370
+ // src/bin/commands/init/steps/select-region.ts
1371
+ var REGIONS = [
1372
+ { value: "ap-southeast-2", label: "Asia Pacific (Sydney)" },
1373
+ { value: "us-east-1", label: "US East (N. Virginia)" },
1374
+ { value: "us-west-2", label: "US West (Oregon)" },
1375
+ { value: "eu-west-1", label: "Europe (Ireland)" }
1376
+ ];
1377
+ var selectRegionStep = {
1378
+ id: "select-region",
1379
+ name: "Select region",
1380
+ async run(state, _provider) {
1381
+ const region = await ve({
1382
+ message: "Where should we create your workspace?",
1383
+ options: REGIONS
1384
+ });
1385
+ if (pD(region)) throw new CancelledError();
1386
+ return { ...state, region };
1387
+ }
1388
+ };
1389
+
1390
+ // src/bin/commands/init/steps/select-workspace.ts
1391
+ var selectWorkspaceStep = {
1392
+ id: "select-workspace",
1393
+ name: "Select workspace",
1394
+ async run(state, _provider) {
1395
+ const s = Y2();
1396
+ s.start("Loading workspaces...");
1397
+ const workspaces = await fetchWorkspaces(state.accessToken);
1398
+ s.stop("Workspaces loaded");
1399
+ const options = [
1400
+ ...workspaces.map((ws2) => ({ value: ws2.id, label: ws2.name })),
1401
+ { value: "__create__", label: "Create new workspace" }
1402
+ ];
1403
+ const selected = await ve({
1404
+ message: "Select a workspace",
1405
+ options
1406
+ });
1407
+ if (pD(selected)) throw new CancelledError();
1408
+ if (selected === "__create__") {
1409
+ const name = await he({
1410
+ message: "What should we call your new workspace?",
1411
+ placeholder: "my-project",
1412
+ validate: (val) => {
1413
+ if (!val.trim()) return "Workspace name is required";
1414
+ }
1415
+ });
1416
+ if (pD(name)) throw new CancelledError();
1417
+ const s2 = Y2();
1418
+ s2.start("Creating workspace...");
1419
+ const ws2 = await createWorkspace(state.accessToken, name);
1420
+ s2.stop(`Workspace created: ${ws2.name}`);
1421
+ return { ...state, workspaceId: ws2.id, workspaceName: ws2.name };
1419
1422
  }
1420
- };
1421
- }
1423
+ const ws = workspaces.find((w2) => w2.id === selected);
1424
+ return { ...state, workspaceId: ws.id, workspaceName: ws.name };
1425
+ }
1426
+ };
1422
1427
 
1423
1428
  // src/bin/commands/init/index.ts
1424
1429
  var PROVIDER_MAP = {
@@ -1501,15 +1506,6 @@ function isEncryptedPayload(value) {
1501
1506
  return true;
1502
1507
  }
1503
1508
 
1504
- // src/errors/index.ts
1505
- var EncryptionErrorTypes = {
1506
- ClientInitError: "ClientInitError",
1507
- EncryptionError: "EncryptionError",
1508
- DecryptionError: "DecryptionError",
1509
- LockContextError: "LockContextError",
1510
- CtsTokenError: "CtsTokenError"
1511
- };
1512
-
1513
1509
  // src/schema/index.ts
1514
1510
  import { z as z2 } from "zod";
1515
1511
  var castAsEnum = z2.enum(["bigint", "boolean", "date", "number", "string", "json", "text"]).default("text");
@@ -1834,6 +1830,15 @@ function buildEncryptConfig(...protectTables) {
1834
1830
  return config3;
1835
1831
  }
1836
1832
 
1833
+ // src/errors/index.ts
1834
+ var EncryptionErrorTypes = {
1835
+ ClientInitError: "ClientInitError",
1836
+ EncryptionError: "EncryptionError",
1837
+ DecryptionError: "DecryptionError",
1838
+ LockContextError: "LockContextError",
1839
+ CtsTokenError: "CtsTokenError"
1840
+ };
1841
+
1837
1842
  // src/utils/config/index.ts
1838
1843
  import fs from "node:fs";
1839
1844
  import path from "node:path";
@@ -1898,26 +1903,34 @@ function loadWorkSpaceId(suppliedCrn) {
1898
1903
  }
1899
1904
 
1900
1905
  // src/utils/logger/index.ts
1901
- import { initLogger, createRequestLogger } from "evlog";
1902
- function samplingFromEnv() {
1903
- const env = process.env.STASH_LOG_LEVEL;
1904
- if (!env) return void 0;
1905
- const levels = ["debug", "info", "warn", "error"];
1906
- const idx = levels.indexOf(env);
1907
- if (idx === -1) return void 0;
1908
- return Object.fromEntries(levels.map((l2, i) => [l2, i >= idx ? 100 : 0]));
1906
+ import { createRequestLogger, initLogger } from "evlog";
1907
+ var validLevels = ["debug", "info", "error"];
1908
+ function levelFromEnv() {
1909
+ const env = process.env.STASH_STACK_LOG;
1910
+ if (env && validLevels.includes(env)) return env;
1911
+ return "error";
1912
+ }
1913
+ function samplingRatesForLevel(level) {
1914
+ switch (level) {
1915
+ case "debug":
1916
+ return { debug: 100, info: 100, warn: 100, error: 100 };
1917
+ case "info":
1918
+ return { debug: 0, info: 100, warn: 100, error: 100 };
1919
+ case "error":
1920
+ default:
1921
+ return { debug: 0, info: 0, warn: 0, error: 100 };
1922
+ }
1909
1923
  }
1910
1924
  var initialized = false;
1911
- function initStackLogger(config3) {
1925
+ function initStackLogger() {
1912
1926
  if (initialized) return;
1913
1927
  initialized = true;
1914
- const rates = samplingFromEnv();
1928
+ const level = levelFromEnv();
1929
+ const rates = samplingRatesForLevel(level);
1915
1930
  initLogger({
1916
1931
  env: { service: "@cipherstash/stack" },
1917
- enabled: config3?.enabled ?? !!rates,
1918
- pretty: config3?.pretty,
1919
- ...rates && { sampling: { rates } },
1920
- ...config3?.drain && { drain: config3.drain }
1932
+ enabled: true,
1933
+ sampling: { rates }
1921
1934
  });
1922
1935
  }
1923
1936
  initStackLogger();
@@ -1955,6 +1968,7 @@ var logger = {
1955
1968
  // src/encryption/index.ts
1956
1969
  import { withResult as withResult11 } from "@byteslice/result";
1957
1970
  import { newClient } from "@cipherstash/protect-ffi";
1971
+ import { validate as uuidValidate } from "uuid";
1958
1972
 
1959
1973
  // src/encryption/helpers/type-guards.ts
1960
1974
  function isScalarQueryTermArray(value) {
@@ -4245,23 +4259,14 @@ var EncryptionClient = class {
4245
4259
  };
4246
4260
  }
4247
4261
  };
4248
-
4249
- // src/index.ts
4250
- function isValidUuid(uuid) {
4251
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
4252
- return uuidRegex.test(uuid);
4253
- }
4254
4262
  var Encryption = async (config3) => {
4255
- if (config3.logging) {
4256
- initStackLogger(config3.logging);
4257
- }
4258
4263
  const { schemas, config: clientConfig } = config3;
4259
4264
  if (!schemas.length) {
4260
4265
  throw new Error(
4261
4266
  "[encryption]: At least one encryptedTable must be provided to initialize the encryption client"
4262
4267
  );
4263
4268
  }
4264
- if (clientConfig?.keyset && "id" in clientConfig.keyset && !isValidUuid(clientConfig.keyset.id)) {
4269
+ if (clientConfig?.keyset && "id" in clientConfig.keyset && !uuidValidate(clientConfig.keyset.id)) {
4265
4270
  throw new Error(
4266
4271
  "[encryption]: Invalid UUID provided for keyset id. Must be a valid UUID."
4267
4272
  );
@@ -4287,7 +4292,22 @@ var Secrets = class {
4287
4292
  value: encryptedColumn("value")
4288
4293
  });
4289
4294
  constructor(config3) {
4290
- this.config = config3;
4295
+ const workspaceCRN = config3.workspaceCRN ?? process.env.CS_WORKSPACE_CRN;
4296
+ const clientId = config3.clientId ?? process.env.CS_CLIENT_ID;
4297
+ const clientKey = config3.clientKey ?? process.env.CS_CLIENT_KEY;
4298
+ const accessKey = config3.accessKey ?? process.env.CS_CLIENT_ACCESS_KEY;
4299
+ if (!workspaceCRN || !clientId || !clientKey || !accessKey) {
4300
+ throw new Error(
4301
+ "Missing required configuration or environment variables."
4302
+ );
4303
+ }
4304
+ this.config = {
4305
+ environment: config3.environment,
4306
+ workspaceCRN,
4307
+ clientId,
4308
+ clientKey,
4309
+ accessKey
4310
+ };
4291
4311
  }
4292
4312
  initPromise = null;
4293
4313
  /**
@@ -4300,24 +4320,24 @@ var Secrets = class {
4300
4320
  return this.initPromise;
4301
4321
  }
4302
4322
  async _doInit() {
4323
+ logger.debug("Initializing the Secrets client.");
4303
4324
  this.encryptionClient = await Encryption({
4304
4325
  schemas: [this.secretsSchema],
4305
4326
  config: {
4306
4327
  workspaceCrn: this.config.workspaceCRN,
4307
4328
  clientId: this.config.clientId,
4308
4329
  clientKey: this.config.clientKey,
4309
- accessKey: this.config.apiKey,
4310
- keyset: {
4311
- name: this.config.environment
4312
- }
4330
+ accessKey: this.config.accessKey,
4331
+ keyset: { name: this.config.environment }
4313
4332
  }
4314
4333
  });
4334
+ logger.debug("Successfully initialized the Secrets client.");
4315
4335
  }
4316
4336
  /**
4317
4337
  * Get the authorization header for API requests
4318
4338
  */
4319
4339
  getAuthHeader() {
4320
- return `Bearer ${this.config.apiKey}`;
4340
+ return `Bearer ${this.config.accessKey}`;
4321
4341
  }
4322
4342
  /**
4323
4343
  * Make an API request with error handling.
@@ -4332,6 +4352,7 @@ var Secrets = class {
4332
4352
  const searchParams = new URLSearchParams(options.params);
4333
4353
  url = `${url}?${searchParams.toString()}`;
4334
4354
  }
4355
+ logger.debug(`Secrets API request: ${method} ${path2}`);
4335
4356
  const headers = {
4336
4357
  "Content-Type": "application/json",
4337
4358
  Authorization: this.getAuthHeader()
@@ -4350,6 +4371,7 @@ var Secrets = class {
4350
4371
  } catch {
4351
4372
  errorMessage = errorText || errorMessage;
4352
4373
  }
4374
+ logger.error(`Secrets API error on ${method} ${path2}: ${errorMessage}`);
4353
4375
  return {
4354
4376
  failure: {
4355
4377
  type: "ApiError",
@@ -4357,13 +4379,16 @@ var Secrets = class {
4357
4379
  }
4358
4380
  };
4359
4381
  }
4382
+ logger.debug(`Secrets API request successful: ${method} ${path2}`);
4360
4383
  const data = await response.json();
4361
4384
  return { data };
4362
4385
  } catch (error) {
4386
+ const message = error instanceof Error ? error.message : "Unknown network error occurred";
4387
+ logger.error(`Secrets network error on ${method} ${path2}: ${message}`);
4363
4388
  return {
4364
4389
  failure: {
4365
4390
  type: "NetworkError",
4366
- message: error instanceof Error ? error.message : "Unknown network error occurred"
4391
+ message
4367
4392
  }
4368
4393
  };
4369
4394
  }
@@ -4379,6 +4404,7 @@ var Secrets = class {
4379
4404
  * @returns A Result containing the API response or an error
4380
4405
  */
4381
4406
  async set(name, value) {
4407
+ logger.debug("Setting secret");
4382
4408
  await this.ensureInitialized();
4383
4409
  if (!this.encryptionClient) {
4384
4410
  return {
@@ -4393,6 +4419,7 @@ var Secrets = class {
4393
4419
  table: this.secretsSchema
4394
4420
  });
4395
4421
  if (encryptResult.failure) {
4422
+ logger.error("Failed to encrypt secret");
4396
4423
  return {
4397
4424
  failure: {
4398
4425
  type: "EncryptionError",
@@ -4420,6 +4447,7 @@ var Secrets = class {
4420
4447
  * @returns A Result containing the decrypted value or an error
4421
4448
  */
4422
4449
  async get(name) {
4450
+ logger.debug("Getting secret");
4423
4451
  await this.ensureInitialized();
4424
4452
  if (!this.encryptionClient) {
4425
4453
  return {
@@ -4444,6 +4472,7 @@ var Secrets = class {
4444
4472
  apiResult.data.encryptedValue.data
4445
4473
  );
4446
4474
  if (decryptResult.failure) {
4475
+ logger.error("Failed to decrypt secret");
4447
4476
  return {
4448
4477
  failure: {
4449
4478
  type: "DecryptionError",
@@ -4452,6 +4481,7 @@ var Secrets = class {
4452
4481
  };
4453
4482
  }
4454
4483
  if (typeof decryptResult.data !== "string") {
4484
+ logger.error("Decrypted secret value is not a string");
4455
4485
  return {
4456
4486
  failure: {
4457
4487
  type: "DecryptionError",
@@ -4476,6 +4506,7 @@ var Secrets = class {
4476
4506
  * @returns A Result containing an object mapping secret names to their decrypted values
4477
4507
  */
4478
4508
  async getMany(names) {
4509
+ logger.debug(`Getting ${names.length} secrets.`);
4479
4510
  await this.ensureInitialized();
4480
4511
  if (!this.encryptionClient) {
4481
4512
  return {
@@ -4522,6 +4553,9 @@ var Secrets = class {
4522
4553
  }));
4523
4554
  const decryptResult = await this.encryptionClient.bulkDecryptModels(dataToDecrypt);
4524
4555
  if (decryptResult.failure) {
4556
+ logger.error(
4557
+ `Failed to decrypt secrets: ${decryptResult.failure.message}`
4558
+ );
4525
4559
  return {
4526
4560
  failure: {
4527
4561
  type: "DecryptionError",
@@ -4547,6 +4581,7 @@ var Secrets = class {
4547
4581
  * @returns A Result containing the list of secrets or an error
4548
4582
  */
4549
4583
  async list() {
4584
+ logger.debug("Listing secrets.");
4550
4585
  const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
4551
4586
  const apiResult = await this.apiRequest(
4552
4587
  "GET",
@@ -4572,6 +4607,7 @@ var Secrets = class {
4572
4607
  * @returns A Result containing the API response or an error
4573
4608
  */
4574
4609
  async delete(name) {
4610
+ logger.debug("Deleting secret");
4575
4611
  const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
4576
4612
  return await this.apiRequest("POST", "/delete", {
4577
4613
  body: {