@cipherstash/stack 0.3.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.
- package/CHANGELOG.md +19 -0
- package/README.md +10 -37
- package/dist/bin/stash.js +261 -320
- package/dist/bin/stash.js.map +1 -1
- package/dist/{chunk-SUYMGQBY.js → chunk-4RNBI3UH.js} +1 -7
- package/dist/chunk-4RNBI3UH.js.map +1 -0
- package/dist/{chunk-OAPLZLR5.js → chunk-GXGEW6T4.js} +2 -76
- package/dist/chunk-GXGEW6T4.js.map +1 -0
- package/dist/{chunk-JLI27P46.js → chunk-HCL75LXQ.js} +1 -1
- package/dist/chunk-HCL75LXQ.js.map +1 -0
- package/dist/chunk-LBMC4D6D.js +19 -0
- package/dist/chunk-LBMC4D6D.js.map +1 -0
- package/dist/chunk-Q5FTQLYG.js +68 -0
- package/dist/chunk-Q5FTQLYG.js.map +1 -0
- package/dist/{chunk-MW6D52V2.js → chunk-TGUELLJS.js} +58 -150
- package/dist/chunk-TGUELLJS.js.map +1 -0
- package/dist/{chunk-TBAIVO6T.js → chunk-Y35W4WFN.js} +6 -6
- package/dist/chunk-Y35W4WFN.js.map +1 -0
- package/dist/chunk-YLISU7FD.js +357 -0
- package/dist/chunk-YLISU7FD.js.map +1 -0
- package/dist/{client-Bf0Xw2xo.d.cts → client-BFrHTgC6.d.ts} +50 -18
- package/dist/{client-Kfp8OsPB.d.ts → client-BVQvgvdY.d.cts} +50 -18
- package/dist/client.cjs +5 -5
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +4 -4
- package/dist/client.d.ts +4 -4
- package/dist/client.js +1 -1
- package/dist/drizzle/index.cjs +5 -5
- package/dist/drizzle/index.cjs.map +1 -1
- package/dist/drizzle/index.d.cts +14 -6
- package/dist/drizzle/index.d.ts +14 -6
- package/dist/drizzle/index.js +4 -4
- package/dist/drizzle/index.js.map +1 -1
- package/dist/dynamodb/index.cjs +68 -0
- package/dist/dynamodb/index.cjs.map +1 -1
- package/dist/dynamodb/index.d.cts +4 -4
- package/dist/dynamodb/index.d.ts +4 -4
- package/dist/dynamodb/index.js +9 -0
- package/dist/dynamodb/index.js.map +1 -1
- package/dist/encryption/index.cjs +2572 -0
- package/dist/encryption/index.cjs.map +1 -0
- package/dist/encryption/index.d.cts +7 -0
- package/dist/encryption/index.d.ts +7 -0
- package/dist/encryption/index.js +17 -0
- package/dist/encryption/index.js.map +1 -0
- package/dist/errors/index.cjs +44 -0
- package/dist/errors/index.cjs.map +1 -0
- package/dist/errors/index.d.cts +94 -0
- package/dist/errors/index.d.ts +94 -0
- package/dist/errors/index.js +9 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/identity/index.cjs +21 -13
- package/dist/identity/index.cjs.map +1 -1
- package/dist/identity/index.d.cts +78 -2
- package/dist/identity/index.d.ts +78 -2
- package/dist/identity/index.js +7 -3
- package/dist/identity/index.js.map +1 -1
- package/dist/index.cjs +425 -182
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -19
- package/dist/index.d.ts +21 -19
- package/dist/index.js +15 -9
- package/dist/schema/index.cjs +5 -5
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +1 -2
- package/dist/schema/index.d.ts +1 -2
- package/dist/schema/index.js +1 -1
- package/dist/secrets/index.cjs +116 -180
- package/dist/secrets/index.cjs.map +1 -1
- package/dist/secrets/index.d.cts +4 -6
- package/dist/secrets/index.d.ts +4 -6
- package/dist/secrets/index.js +9 -318
- package/dist/secrets/index.js.map +1 -1
- package/dist/supabase/index.cjs +86 -3
- package/dist/supabase/index.cjs.map +1 -1
- package/dist/supabase/index.d.cts +4 -4
- package/dist/supabase/index.d.ts +4 -4
- package/dist/supabase/index.js +26 -3
- package/dist/supabase/index.js.map +1 -1
- package/dist/{types-public-0CzBV45X.d.cts → types-public-dKxDzTIL.d.cts} +47 -34
- package/dist/{types-public-0CzBV45X.d.ts → types-public-dKxDzTIL.d.ts} +47 -34
- package/dist/types-public.cjs.map +1 -1
- package/dist/types-public.d.cts +1 -2
- package/dist/types-public.d.ts +1 -2
- package/dist/types-public.js +1 -1
- package/package.json +30 -2
- package/dist/chunk-JLI27P46.js.map +0 -1
- package/dist/chunk-MW6D52V2.js.map +0 -1
- package/dist/chunk-OAPLZLR5.js.map +0 -1
- package/dist/chunk-SUYMGQBY.js.map +0 -1
- package/dist/chunk-TBAIVO6T.js.map +0 -1
- package/dist/index-9-Ya3fDK.d.cts +0 -169
- package/dist/index-9-Ya3fDK.d.ts +0 -169
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/
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
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"))
|
|
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/
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
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/
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
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 = {
|
|
@@ -1470,15 +1475,9 @@ function encryptedToPgComposite(obj) {
|
|
|
1470
1475
|
};
|
|
1471
1476
|
}
|
|
1472
1477
|
function encryptedToCompositeLiteral(obj) {
|
|
1473
|
-
if (obj === null) {
|
|
1474
|
-
throw new Error("encryptedToCompositeLiteral: obj cannot be null");
|
|
1475
|
-
}
|
|
1476
1478
|
return `(${JSON.stringify(JSON.stringify(obj))})`;
|
|
1477
1479
|
}
|
|
1478
1480
|
function encryptedToEscapedCompositeLiteral(obj) {
|
|
1479
|
-
if (obj === null) {
|
|
1480
|
-
throw new Error("encryptedToEscapedCompositeLiteral: obj cannot be null");
|
|
1481
|
-
}
|
|
1482
1481
|
return JSON.stringify(encryptedToCompositeLiteral(obj));
|
|
1483
1482
|
}
|
|
1484
1483
|
function formatEncryptedResult(encrypted, returnType) {
|
|
@@ -1507,18 +1506,9 @@ function isEncryptedPayload(value) {
|
|
|
1507
1506
|
return true;
|
|
1508
1507
|
}
|
|
1509
1508
|
|
|
1510
|
-
// src/errors/index.ts
|
|
1511
|
-
var EncryptionErrorTypes = {
|
|
1512
|
-
ClientInitError: "ClientInitError",
|
|
1513
|
-
EncryptionError: "EncryptionError",
|
|
1514
|
-
DecryptionError: "DecryptionError",
|
|
1515
|
-
LockContextError: "LockContextError",
|
|
1516
|
-
CtsTokenError: "CtsTokenError"
|
|
1517
|
-
};
|
|
1518
|
-
|
|
1519
1509
|
// src/schema/index.ts
|
|
1520
1510
|
import { z as z2 } from "zod";
|
|
1521
|
-
var castAsEnum = z2.enum(["bigint", "boolean", "date", "number", "string", "json"]).default("
|
|
1511
|
+
var castAsEnum = z2.enum(["bigint", "boolean", "date", "number", "string", "json", "text"]).default("text");
|
|
1522
1512
|
var tokenFilterSchema = z2.object({
|
|
1523
1513
|
kind: z2.literal("downcase")
|
|
1524
1514
|
});
|
|
@@ -1566,7 +1556,7 @@ var EncryptedField = class {
|
|
|
1566
1556
|
castAsValue;
|
|
1567
1557
|
constructor(valueName) {
|
|
1568
1558
|
this.valueName = valueName;
|
|
1569
|
-
this.castAsValue = "
|
|
1559
|
+
this.castAsValue = "text";
|
|
1570
1560
|
}
|
|
1571
1561
|
/**
|
|
1572
1562
|
* Set or override the plaintext data type for this field.
|
|
@@ -1575,7 +1565,7 @@ var EncryptedField = class {
|
|
|
1575
1565
|
* a different type so the encryption layer knows how to encode the plaintext
|
|
1576
1566
|
* before encrypting.
|
|
1577
1567
|
*
|
|
1578
|
-
* @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.
|
|
1568
|
+
* @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'text'`, `'bigint'`, or `'json'`.
|
|
1579
1569
|
* @returns This `EncryptedField` instance for method chaining.
|
|
1580
1570
|
*
|
|
1581
1571
|
* @example
|
|
@@ -1591,7 +1581,7 @@ var EncryptedField = class {
|
|
|
1591
1581
|
}
|
|
1592
1582
|
build() {
|
|
1593
1583
|
return {
|
|
1594
|
-
cast_as: this.castAsValue,
|
|
1584
|
+
cast_as: this.castAsValue === "string" ? "text" : this.castAsValue,
|
|
1595
1585
|
indexes: {}
|
|
1596
1586
|
};
|
|
1597
1587
|
}
|
|
@@ -1745,7 +1735,7 @@ var EncryptedColumn = class {
|
|
|
1745
1735
|
}
|
|
1746
1736
|
build() {
|
|
1747
1737
|
return {
|
|
1748
|
-
cast_as: this.castAsValue,
|
|
1738
|
+
cast_as: this.castAsValue === "string" ? "text" : this.castAsValue,
|
|
1749
1739
|
indexes: this.indexesValue
|
|
1750
1740
|
};
|
|
1751
1741
|
}
|
|
@@ -1840,6 +1830,15 @@ function buildEncryptConfig(...protectTables) {
|
|
|
1840
1830
|
return config3;
|
|
1841
1831
|
}
|
|
1842
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
|
+
|
|
1843
1842
|
// src/utils/config/index.ts
|
|
1844
1843
|
import fs from "node:fs";
|
|
1845
1844
|
import path from "node:path";
|
|
@@ -1904,26 +1903,34 @@ function loadWorkSpaceId(suppliedCrn) {
|
|
|
1904
1903
|
}
|
|
1905
1904
|
|
|
1906
1905
|
// src/utils/logger/index.ts
|
|
1907
|
-
import {
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
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
|
+
}
|
|
1915
1923
|
}
|
|
1916
1924
|
var initialized = false;
|
|
1917
|
-
function initStackLogger(
|
|
1925
|
+
function initStackLogger() {
|
|
1918
1926
|
if (initialized) return;
|
|
1919
1927
|
initialized = true;
|
|
1920
|
-
const
|
|
1928
|
+
const level = levelFromEnv();
|
|
1929
|
+
const rates = samplingRatesForLevel(level);
|
|
1921
1930
|
initLogger({
|
|
1922
1931
|
env: { service: "@cipherstash/stack" },
|
|
1923
|
-
enabled:
|
|
1924
|
-
|
|
1925
|
-
...rates && { sampling: { rates } },
|
|
1926
|
-
...config3?.drain && { drain: config3.drain }
|
|
1932
|
+
enabled: true,
|
|
1933
|
+
sampling: { rates }
|
|
1927
1934
|
});
|
|
1928
1935
|
}
|
|
1929
1936
|
initStackLogger();
|
|
@@ -1961,6 +1968,7 @@ var logger = {
|
|
|
1961
1968
|
// src/encryption/index.ts
|
|
1962
1969
|
import { withResult as withResult11 } from "@byteslice/result";
|
|
1963
1970
|
import { newClient } from "@cipherstash/protect-ffi";
|
|
1971
|
+
import { validate as uuidValidate } from "uuid";
|
|
1964
1972
|
|
|
1965
1973
|
// src/encryption/helpers/type-guards.ts
|
|
1966
1974
|
function isScalarQueryTermArray(value) {
|
|
@@ -2120,18 +2128,6 @@ var EncryptionOperation = class {
|
|
|
2120
2128
|
};
|
|
2121
2129
|
|
|
2122
2130
|
// src/encryption/operations/batch-encrypt-query.ts
|
|
2123
|
-
function filterNullTerms(terms) {
|
|
2124
|
-
const nullIndices = /* @__PURE__ */ new Set();
|
|
2125
|
-
const nonNullTerms = [];
|
|
2126
|
-
terms.forEach((term, index) => {
|
|
2127
|
-
if (term.value === null || term.value === void 0) {
|
|
2128
|
-
nullIndices.add(index);
|
|
2129
|
-
} else {
|
|
2130
|
-
nonNullTerms.push({ term, originalIndex: index });
|
|
2131
|
-
}
|
|
2132
|
-
});
|
|
2133
|
-
return { nullIndices, nonNullTerms };
|
|
2134
|
-
}
|
|
2135
2131
|
function buildQueryPayload(term, lockContext) {
|
|
2136
2132
|
assertValidNumericValue(term.value);
|
|
2137
2133
|
const { indexType, queryOp } = resolveIndexType(
|
|
@@ -2152,13 +2148,10 @@ function buildQueryPayload(term, lockContext) {
|
|
|
2152
2148
|
}
|
|
2153
2149
|
return payload;
|
|
2154
2150
|
}
|
|
2155
|
-
function assembleResults(
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
results[originalIndex] = formatEncryptedResult(encrypted, term.returnType);
|
|
2160
|
-
});
|
|
2161
|
-
return results;
|
|
2151
|
+
function assembleResults(terms, encryptedValues) {
|
|
2152
|
+
return terms.map(
|
|
2153
|
+
(term, i) => formatEncryptedResult(encryptedValues[i], term.returnType)
|
|
2154
|
+
);
|
|
2162
2155
|
}
|
|
2163
2156
|
var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
2164
2157
|
constructor(client, terms) {
|
|
@@ -2185,23 +2178,18 @@ var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
|
2185
2178
|
log.emit();
|
|
2186
2179
|
return { data: [] };
|
|
2187
2180
|
}
|
|
2188
|
-
const { nullIndices, nonNullTerms } = filterNullTerms(this.terms);
|
|
2189
|
-
if (nonNullTerms.length === 0) {
|
|
2190
|
-
log.emit();
|
|
2191
|
-
return { data: this.terms.map(() => null) };
|
|
2192
|
-
}
|
|
2193
2181
|
const result = await withResult(
|
|
2194
2182
|
async () => {
|
|
2195
2183
|
if (!this.client) throw noClientError();
|
|
2196
2184
|
const { metadata } = this.getAuditData();
|
|
2197
|
-
const queries =
|
|
2198
|
-
(
|
|
2185
|
+
const queries = this.terms.map(
|
|
2186
|
+
(term) => buildQueryPayload(term)
|
|
2199
2187
|
);
|
|
2200
2188
|
const encrypted = await ffiEncryptQueryBulk(this.client, {
|
|
2201
2189
|
queries,
|
|
2202
2190
|
unverifiedContext: metadata
|
|
2203
2191
|
});
|
|
2204
|
-
return assembleResults(this.terms
|
|
2192
|
+
return assembleResults(this.terms, encrypted);
|
|
2205
2193
|
},
|
|
2206
2194
|
(error) => {
|
|
2207
2195
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -2235,11 +2223,6 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
2235
2223
|
log.emit();
|
|
2236
2224
|
return { data: [] };
|
|
2237
2225
|
}
|
|
2238
|
-
const { nullIndices, nonNullTerms } = filterNullTerms(this.terms);
|
|
2239
|
-
if (nonNullTerms.length === 0) {
|
|
2240
|
-
log.emit();
|
|
2241
|
-
return { data: this.terms.map(() => null) };
|
|
2242
|
-
}
|
|
2243
2226
|
const lockContextResult = await this.lockContext.getLockContext();
|
|
2244
2227
|
if (lockContextResult.failure) {
|
|
2245
2228
|
log.emit();
|
|
@@ -2250,15 +2233,15 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
2250
2233
|
async () => {
|
|
2251
2234
|
if (!this.client) throw noClientError();
|
|
2252
2235
|
const { metadata } = this.getAuditData();
|
|
2253
|
-
const queries =
|
|
2254
|
-
(
|
|
2236
|
+
const queries = this.terms.map(
|
|
2237
|
+
(term) => buildQueryPayload(term, context)
|
|
2255
2238
|
);
|
|
2256
2239
|
const encrypted = await ffiEncryptQueryBulk(this.client, {
|
|
2257
2240
|
queries,
|
|
2258
2241
|
serviceToken: ctsToken,
|
|
2259
2242
|
unverifiedContext: metadata
|
|
2260
2243
|
});
|
|
2261
|
-
return assembleResults(this.terms
|
|
2244
|
+
return assembleResults(this.terms, encrypted);
|
|
2262
2245
|
},
|
|
2263
2246
|
(error) => {
|
|
2264
2247
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -2280,42 +2263,25 @@ import {
|
|
|
2280
2263
|
decryptBulkFallible
|
|
2281
2264
|
} from "@cipherstash/protect-ffi";
|
|
2282
2265
|
var createDecryptPayloads = (encryptedPayloads, lockContext) => {
|
|
2283
|
-
return encryptedPayloads.map((
|
|
2266
|
+
return encryptedPayloads.map(({ id, data }) => ({
|
|
2284
2267
|
id,
|
|
2285
2268
|
ciphertext: data,
|
|
2286
|
-
originalIndex,
|
|
2287
2269
|
...lockContext && { lockContext }
|
|
2288
2270
|
}));
|
|
2289
2271
|
};
|
|
2290
|
-
var createNullResult = (encryptedPayloads) => {
|
|
2291
|
-
return encryptedPayloads.map(({ id }) => ({
|
|
2292
|
-
id,
|
|
2293
|
-
data: null
|
|
2294
|
-
}));
|
|
2295
|
-
};
|
|
2296
2272
|
var mapDecryptedDataToResult = (encryptedPayloads, decryptedData) => {
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
const decryptResult = decryptedData[decryptedIndex];
|
|
2304
|
-
if ("error" in decryptResult) {
|
|
2305
|
-
result[i] = {
|
|
2306
|
-
id: encryptedPayloads[i].id,
|
|
2307
|
-
error: decryptResult.error
|
|
2308
|
-
};
|
|
2309
|
-
} else {
|
|
2310
|
-
result[i] = {
|
|
2311
|
-
id: encryptedPayloads[i].id,
|
|
2312
|
-
data: decryptResult.data
|
|
2313
|
-
};
|
|
2314
|
-
}
|
|
2315
|
-
decryptedIndex++;
|
|
2273
|
+
return decryptedData.map((decryptResult, i) => {
|
|
2274
|
+
if ("error" in decryptResult) {
|
|
2275
|
+
return {
|
|
2276
|
+
id: encryptedPayloads[i].id,
|
|
2277
|
+
error: decryptResult.error
|
|
2278
|
+
};
|
|
2316
2279
|
}
|
|
2317
|
-
|
|
2318
|
-
|
|
2280
|
+
return {
|
|
2281
|
+
id: encryptedPayloads[i].id,
|
|
2282
|
+
data: decryptResult.data
|
|
2283
|
+
};
|
|
2284
|
+
});
|
|
2319
2285
|
};
|
|
2320
2286
|
var BulkDecryptOperation = class extends EncryptionOperation {
|
|
2321
2287
|
client;
|
|
@@ -2340,13 +2306,10 @@ var BulkDecryptOperation = class extends EncryptionOperation {
|
|
|
2340
2306
|
if (!this.client) throw noClientError();
|
|
2341
2307
|
if (!this.encryptedPayloads || this.encryptedPayloads.length === 0)
|
|
2342
2308
|
return [];
|
|
2343
|
-
const
|
|
2344
|
-
if (nonNullPayloads.length === 0) {
|
|
2345
|
-
return createNullResult(this.encryptedPayloads);
|
|
2346
|
-
}
|
|
2309
|
+
const payloads = createDecryptPayloads(this.encryptedPayloads);
|
|
2347
2310
|
const { metadata } = this.getAuditData();
|
|
2348
2311
|
const decryptedData = await decryptBulkFallible(this.client, {
|
|
2349
|
-
ciphertexts:
|
|
2312
|
+
ciphertexts: payloads,
|
|
2350
2313
|
unverifiedContext: metadata
|
|
2351
2314
|
});
|
|
2352
2315
|
return mapDecryptedDataToResult(this.encryptedPayloads, decryptedData);
|
|
@@ -2398,16 +2361,13 @@ var BulkDecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2398
2361
|
if (context.failure) {
|
|
2399
2362
|
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
2400
2363
|
}
|
|
2401
|
-
const
|
|
2364
|
+
const payloads = createDecryptPayloads(
|
|
2402
2365
|
encryptedPayloads,
|
|
2403
2366
|
context.data.context
|
|
2404
2367
|
);
|
|
2405
|
-
if (nonNullPayloads.length === 0) {
|
|
2406
|
-
return createNullResult(encryptedPayloads);
|
|
2407
|
-
}
|
|
2408
2368
|
const { metadata } = this.getAuditData();
|
|
2409
2369
|
const decryptedData = await decryptBulkFallible(client, {
|
|
2410
|
-
ciphertexts:
|
|
2370
|
+
ciphertexts: payloads,
|
|
2411
2371
|
serviceToken: context.data.ctsToken,
|
|
2412
2372
|
unverifiedContext: metadata
|
|
2413
2373
|
});
|
|
@@ -3049,34 +3009,14 @@ var BulkDecryptModelsOperationWithLockContext = class extends EncryptionOperatio
|
|
|
3049
3009
|
import { withResult as withResult4 } from "@byteslice/result";
|
|
3050
3010
|
import { encryptBulk as encryptBulk2 } from "@cipherstash/protect-ffi";
|
|
3051
3011
|
var createEncryptPayloads = (plaintexts, column, table, lockContext) => {
|
|
3052
|
-
return plaintexts.map((
|
|
3012
|
+
return plaintexts.map(({ id, plaintext }) => ({
|
|
3053
3013
|
id,
|
|
3054
3014
|
plaintext,
|
|
3055
3015
|
column: column.getName(),
|
|
3056
3016
|
table: table.tableName,
|
|
3057
|
-
originalIndex,
|
|
3058
3017
|
...lockContext && { lockContext }
|
|
3059
3018
|
}));
|
|
3060
3019
|
};
|
|
3061
|
-
var createNullResult2 = (plaintexts) => {
|
|
3062
|
-
return plaintexts.map(({ id }) => ({ id, data: null }));
|
|
3063
|
-
};
|
|
3064
|
-
var mapEncryptedDataToResult = (plaintexts, encryptedData) => {
|
|
3065
|
-
const result = new Array(plaintexts.length);
|
|
3066
|
-
let encryptedIndex = 0;
|
|
3067
|
-
for (let i = 0; i < plaintexts.length; i++) {
|
|
3068
|
-
if (plaintexts[i].plaintext === null) {
|
|
3069
|
-
result[i] = { id: plaintexts[i].id, data: null };
|
|
3070
|
-
} else {
|
|
3071
|
-
result[i] = {
|
|
3072
|
-
id: plaintexts[i].id,
|
|
3073
|
-
data: encryptedData[encryptedIndex]
|
|
3074
|
-
};
|
|
3075
|
-
encryptedIndex++;
|
|
3076
|
-
}
|
|
3077
|
-
}
|
|
3078
|
-
return result;
|
|
3079
|
-
};
|
|
3080
3020
|
var BulkEncryptOperation = class extends EncryptionOperation {
|
|
3081
3021
|
client;
|
|
3082
3022
|
plaintexts;
|
|
@@ -3109,20 +3049,20 @@ var BulkEncryptOperation = class extends EncryptionOperation {
|
|
|
3109
3049
|
if (!this.plaintexts || this.plaintexts.length === 0) {
|
|
3110
3050
|
return [];
|
|
3111
3051
|
}
|
|
3112
|
-
const
|
|
3052
|
+
const payloads = createEncryptPayloads(
|
|
3113
3053
|
this.plaintexts,
|
|
3114
3054
|
this.column,
|
|
3115
3055
|
this.table
|
|
3116
3056
|
);
|
|
3117
|
-
if (nonNullPayloads.length === 0) {
|
|
3118
|
-
return createNullResult2(this.plaintexts);
|
|
3119
|
-
}
|
|
3120
3057
|
const { metadata } = this.getAuditData();
|
|
3121
3058
|
const encryptedData = await encryptBulk2(this.client, {
|
|
3122
|
-
plaintexts:
|
|
3059
|
+
plaintexts: payloads,
|
|
3123
3060
|
unverifiedContext: metadata
|
|
3124
3061
|
});
|
|
3125
|
-
return
|
|
3062
|
+
return encryptedData.map((data, i) => ({
|
|
3063
|
+
id: this.plaintexts[i].id,
|
|
3064
|
+
data
|
|
3065
|
+
}));
|
|
3126
3066
|
},
|
|
3127
3067
|
(error) => {
|
|
3128
3068
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -3179,22 +3119,22 @@ var BulkEncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
3179
3119
|
if (context.failure) {
|
|
3180
3120
|
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
3181
3121
|
}
|
|
3182
|
-
const
|
|
3122
|
+
const payloads = createEncryptPayloads(
|
|
3183
3123
|
plaintexts,
|
|
3184
3124
|
column,
|
|
3185
3125
|
table,
|
|
3186
3126
|
context.data.context
|
|
3187
3127
|
);
|
|
3188
|
-
if (nonNullPayloads.length === 0) {
|
|
3189
|
-
return createNullResult2(plaintexts);
|
|
3190
|
-
}
|
|
3191
3128
|
const { metadata } = this.getAuditData();
|
|
3192
3129
|
const encryptedData = await encryptBulk2(client, {
|
|
3193
|
-
plaintexts:
|
|
3130
|
+
plaintexts: payloads,
|
|
3194
3131
|
serviceToken: context.data.ctsToken,
|
|
3195
3132
|
unverifiedContext: metadata
|
|
3196
3133
|
});
|
|
3197
|
-
return
|
|
3134
|
+
return encryptedData.map((data, i) => ({
|
|
3135
|
+
id: plaintexts[i].id,
|
|
3136
|
+
data
|
|
3137
|
+
}));
|
|
3198
3138
|
},
|
|
3199
3139
|
(error) => {
|
|
3200
3140
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -3346,9 +3286,6 @@ var DecryptOperation = class extends EncryptionOperation {
|
|
|
3346
3286
|
if (!this.client) {
|
|
3347
3287
|
throw noClientError();
|
|
3348
3288
|
}
|
|
3349
|
-
if (this.encryptedData === null) {
|
|
3350
|
-
return null;
|
|
3351
|
-
}
|
|
3352
3289
|
const { metadata } = this.getAuditData();
|
|
3353
3290
|
return await ffiDecrypt(this.client, {
|
|
3354
3291
|
ciphertext: this.encryptedData,
|
|
@@ -3399,9 +3336,6 @@ var DecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
3399
3336
|
if (!client) {
|
|
3400
3337
|
throw noClientError();
|
|
3401
3338
|
}
|
|
3402
|
-
if (encryptedData === null) {
|
|
3403
|
-
return null;
|
|
3404
|
-
}
|
|
3405
3339
|
const { metadata } = this.getAuditData();
|
|
3406
3340
|
const context = await this.lockContext.getLockContext();
|
|
3407
3341
|
if (context.failure) {
|
|
@@ -3557,9 +3491,6 @@ var EncryptOperation = class extends EncryptionOperation {
|
|
|
3557
3491
|
if (!this.client) {
|
|
3558
3492
|
throw noClientError();
|
|
3559
3493
|
}
|
|
3560
|
-
if (this.plaintext === null) {
|
|
3561
|
-
return null;
|
|
3562
|
-
}
|
|
3563
3494
|
if (typeof this.plaintext === "number" && Number.isNaN(this.plaintext)) {
|
|
3564
3495
|
throw new Error("[encryption]: Cannot encrypt NaN value");
|
|
3565
3496
|
}
|
|
@@ -3621,9 +3552,6 @@ var EncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
3621
3552
|
if (!client) {
|
|
3622
3553
|
throw noClientError();
|
|
3623
3554
|
}
|
|
3624
|
-
if (plaintext === null) {
|
|
3625
|
-
return null;
|
|
3626
|
-
}
|
|
3627
3555
|
const { metadata } = this.getAuditData();
|
|
3628
3556
|
const context = await this.lockContext.getLockContext();
|
|
3629
3557
|
if (context.failure) {
|
|
@@ -3789,10 +3717,6 @@ var EncryptQueryOperation = class extends EncryptionOperation {
|
|
|
3789
3717
|
queryType: this.opts.queryType,
|
|
3790
3718
|
lockContext: false
|
|
3791
3719
|
});
|
|
3792
|
-
if (this.plaintext === null || this.plaintext === void 0) {
|
|
3793
|
-
log.emit();
|
|
3794
|
-
return { data: null };
|
|
3795
|
-
}
|
|
3796
3720
|
const validationError = validateNumericValue(this.plaintext);
|
|
3797
3721
|
if (validationError?.failure) {
|
|
3798
3722
|
log.emit();
|
|
@@ -3856,10 +3780,6 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
3856
3780
|
queryType: this.opts.queryType,
|
|
3857
3781
|
lockContext: true
|
|
3858
3782
|
});
|
|
3859
|
-
if (this.plaintext === null || this.plaintext === void 0) {
|
|
3860
|
-
log.emit();
|
|
3861
|
-
return { data: null };
|
|
3862
|
-
}
|
|
3863
3783
|
const validationError = validateNumericValue(this.plaintext);
|
|
3864
3784
|
if (validationError?.failure) {
|
|
3865
3785
|
log.emit();
|
|
@@ -3964,7 +3884,7 @@ var EncryptionClient = class {
|
|
|
3964
3884
|
/**
|
|
3965
3885
|
* Encrypt a value - returns a promise which resolves to an encrypted value.
|
|
3966
3886
|
*
|
|
3967
|
-
* @param plaintext - The plaintext value to be encrypted.
|
|
3887
|
+
* @param plaintext - The plaintext value to be encrypted.
|
|
3968
3888
|
* @param opts - Options specifying the column (or nested field) and table for encryption. See {@link EncryptOptions}.
|
|
3969
3889
|
* @returns An EncryptOperation that can be awaited or chained with additional methods.
|
|
3970
3890
|
*
|
|
@@ -4265,7 +4185,7 @@ var EncryptionClient = class {
|
|
|
4265
4185
|
*
|
|
4266
4186
|
* Each value is encrypted with its own unique key via a single call to ZeroKMS.
|
|
4267
4187
|
* Values can include optional `id` fields for correlating results back to
|
|
4268
|
-
* your application data.
|
|
4188
|
+
* your application data.
|
|
4269
4189
|
*
|
|
4270
4190
|
* @param plaintexts - An array of objects with `plaintext` (and optional `id`) fields.
|
|
4271
4191
|
* @param opts - Options specifying the target column (or nested {@link encryptedField}) and table. See {@link EncryptOptions}.
|
|
@@ -4286,7 +4206,6 @@ var EncryptionClient = class {
|
|
|
4286
4206
|
* [
|
|
4287
4207
|
* { id: "u1", plaintext: "alice@example.com" },
|
|
4288
4208
|
* { id: "u2", plaintext: "bob@example.com" },
|
|
4289
|
-
* { id: "u3", plaintext: null },
|
|
4290
4209
|
* ],
|
|
4291
4210
|
* { column: users.email, table: users },
|
|
4292
4211
|
* )
|
|
@@ -4340,23 +4259,14 @@ var EncryptionClient = class {
|
|
|
4340
4259
|
};
|
|
4341
4260
|
}
|
|
4342
4261
|
};
|
|
4343
|
-
|
|
4344
|
-
// src/index.ts
|
|
4345
|
-
function isValidUuid(uuid) {
|
|
4346
|
-
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;
|
|
4347
|
-
return uuidRegex.test(uuid);
|
|
4348
|
-
}
|
|
4349
4262
|
var Encryption = async (config3) => {
|
|
4350
|
-
if (config3.logging) {
|
|
4351
|
-
initStackLogger(config3.logging);
|
|
4352
|
-
}
|
|
4353
4263
|
const { schemas, config: clientConfig } = config3;
|
|
4354
4264
|
if (!schemas.length) {
|
|
4355
4265
|
throw new Error(
|
|
4356
4266
|
"[encryption]: At least one encryptedTable must be provided to initialize the encryption client"
|
|
4357
4267
|
);
|
|
4358
4268
|
}
|
|
4359
|
-
if (clientConfig?.keyset && "id" in clientConfig.keyset && !
|
|
4269
|
+
if (clientConfig?.keyset && "id" in clientConfig.keyset && !uuidValidate(clientConfig.keyset.id)) {
|
|
4360
4270
|
throw new Error(
|
|
4361
4271
|
"[encryption]: Invalid UUID provided for keyset id. Must be a valid UUID."
|
|
4362
4272
|
);
|
|
@@ -4382,7 +4292,22 @@ var Secrets = class {
|
|
|
4382
4292
|
value: encryptedColumn("value")
|
|
4383
4293
|
});
|
|
4384
4294
|
constructor(config3) {
|
|
4385
|
-
|
|
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
|
+
};
|
|
4386
4311
|
}
|
|
4387
4312
|
initPromise = null;
|
|
4388
4313
|
/**
|
|
@@ -4395,24 +4320,24 @@ var Secrets = class {
|
|
|
4395
4320
|
return this.initPromise;
|
|
4396
4321
|
}
|
|
4397
4322
|
async _doInit() {
|
|
4323
|
+
logger.debug("Initializing the Secrets client.");
|
|
4398
4324
|
this.encryptionClient = await Encryption({
|
|
4399
4325
|
schemas: [this.secretsSchema],
|
|
4400
4326
|
config: {
|
|
4401
4327
|
workspaceCrn: this.config.workspaceCRN,
|
|
4402
4328
|
clientId: this.config.clientId,
|
|
4403
4329
|
clientKey: this.config.clientKey,
|
|
4404
|
-
accessKey: this.config.
|
|
4405
|
-
keyset: {
|
|
4406
|
-
name: this.config.environment
|
|
4407
|
-
}
|
|
4330
|
+
accessKey: this.config.accessKey,
|
|
4331
|
+
keyset: { name: this.config.environment }
|
|
4408
4332
|
}
|
|
4409
4333
|
});
|
|
4334
|
+
logger.debug("Successfully initialized the Secrets client.");
|
|
4410
4335
|
}
|
|
4411
4336
|
/**
|
|
4412
4337
|
* Get the authorization header for API requests
|
|
4413
4338
|
*/
|
|
4414
4339
|
getAuthHeader() {
|
|
4415
|
-
return `Bearer ${this.config.
|
|
4340
|
+
return `Bearer ${this.config.accessKey}`;
|
|
4416
4341
|
}
|
|
4417
4342
|
/**
|
|
4418
4343
|
* Make an API request with error handling.
|
|
@@ -4427,6 +4352,7 @@ var Secrets = class {
|
|
|
4427
4352
|
const searchParams = new URLSearchParams(options.params);
|
|
4428
4353
|
url = `${url}?${searchParams.toString()}`;
|
|
4429
4354
|
}
|
|
4355
|
+
logger.debug(`Secrets API request: ${method} ${path2}`);
|
|
4430
4356
|
const headers = {
|
|
4431
4357
|
"Content-Type": "application/json",
|
|
4432
4358
|
Authorization: this.getAuthHeader()
|
|
@@ -4445,6 +4371,7 @@ var Secrets = class {
|
|
|
4445
4371
|
} catch {
|
|
4446
4372
|
errorMessage = errorText || errorMessage;
|
|
4447
4373
|
}
|
|
4374
|
+
logger.error(`Secrets API error on ${method} ${path2}: ${errorMessage}`);
|
|
4448
4375
|
return {
|
|
4449
4376
|
failure: {
|
|
4450
4377
|
type: "ApiError",
|
|
@@ -4452,13 +4379,16 @@ var Secrets = class {
|
|
|
4452
4379
|
}
|
|
4453
4380
|
};
|
|
4454
4381
|
}
|
|
4382
|
+
logger.debug(`Secrets API request successful: ${method} ${path2}`);
|
|
4455
4383
|
const data = await response.json();
|
|
4456
4384
|
return { data };
|
|
4457
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}`);
|
|
4458
4388
|
return {
|
|
4459
4389
|
failure: {
|
|
4460
4390
|
type: "NetworkError",
|
|
4461
|
-
message
|
|
4391
|
+
message
|
|
4462
4392
|
}
|
|
4463
4393
|
};
|
|
4464
4394
|
}
|
|
@@ -4474,6 +4404,7 @@ var Secrets = class {
|
|
|
4474
4404
|
* @returns A Result containing the API response or an error
|
|
4475
4405
|
*/
|
|
4476
4406
|
async set(name, value) {
|
|
4407
|
+
logger.debug("Setting secret");
|
|
4477
4408
|
await this.ensureInitialized();
|
|
4478
4409
|
if (!this.encryptionClient) {
|
|
4479
4410
|
return {
|
|
@@ -4488,6 +4419,7 @@ var Secrets = class {
|
|
|
4488
4419
|
table: this.secretsSchema
|
|
4489
4420
|
});
|
|
4490
4421
|
if (encryptResult.failure) {
|
|
4422
|
+
logger.error("Failed to encrypt secret");
|
|
4491
4423
|
return {
|
|
4492
4424
|
failure: {
|
|
4493
4425
|
type: "EncryptionError",
|
|
@@ -4515,6 +4447,7 @@ var Secrets = class {
|
|
|
4515
4447
|
* @returns A Result containing the decrypted value or an error
|
|
4516
4448
|
*/
|
|
4517
4449
|
async get(name) {
|
|
4450
|
+
logger.debug("Getting secret");
|
|
4518
4451
|
await this.ensureInitialized();
|
|
4519
4452
|
if (!this.encryptionClient) {
|
|
4520
4453
|
return {
|
|
@@ -4539,6 +4472,7 @@ var Secrets = class {
|
|
|
4539
4472
|
apiResult.data.encryptedValue.data
|
|
4540
4473
|
);
|
|
4541
4474
|
if (decryptResult.failure) {
|
|
4475
|
+
logger.error("Failed to decrypt secret");
|
|
4542
4476
|
return {
|
|
4543
4477
|
failure: {
|
|
4544
4478
|
type: "DecryptionError",
|
|
@@ -4547,6 +4481,7 @@ var Secrets = class {
|
|
|
4547
4481
|
};
|
|
4548
4482
|
}
|
|
4549
4483
|
if (typeof decryptResult.data !== "string") {
|
|
4484
|
+
logger.error("Decrypted secret value is not a string");
|
|
4550
4485
|
return {
|
|
4551
4486
|
failure: {
|
|
4552
4487
|
type: "DecryptionError",
|
|
@@ -4571,6 +4506,7 @@ var Secrets = class {
|
|
|
4571
4506
|
* @returns A Result containing an object mapping secret names to their decrypted values
|
|
4572
4507
|
*/
|
|
4573
4508
|
async getMany(names) {
|
|
4509
|
+
logger.debug(`Getting ${names.length} secrets.`);
|
|
4574
4510
|
await this.ensureInitialized();
|
|
4575
4511
|
if (!this.encryptionClient) {
|
|
4576
4512
|
return {
|
|
@@ -4617,6 +4553,9 @@ var Secrets = class {
|
|
|
4617
4553
|
}));
|
|
4618
4554
|
const decryptResult = await this.encryptionClient.bulkDecryptModels(dataToDecrypt);
|
|
4619
4555
|
if (decryptResult.failure) {
|
|
4556
|
+
logger.error(
|
|
4557
|
+
`Failed to decrypt secrets: ${decryptResult.failure.message}`
|
|
4558
|
+
);
|
|
4620
4559
|
return {
|
|
4621
4560
|
failure: {
|
|
4622
4561
|
type: "DecryptionError",
|
|
@@ -4642,6 +4581,7 @@ var Secrets = class {
|
|
|
4642
4581
|
* @returns A Result containing the list of secrets or an error
|
|
4643
4582
|
*/
|
|
4644
4583
|
async list() {
|
|
4584
|
+
logger.debug("Listing secrets.");
|
|
4645
4585
|
const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
|
|
4646
4586
|
const apiResult = await this.apiRequest(
|
|
4647
4587
|
"GET",
|
|
@@ -4667,6 +4607,7 @@ var Secrets = class {
|
|
|
4667
4607
|
* @returns A Result containing the API response or an error
|
|
4668
4608
|
*/
|
|
4669
4609
|
async delete(name) {
|
|
4610
|
+
logger.debug("Deleting secret");
|
|
4670
4611
|
const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
|
|
4671
4612
|
return await this.apiRequest("POST", "/delete", {
|
|
4672
4613
|
body: {
|