@cipherstash/protect-ffi 0.19.0 → 0.20.1
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/README.md +18 -3
- package/lib/index.cjs +143 -9
- package/lib/index.d.cts +54 -4
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -38,12 +38,27 @@ $ npm i
|
|
|
38
38
|
$ npm run build
|
|
39
39
|
$ node
|
|
40
40
|
> const addon = require(".");
|
|
41
|
-
> const client = await addon.newClient(
|
|
42
|
-
> const ciphertext = await addon.encrypt(client, "plaintext", "email", "users");
|
|
43
|
-
> const plaintext = await addon.decrypt(client,
|
|
41
|
+
> const client = await addon.newClient({ encryptConfig: {v: 1, tables: {users: {email: {indexes: {ore: {}, match: {}, unique: {}}}}}} });
|
|
42
|
+
> const ciphertext = await addon.encrypt(client, { plaintext: "plaintext", column: "email", table: "users" });
|
|
43
|
+
> const plaintext = await addon.decrypt(client, { ciphertext });
|
|
44
44
|
> console.log({ciphertext, plaintext});
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
## Errors
|
|
48
|
+
|
|
49
|
+
Async API calls throw `ProtectError` with a stable `code` for programmatic handling.
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
try {
|
|
53
|
+
await addon.encryptQuery(client, opts)
|
|
54
|
+
} catch (err) {
|
|
55
|
+
if (err?.code === 'INVALID_JSON_PATH') {
|
|
56
|
+
// handle JSON path mistakes
|
|
57
|
+
}
|
|
58
|
+
throw err
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
47
62
|
## Available Scripts
|
|
48
63
|
|
|
49
64
|
In the project directory, you can run:
|
package/lib/index.cjs
CHANGED
|
@@ -1,12 +1,146 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// This module is the CJS entry point for the library.
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
3
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
37
|
+
exports.ProtectError = void 0;
|
|
38
|
+
exports.newClient = newClient;
|
|
39
|
+
exports.encrypt = encrypt;
|
|
40
|
+
exports.decrypt = decrypt;
|
|
41
|
+
exports.isEncrypted = isEncrypted;
|
|
42
|
+
exports.encryptBulk = encryptBulk;
|
|
43
|
+
exports.decryptBulk = decryptBulk;
|
|
44
|
+
exports.decryptBulkFallible = decryptBulkFallible;
|
|
45
|
+
exports.encryptQuery = encryptQuery;
|
|
46
|
+
exports.encryptQueryBulk = encryptQueryBulk;
|
|
47
|
+
const native = __importStar(require("./load.cjs"));
|
|
48
|
+
class ProtectError extends Error {
|
|
49
|
+
code;
|
|
50
|
+
details;
|
|
51
|
+
cause;
|
|
52
|
+
constructor(opts) {
|
|
53
|
+
super(opts.message);
|
|
54
|
+
this.name = 'ProtectError';
|
|
55
|
+
this.code = opts.code;
|
|
56
|
+
this.details = opts.details;
|
|
57
|
+
this.cause = opts.cause;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.ProtectError = ProtectError;
|
|
61
|
+
function inferErrorCode(message) {
|
|
62
|
+
if (message.startsWith('protect-ffi invariant violation:')) {
|
|
63
|
+
return 'INVARIANT_VIOLATION';
|
|
64
|
+
}
|
|
65
|
+
if (message.startsWith('Unknown query operation:')) {
|
|
66
|
+
return 'UNKNOWN_QUERY_OP';
|
|
67
|
+
}
|
|
68
|
+
if (message.startsWith('Invalid query input for')) {
|
|
69
|
+
return 'INVALID_QUERY_INPUT';
|
|
70
|
+
}
|
|
71
|
+
if (message.startsWith('Invalid JSON path')) {
|
|
72
|
+
return 'INVALID_JSON_PATH';
|
|
73
|
+
}
|
|
74
|
+
if (message.includes(' not found in Encrypt config')) {
|
|
75
|
+
return 'UNKNOWN_COLUMN';
|
|
76
|
+
}
|
|
77
|
+
if (message.includes(' index configured')) {
|
|
78
|
+
return 'MISSING_INDEX';
|
|
79
|
+
}
|
|
80
|
+
if (message.includes("ste_vec index requires cast_as: 'json'")) {
|
|
81
|
+
return 'STE_VEC_REQUIRES_JSON_CAST_AS';
|
|
82
|
+
}
|
|
83
|
+
return 'UNKNOWN';
|
|
84
|
+
}
|
|
85
|
+
function normalizeError(err) {
|
|
86
|
+
if (err instanceof ProtectError) {
|
|
87
|
+
return err;
|
|
88
|
+
}
|
|
89
|
+
if (err && typeof err === 'object' && 'message' in err) {
|
|
90
|
+
const message = String(err.message ?? 'Unknown error');
|
|
91
|
+
const code = inferErrorCode(message);
|
|
92
|
+
if (code !== 'UNKNOWN') {
|
|
93
|
+
return new ProtectError({ code, message, cause: err });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return err;
|
|
97
|
+
}
|
|
98
|
+
async function wrapAsync(fn) {
|
|
99
|
+
try {
|
|
100
|
+
return await fn();
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
throw normalizeError(err);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function wrapSync(fn) {
|
|
107
|
+
try {
|
|
108
|
+
return fn();
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
throw normalizeError(err);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function newClient(opts) {
|
|
115
|
+
return wrapAsync(() => native.newClient(opts));
|
|
116
|
+
}
|
|
117
|
+
function encrypt(client, opts) {
|
|
118
|
+
return wrapAsync(() => native.encrypt(client, opts));
|
|
119
|
+
}
|
|
120
|
+
function decrypt(client, opts) {
|
|
121
|
+
return wrapAsync(() => native.decrypt(client, opts));
|
|
122
|
+
}
|
|
123
|
+
function isEncrypted(encrypted) {
|
|
124
|
+
return wrapSync(() => native.isEncrypted(encrypted));
|
|
125
|
+
}
|
|
126
|
+
function encryptBulk(client, opts) {
|
|
127
|
+
return wrapAsync(() => native.encryptBulk(client, opts));
|
|
128
|
+
}
|
|
129
|
+
function decryptBulk(client, opts) {
|
|
130
|
+
return wrapAsync(() => native.decryptBulk(client, opts));
|
|
131
|
+
}
|
|
132
|
+
async function decryptBulkFallible(client, opts) {
|
|
133
|
+
const results = await wrapAsync(() => native.decryptBulkFallible(client, opts));
|
|
134
|
+
return results.map((item) => {
|
|
135
|
+
if ('error' in item && typeof item.error === 'string') {
|
|
136
|
+
return { ...item, code: inferErrorCode(item.error) };
|
|
137
|
+
}
|
|
138
|
+
return item;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function encryptQuery(client, opts) {
|
|
142
|
+
return wrapAsync(() => native.encryptQuery(client, opts));
|
|
143
|
+
}
|
|
144
|
+
function encryptQueryBulk(client, opts) {
|
|
145
|
+
return wrapAsync(() => native.encryptQueryBulk(client, opts));
|
|
146
|
+
}
|
package/lib/index.d.cts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { newClient, encrypt, encryptBulk, isEncrypted, decrypt, decryptBulk, decryptBulkFallible, } from './load.cjs';
|
|
2
1
|
declare const sym: unique symbol;
|
|
3
2
|
export type Client = {
|
|
4
3
|
readonly [sym]: unknown;
|
|
@@ -11,12 +10,36 @@ declare module './load.cjs' {
|
|
|
11
10
|
function encryptBulk(client: Client, opts: EncryptBulkOptions): Promise<Encrypted[]>;
|
|
12
11
|
function decryptBulk(client: Client, opts: DecryptBulkOptions): Promise<JsPlaintext[]>;
|
|
13
12
|
function decryptBulkFallible(client: Client, opts: DecryptBulkOptions): Promise<DecryptResult[]>;
|
|
13
|
+
function encryptQuery(client: Client, opts: EncryptQueryOptions): Promise<Encrypted>;
|
|
14
|
+
function encryptQueryBulk(client: Client, opts: EncryptQueryBulkOptions): Promise<Encrypted[]>;
|
|
15
|
+
}
|
|
16
|
+
export type ProtectErrorCode = 'INVARIANT_VIOLATION' | 'UNKNOWN_QUERY_OP' | 'UNKNOWN_COLUMN' | 'MISSING_INDEX' | 'INVALID_QUERY_INPUT' | 'INVALID_JSON_PATH' | 'STE_VEC_REQUIRES_JSON_CAST_AS' | 'UNKNOWN';
|
|
17
|
+
export declare class ProtectError extends Error {
|
|
18
|
+
code: ProtectErrorCode;
|
|
19
|
+
details?: unknown;
|
|
20
|
+
cause?: unknown;
|
|
21
|
+
constructor(opts: {
|
|
22
|
+
code: ProtectErrorCode;
|
|
23
|
+
message: string;
|
|
24
|
+
details?: unknown;
|
|
25
|
+
cause?: unknown;
|
|
26
|
+
});
|
|
14
27
|
}
|
|
15
28
|
export type DecryptResult = {
|
|
16
|
-
data:
|
|
29
|
+
data: JsPlaintext;
|
|
17
30
|
} | {
|
|
18
31
|
error: string;
|
|
19
|
-
|
|
32
|
+
code?: ProtectErrorCode;
|
|
33
|
+
};
|
|
34
|
+
export declare function newClient(opts: NewClientOptions): Promise<Client>;
|
|
35
|
+
export declare function encrypt(client: Client, opts: EncryptOptions): Promise<Encrypted>;
|
|
36
|
+
export declare function decrypt(client: Client, opts: DecryptOptions): Promise<JsPlaintext>;
|
|
37
|
+
export declare function isEncrypted(encrypted: Encrypted): boolean;
|
|
38
|
+
export declare function encryptBulk(client: Client, opts: EncryptBulkOptions): Promise<Encrypted[]>;
|
|
39
|
+
export declare function decryptBulk(client: Client, opts: DecryptBulkOptions): Promise<JsPlaintext[]>;
|
|
40
|
+
export declare function decryptBulkFallible(client: Client, opts: DecryptBulkOptions): Promise<DecryptResult[]>;
|
|
41
|
+
export declare function encryptQuery(client: Client, opts: EncryptQueryOptions): Promise<Encrypted>;
|
|
42
|
+
export declare function encryptQueryBulk(client: Client, opts: EncryptQueryBulkOptions): Promise<Encrypted[]>;
|
|
20
43
|
export type EncryptPayload = {
|
|
21
44
|
plaintext: JsPlaintext;
|
|
22
45
|
column: string;
|
|
@@ -135,6 +158,7 @@ export type MatchIndexOpts = {
|
|
|
135
158
|
};
|
|
136
159
|
export type SteVecIndexOpts = {
|
|
137
160
|
prefix: string;
|
|
161
|
+
term_filters?: TokenFilter[];
|
|
138
162
|
};
|
|
139
163
|
export type Tokenizer = {
|
|
140
164
|
kind: 'standard';
|
|
@@ -161,7 +185,7 @@ export type KeysetIdentifier = {
|
|
|
161
185
|
} | {
|
|
162
186
|
Name: string;
|
|
163
187
|
};
|
|
164
|
-
export type JsPlaintext = string | number | Record<string, unknown> | JsPlaintext[];
|
|
188
|
+
export type JsPlaintext = string | number | boolean | Record<string, unknown> | JsPlaintext[];
|
|
165
189
|
export type EncryptOptions = {
|
|
166
190
|
plaintext: JsPlaintext;
|
|
167
191
|
column: string;
|
|
@@ -186,3 +210,29 @@ export type DecryptBulkOptions = {
|
|
|
186
210
|
serviceToken?: CtsToken;
|
|
187
211
|
unverifiedContext?: Record<string, unknown>;
|
|
188
212
|
};
|
|
213
|
+
export type IndexTypeName = 'ste_vec' | 'match' | 'ore' | 'unique';
|
|
214
|
+
export type QueryOpName = 'default' | 'ste_vec_selector' | 'ste_vec_term';
|
|
215
|
+
export type EncryptQueryOptions = {
|
|
216
|
+
plaintext: JsPlaintext;
|
|
217
|
+
column: string;
|
|
218
|
+
table: string;
|
|
219
|
+
indexType: IndexTypeName;
|
|
220
|
+
queryOp?: QueryOpName;
|
|
221
|
+
lockContext?: Context;
|
|
222
|
+
serviceToken?: CtsToken;
|
|
223
|
+
unverifiedContext?: Record<string, unknown>;
|
|
224
|
+
};
|
|
225
|
+
export type QueryPayload = {
|
|
226
|
+
plaintext: JsPlaintext;
|
|
227
|
+
column: string;
|
|
228
|
+
table: string;
|
|
229
|
+
indexType: IndexTypeName;
|
|
230
|
+
queryOp?: QueryOpName;
|
|
231
|
+
lockContext?: Context;
|
|
232
|
+
};
|
|
233
|
+
export type EncryptQueryBulkOptions = {
|
|
234
|
+
queries: QueryPayload[];
|
|
235
|
+
serviceToken?: CtsToken;
|
|
236
|
+
unverifiedContext?: Record<string, unknown>;
|
|
237
|
+
};
|
|
238
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cipherstash/protect-ffi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/index.cjs",
|
|
6
6
|
"scripts": {
|
|
@@ -67,11 +67,11 @@
|
|
|
67
67
|
"@neon-rs/load": "^0.1.82"
|
|
68
68
|
},
|
|
69
69
|
"optionalDependencies": {
|
|
70
|
-
"@cipherstash/protect-ffi-darwin-x64": "0.
|
|
71
|
-
"@cipherstash/protect-ffi-darwin-arm64": "0.
|
|
72
|
-
"@cipherstash/protect-ffi-win32-x64-msvc": "0.
|
|
73
|
-
"@cipherstash/protect-ffi-linux-x64-gnu": "0.
|
|
74
|
-
"@cipherstash/protect-ffi-linux-arm64-gnu": "0.
|
|
75
|
-
"@cipherstash/protect-ffi-linux-x64-musl": "0.
|
|
70
|
+
"@cipherstash/protect-ffi-darwin-x64": "0.20.1",
|
|
71
|
+
"@cipherstash/protect-ffi-darwin-arm64": "0.20.1",
|
|
72
|
+
"@cipherstash/protect-ffi-win32-x64-msvc": "0.20.1",
|
|
73
|
+
"@cipherstash/protect-ffi-linux-x64-gnu": "0.20.1",
|
|
74
|
+
"@cipherstash/protect-ffi-linux-arm64-gnu": "0.20.1",
|
|
75
|
+
"@cipherstash/protect-ffi-linux-x64-musl": "0.20.1"
|
|
76
76
|
}
|
|
77
77
|
}
|