@cipherstash/stack 0.4.0 → 0.6.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 +9 -36
- package/dist/bin/stash.js +220 -184
- package/dist/bin/stash.js.map +1 -1
- package/dist/{chunk-OAPLZLR5.js → chunk-GXGEW6T4.js} +2 -76
- package/dist/chunk-GXGEW6T4.js.map +1 -0
- package/dist/{chunk-KOU2MHXJ.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-WUZGKTMG.js → chunk-TGUELLJS.js} +16 -19
- package/dist/chunk-TGUELLJS.js.map +1 -0
- package/dist/chunk-YLISU7FD.js +357 -0
- package/dist/chunk-YLISU7FD.js.map +1 -0
- package/dist/{client-CrGQnSlk.d.ts → client-CJueivkw.d.cts} +36 -3
- package/dist/{client-CUGXheRq.d.cts → client-hHEpZIZH.d.ts} +36 -3
- package/dist/client.d.cts +4 -4
- package/dist/client.d.ts +4 -4
- 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 +3 -3
- 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 +379 -41
- 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 +14 -8
- package/dist/schema/index.d.cts +1 -2
- package/dist/schema/index.d.ts +1 -2
- package/dist/secrets/index.cjs +70 -39
- 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 +84 -1
- 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 +24 -1
- package/dist/supabase/index.js.map +1 -1
- package/dist/{types-public-Wj6tB_ux.d.ts → types-public-07ilcGY-.d.cts} +1 -9
- package/dist/{types-public-Wj6tB_ux.d.cts → types-public-07ilcGY-.d.ts} +1 -9
- 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 +29 -1
- package/dist/chunk-KOU2MHXJ.js.map +0 -1
- package/dist/chunk-OAPLZLR5.js.map +0 -1
- package/dist/chunk-WUZGKTMG.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 = {
|
|
@@ -1443,7 +1448,10 @@ function resolveProvider(flags) {
|
|
|
1443
1448
|
}
|
|
1444
1449
|
async function initCommand(flags) {
|
|
1445
1450
|
const provider = resolveProvider(flags);
|
|
1446
|
-
Ie(
|
|
1451
|
+
Ie("CipherStash Stack Setup");
|
|
1452
|
+
M2.warn(
|
|
1453
|
+
"This command is a prototype and a sneak peek at what's next. It doesn't perform any actual setup yet."
|
|
1454
|
+
);
|
|
1447
1455
|
M2.info(provider.introMessage);
|
|
1448
1456
|
let state = {};
|
|
1449
1457
|
try {
|
|
@@ -1501,15 +1509,6 @@ function isEncryptedPayload(value) {
|
|
|
1501
1509
|
return true;
|
|
1502
1510
|
}
|
|
1503
1511
|
|
|
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
1512
|
// src/schema/index.ts
|
|
1514
1513
|
import { z as z2 } from "zod";
|
|
1515
1514
|
var castAsEnum = z2.enum(["bigint", "boolean", "date", "number", "string", "json", "text"]).default("text");
|
|
@@ -1834,6 +1833,15 @@ function buildEncryptConfig(...protectTables) {
|
|
|
1834
1833
|
return config3;
|
|
1835
1834
|
}
|
|
1836
1835
|
|
|
1836
|
+
// src/errors/index.ts
|
|
1837
|
+
var EncryptionErrorTypes = {
|
|
1838
|
+
ClientInitError: "ClientInitError",
|
|
1839
|
+
EncryptionError: "EncryptionError",
|
|
1840
|
+
DecryptionError: "DecryptionError",
|
|
1841
|
+
LockContextError: "LockContextError",
|
|
1842
|
+
CtsTokenError: "CtsTokenError"
|
|
1843
|
+
};
|
|
1844
|
+
|
|
1837
1845
|
// src/utils/config/index.ts
|
|
1838
1846
|
import fs from "node:fs";
|
|
1839
1847
|
import path from "node:path";
|
|
@@ -1898,26 +1906,34 @@ function loadWorkSpaceId(suppliedCrn) {
|
|
|
1898
1906
|
}
|
|
1899
1907
|
|
|
1900
1908
|
// src/utils/logger/index.ts
|
|
1901
|
-
import {
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
+
import { createRequestLogger, initLogger } from "evlog";
|
|
1910
|
+
var validLevels = ["debug", "info", "error"];
|
|
1911
|
+
function levelFromEnv() {
|
|
1912
|
+
const env = process.env.STASH_STACK_LOG;
|
|
1913
|
+
if (env && validLevels.includes(env)) return env;
|
|
1914
|
+
return "error";
|
|
1915
|
+
}
|
|
1916
|
+
function samplingRatesForLevel(level) {
|
|
1917
|
+
switch (level) {
|
|
1918
|
+
case "debug":
|
|
1919
|
+
return { debug: 100, info: 100, warn: 100, error: 100 };
|
|
1920
|
+
case "info":
|
|
1921
|
+
return { debug: 0, info: 100, warn: 100, error: 100 };
|
|
1922
|
+
case "error":
|
|
1923
|
+
default:
|
|
1924
|
+
return { debug: 0, info: 0, warn: 0, error: 100 };
|
|
1925
|
+
}
|
|
1909
1926
|
}
|
|
1910
1927
|
var initialized = false;
|
|
1911
|
-
function initStackLogger(
|
|
1928
|
+
function initStackLogger() {
|
|
1912
1929
|
if (initialized) return;
|
|
1913
1930
|
initialized = true;
|
|
1914
|
-
const
|
|
1931
|
+
const level = levelFromEnv();
|
|
1932
|
+
const rates = samplingRatesForLevel(level);
|
|
1915
1933
|
initLogger({
|
|
1916
1934
|
env: { service: "@cipherstash/stack" },
|
|
1917
|
-
enabled:
|
|
1918
|
-
|
|
1919
|
-
...rates && { sampling: { rates } },
|
|
1920
|
-
...config3?.drain && { drain: config3.drain }
|
|
1935
|
+
enabled: true,
|
|
1936
|
+
sampling: { rates }
|
|
1921
1937
|
});
|
|
1922
1938
|
}
|
|
1923
1939
|
initStackLogger();
|
|
@@ -1955,6 +1971,7 @@ var logger = {
|
|
|
1955
1971
|
// src/encryption/index.ts
|
|
1956
1972
|
import { withResult as withResult11 } from "@byteslice/result";
|
|
1957
1973
|
import { newClient } from "@cipherstash/protect-ffi";
|
|
1974
|
+
import { validate as uuidValidate } from "uuid";
|
|
1958
1975
|
|
|
1959
1976
|
// src/encryption/helpers/type-guards.ts
|
|
1960
1977
|
function isScalarQueryTermArray(value) {
|
|
@@ -4245,23 +4262,14 @@ var EncryptionClient = class {
|
|
|
4245
4262
|
};
|
|
4246
4263
|
}
|
|
4247
4264
|
};
|
|
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
4265
|
var Encryption = async (config3) => {
|
|
4255
|
-
if (config3.logging) {
|
|
4256
|
-
initStackLogger(config3.logging);
|
|
4257
|
-
}
|
|
4258
4266
|
const { schemas, config: clientConfig } = config3;
|
|
4259
4267
|
if (!schemas.length) {
|
|
4260
4268
|
throw new Error(
|
|
4261
4269
|
"[encryption]: At least one encryptedTable must be provided to initialize the encryption client"
|
|
4262
4270
|
);
|
|
4263
4271
|
}
|
|
4264
|
-
if (clientConfig?.keyset && "id" in clientConfig.keyset && !
|
|
4272
|
+
if (clientConfig?.keyset && "id" in clientConfig.keyset && !uuidValidate(clientConfig.keyset.id)) {
|
|
4265
4273
|
throw new Error(
|
|
4266
4274
|
"[encryption]: Invalid UUID provided for keyset id. Must be a valid UUID."
|
|
4267
4275
|
);
|
|
@@ -4287,7 +4295,22 @@ var Secrets = class {
|
|
|
4287
4295
|
value: encryptedColumn("value")
|
|
4288
4296
|
});
|
|
4289
4297
|
constructor(config3) {
|
|
4290
|
-
|
|
4298
|
+
const workspaceCRN = config3.workspaceCRN ?? process.env.CS_WORKSPACE_CRN;
|
|
4299
|
+
const clientId = config3.clientId ?? process.env.CS_CLIENT_ID;
|
|
4300
|
+
const clientKey = config3.clientKey ?? process.env.CS_CLIENT_KEY;
|
|
4301
|
+
const accessKey = config3.accessKey ?? process.env.CS_CLIENT_ACCESS_KEY;
|
|
4302
|
+
if (!workspaceCRN || !clientId || !clientKey || !accessKey) {
|
|
4303
|
+
throw new Error(
|
|
4304
|
+
"Missing required configuration or environment variables."
|
|
4305
|
+
);
|
|
4306
|
+
}
|
|
4307
|
+
this.config = {
|
|
4308
|
+
environment: config3.environment,
|
|
4309
|
+
workspaceCRN,
|
|
4310
|
+
clientId,
|
|
4311
|
+
clientKey,
|
|
4312
|
+
accessKey
|
|
4313
|
+
};
|
|
4291
4314
|
}
|
|
4292
4315
|
initPromise = null;
|
|
4293
4316
|
/**
|
|
@@ -4300,24 +4323,24 @@ var Secrets = class {
|
|
|
4300
4323
|
return this.initPromise;
|
|
4301
4324
|
}
|
|
4302
4325
|
async _doInit() {
|
|
4326
|
+
logger.debug("Initializing the Secrets client.");
|
|
4303
4327
|
this.encryptionClient = await Encryption({
|
|
4304
4328
|
schemas: [this.secretsSchema],
|
|
4305
4329
|
config: {
|
|
4306
4330
|
workspaceCrn: this.config.workspaceCRN,
|
|
4307
4331
|
clientId: this.config.clientId,
|
|
4308
4332
|
clientKey: this.config.clientKey,
|
|
4309
|
-
accessKey: this.config.
|
|
4310
|
-
keyset: {
|
|
4311
|
-
name: this.config.environment
|
|
4312
|
-
}
|
|
4333
|
+
accessKey: this.config.accessKey,
|
|
4334
|
+
keyset: { name: this.config.environment }
|
|
4313
4335
|
}
|
|
4314
4336
|
});
|
|
4337
|
+
logger.debug("Successfully initialized the Secrets client.");
|
|
4315
4338
|
}
|
|
4316
4339
|
/**
|
|
4317
4340
|
* Get the authorization header for API requests
|
|
4318
4341
|
*/
|
|
4319
4342
|
getAuthHeader() {
|
|
4320
|
-
return `Bearer ${this.config.
|
|
4343
|
+
return `Bearer ${this.config.accessKey}`;
|
|
4321
4344
|
}
|
|
4322
4345
|
/**
|
|
4323
4346
|
* Make an API request with error handling.
|
|
@@ -4332,6 +4355,7 @@ var Secrets = class {
|
|
|
4332
4355
|
const searchParams = new URLSearchParams(options.params);
|
|
4333
4356
|
url = `${url}?${searchParams.toString()}`;
|
|
4334
4357
|
}
|
|
4358
|
+
logger.debug(`Secrets API request: ${method} ${path2}`);
|
|
4335
4359
|
const headers = {
|
|
4336
4360
|
"Content-Type": "application/json",
|
|
4337
4361
|
Authorization: this.getAuthHeader()
|
|
@@ -4350,6 +4374,7 @@ var Secrets = class {
|
|
|
4350
4374
|
} catch {
|
|
4351
4375
|
errorMessage = errorText || errorMessage;
|
|
4352
4376
|
}
|
|
4377
|
+
logger.error(`Secrets API error on ${method} ${path2}: ${errorMessage}`);
|
|
4353
4378
|
return {
|
|
4354
4379
|
failure: {
|
|
4355
4380
|
type: "ApiError",
|
|
@@ -4357,13 +4382,16 @@ var Secrets = class {
|
|
|
4357
4382
|
}
|
|
4358
4383
|
};
|
|
4359
4384
|
}
|
|
4385
|
+
logger.debug(`Secrets API request successful: ${method} ${path2}`);
|
|
4360
4386
|
const data = await response.json();
|
|
4361
4387
|
return { data };
|
|
4362
4388
|
} catch (error) {
|
|
4389
|
+
const message = error instanceof Error ? error.message : "Unknown network error occurred";
|
|
4390
|
+
logger.error(`Secrets network error on ${method} ${path2}: ${message}`);
|
|
4363
4391
|
return {
|
|
4364
4392
|
failure: {
|
|
4365
4393
|
type: "NetworkError",
|
|
4366
|
-
message
|
|
4394
|
+
message
|
|
4367
4395
|
}
|
|
4368
4396
|
};
|
|
4369
4397
|
}
|
|
@@ -4379,6 +4407,7 @@ var Secrets = class {
|
|
|
4379
4407
|
* @returns A Result containing the API response or an error
|
|
4380
4408
|
*/
|
|
4381
4409
|
async set(name, value) {
|
|
4410
|
+
logger.debug("Setting secret");
|
|
4382
4411
|
await this.ensureInitialized();
|
|
4383
4412
|
if (!this.encryptionClient) {
|
|
4384
4413
|
return {
|
|
@@ -4393,6 +4422,7 @@ var Secrets = class {
|
|
|
4393
4422
|
table: this.secretsSchema
|
|
4394
4423
|
});
|
|
4395
4424
|
if (encryptResult.failure) {
|
|
4425
|
+
logger.error("Failed to encrypt secret");
|
|
4396
4426
|
return {
|
|
4397
4427
|
failure: {
|
|
4398
4428
|
type: "EncryptionError",
|
|
@@ -4420,6 +4450,7 @@ var Secrets = class {
|
|
|
4420
4450
|
* @returns A Result containing the decrypted value or an error
|
|
4421
4451
|
*/
|
|
4422
4452
|
async get(name) {
|
|
4453
|
+
logger.debug("Getting secret");
|
|
4423
4454
|
await this.ensureInitialized();
|
|
4424
4455
|
if (!this.encryptionClient) {
|
|
4425
4456
|
return {
|
|
@@ -4444,6 +4475,7 @@ var Secrets = class {
|
|
|
4444
4475
|
apiResult.data.encryptedValue.data
|
|
4445
4476
|
);
|
|
4446
4477
|
if (decryptResult.failure) {
|
|
4478
|
+
logger.error("Failed to decrypt secret");
|
|
4447
4479
|
return {
|
|
4448
4480
|
failure: {
|
|
4449
4481
|
type: "DecryptionError",
|
|
@@ -4452,6 +4484,7 @@ var Secrets = class {
|
|
|
4452
4484
|
};
|
|
4453
4485
|
}
|
|
4454
4486
|
if (typeof decryptResult.data !== "string") {
|
|
4487
|
+
logger.error("Decrypted secret value is not a string");
|
|
4455
4488
|
return {
|
|
4456
4489
|
failure: {
|
|
4457
4490
|
type: "DecryptionError",
|
|
@@ -4476,6 +4509,7 @@ var Secrets = class {
|
|
|
4476
4509
|
* @returns A Result containing an object mapping secret names to their decrypted values
|
|
4477
4510
|
*/
|
|
4478
4511
|
async getMany(names) {
|
|
4512
|
+
logger.debug(`Getting ${names.length} secrets.`);
|
|
4479
4513
|
await this.ensureInitialized();
|
|
4480
4514
|
if (!this.encryptionClient) {
|
|
4481
4515
|
return {
|
|
@@ -4522,6 +4556,9 @@ var Secrets = class {
|
|
|
4522
4556
|
}));
|
|
4523
4557
|
const decryptResult = await this.encryptionClient.bulkDecryptModels(dataToDecrypt);
|
|
4524
4558
|
if (decryptResult.failure) {
|
|
4559
|
+
logger.error(
|
|
4560
|
+
`Failed to decrypt secrets: ${decryptResult.failure.message}`
|
|
4561
|
+
);
|
|
4525
4562
|
return {
|
|
4526
4563
|
failure: {
|
|
4527
4564
|
type: "DecryptionError",
|
|
@@ -4547,6 +4584,7 @@ var Secrets = class {
|
|
|
4547
4584
|
* @returns A Result containing the list of secrets or an error
|
|
4548
4585
|
*/
|
|
4549
4586
|
async list() {
|
|
4587
|
+
logger.debug("Listing secrets.");
|
|
4550
4588
|
const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
|
|
4551
4589
|
const apiResult = await this.apiRequest(
|
|
4552
4590
|
"GET",
|
|
@@ -4572,6 +4610,7 @@ var Secrets = class {
|
|
|
4572
4610
|
* @returns A Result containing the API response or an error
|
|
4573
4611
|
*/
|
|
4574
4612
|
async delete(name) {
|
|
4613
|
+
logger.debug("Deleting secret");
|
|
4575
4614
|
const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
|
|
4576
4615
|
return await this.apiRequest("POST", "/delete", {
|
|
4577
4616
|
body: {
|
|
@@ -4610,13 +4649,11 @@ function getConfig(environment) {
|
|
|
4610
4649
|
const workspaceCRN = process.env.CS_WORKSPACE_CRN;
|
|
4611
4650
|
const clientId = process.env.CS_CLIENT_ID;
|
|
4612
4651
|
const clientKey = process.env.CS_CLIENT_KEY;
|
|
4613
|
-
const apiKey = process.env.CS_CLIENT_ACCESS_KEY;
|
|
4614
4652
|
const accessKey = process.env.CS_ACCESS_KEY;
|
|
4615
4653
|
const missing = [];
|
|
4616
4654
|
if (!workspaceCRN) missing.push("CS_WORKSPACE_CRN");
|
|
4617
4655
|
if (!clientId) missing.push("CS_CLIENT_ID");
|
|
4618
4656
|
if (!clientKey) missing.push("CS_CLIENT_KEY");
|
|
4619
|
-
if (!apiKey) missing.push("CS_CLIENT_ACCESS_KEY");
|
|
4620
4657
|
if (missing.length > 0) {
|
|
4621
4658
|
console.error(
|
|
4622
4659
|
style.error(
|
|
@@ -4632,14 +4669,13 @@ ${style.info("Please set the following environment variables:")}`
|
|
|
4632
4669
|
}
|
|
4633
4670
|
process.exit(1);
|
|
4634
4671
|
}
|
|
4635
|
-
if (!workspaceCRN || !clientId || !clientKey || !
|
|
4672
|
+
if (!workspaceCRN || !clientId || !clientKey || !accessKey) {
|
|
4636
4673
|
throw new Error("Missing required configuration");
|
|
4637
4674
|
}
|
|
4638
4675
|
return {
|
|
4639
4676
|
workspaceCRN,
|
|
4640
4677
|
clientId,
|
|
4641
4678
|
clientKey,
|
|
4642
|
-
apiKey,
|
|
4643
4679
|
accessKey,
|
|
4644
4680
|
environment
|
|
4645
4681
|
};
|