@cipherstash/protect-ffi 0.20.0 → 0.20.2
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 -11
- package/lib/index.d.cts +28 -5
- 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,14 +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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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, encryptQuery, encryptQueryBulk, isEncrypted, decrypt, decryptBulk, decryptBulkFallible, } from './load.cjs';
|
|
2
1
|
declare const sym: unique symbol;
|
|
3
2
|
export type Client = {
|
|
4
3
|
readonly [sym]: unknown;
|
|
@@ -14,11 +13,33 @@ declare module './load.cjs' {
|
|
|
14
13
|
function encryptQuery(client: Client, opts: EncryptQueryOptions): Promise<Encrypted>;
|
|
15
14
|
function encryptQueryBulk(client: Client, opts: EncryptQueryBulkOptions): Promise<Encrypted[]>;
|
|
16
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
|
+
});
|
|
27
|
+
}
|
|
17
28
|
export type DecryptResult = {
|
|
18
|
-
data:
|
|
29
|
+
data: JsPlaintext;
|
|
19
30
|
} | {
|
|
20
31
|
error: string;
|
|
21
|
-
|
|
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[]>;
|
|
22
43
|
export type EncryptPayload = {
|
|
23
44
|
plaintext: JsPlaintext;
|
|
24
45
|
column: string;
|
|
@@ -108,7 +129,7 @@ export type Column = {
|
|
|
108
129
|
cast_as?: CastAs;
|
|
109
130
|
indexes?: Indexes;
|
|
110
131
|
};
|
|
111
|
-
export type CastAs = 'bigint' | 'boolean' | 'date' | 'number' | 'string' | 'json';
|
|
132
|
+
export type CastAs = 'bigint' | 'boolean' | 'date' | 'number' | 'string' | 'text' | 'json';
|
|
112
133
|
type TablesOf<C extends EncryptConfig> = C['tables'];
|
|
113
134
|
export type Identifier<C extends EncryptConfig> = {
|
|
114
135
|
[T in keyof TablesOf<C>]: {
|
|
@@ -137,6 +158,7 @@ export type MatchIndexOpts = {
|
|
|
137
158
|
};
|
|
138
159
|
export type SteVecIndexOpts = {
|
|
139
160
|
prefix: string;
|
|
161
|
+
term_filters?: TokenFilter[];
|
|
140
162
|
};
|
|
141
163
|
export type Tokenizer = {
|
|
142
164
|
kind: 'standard';
|
|
@@ -163,7 +185,7 @@ export type KeysetIdentifier = {
|
|
|
163
185
|
} | {
|
|
164
186
|
Name: string;
|
|
165
187
|
};
|
|
166
|
-
export type JsPlaintext = string | number | Record<string, unknown> | JsPlaintext[];
|
|
188
|
+
export type JsPlaintext = string | number | boolean | Record<string, unknown> | JsPlaintext[];
|
|
167
189
|
export type EncryptOptions = {
|
|
168
190
|
plaintext: JsPlaintext;
|
|
169
191
|
column: string;
|
|
@@ -213,3 +235,4 @@ export type EncryptQueryBulkOptions = {
|
|
|
213
235
|
serviceToken?: CtsToken;
|
|
214
236
|
unverifiedContext?: Record<string, unknown>;
|
|
215
237
|
};
|
|
238
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cipherstash/protect-ffi",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.2",
|
|
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.20.
|
|
71
|
-
"@cipherstash/protect-ffi-darwin-arm64": "0.20.
|
|
72
|
-
"@cipherstash/protect-ffi-win32-x64-msvc": "0.20.
|
|
73
|
-
"@cipherstash/protect-ffi-linux-x64-gnu": "0.20.
|
|
74
|
-
"@cipherstash/protect-ffi-linux-arm64-gnu": "0.20.
|
|
75
|
-
"@cipherstash/protect-ffi-linux-x64-musl": "0.20.
|
|
70
|
+
"@cipherstash/protect-ffi-darwin-x64": "0.20.2",
|
|
71
|
+
"@cipherstash/protect-ffi-darwin-arm64": "0.20.2",
|
|
72
|
+
"@cipherstash/protect-ffi-win32-x64-msvc": "0.20.2",
|
|
73
|
+
"@cipherstash/protect-ffi-linux-x64-gnu": "0.20.2",
|
|
74
|
+
"@cipherstash/protect-ffi-linux-arm64-gnu": "0.20.2",
|
|
75
|
+
"@cipherstash/protect-ffi-linux-x64-musl": "0.20.2"
|
|
76
76
|
}
|
|
77
77
|
}
|