@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 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(JSON.stringify({v: 1, tables: {users: {email: {indexes: {ore: {}, match: {}, unique: {}}}}}}));
42
- > const ciphertext = await addon.encrypt(client, "plaintext", "email", "users");
43
- > const plaintext = await addon.decrypt(client, JSON.parse(ciphertext).c);
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.decryptBulkFallible = exports.decryptBulk = exports.decrypt = exports.isEncrypted = exports.encryptQueryBulk = exports.encryptQuery = exports.encryptBulk = exports.encrypt = exports.newClient = void 0;
5
- var load_cjs_1 = require("./load.cjs");
6
- Object.defineProperty(exports, "newClient", { enumerable: true, get: function () { return load_cjs_1.newClient; } });
7
- Object.defineProperty(exports, "encrypt", { enumerable: true, get: function () { return load_cjs_1.encrypt; } });
8
- Object.defineProperty(exports, "encryptBulk", { enumerable: true, get: function () { return load_cjs_1.encryptBulk; } });
9
- Object.defineProperty(exports, "encryptQuery", { enumerable: true, get: function () { return load_cjs_1.encryptQuery; } });
10
- Object.defineProperty(exports, "encryptQueryBulk", { enumerable: true, get: function () { return load_cjs_1.encryptQueryBulk; } });
11
- Object.defineProperty(exports, "isEncrypted", { enumerable: true, get: function () { return load_cjs_1.isEncrypted; } });
12
- Object.defineProperty(exports, "decrypt", { enumerable: true, get: function () { return load_cjs_1.decrypt; } });
13
- Object.defineProperty(exports, "decryptBulk", { enumerable: true, get: function () { return load_cjs_1.decryptBulk; } });
14
- Object.defineProperty(exports, "decryptBulkFallible", { enumerable: true, get: function () { return load_cjs_1.decryptBulkFallible; } });
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: string;
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.0",
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.0",
71
- "@cipherstash/protect-ffi-darwin-arm64": "0.20.0",
72
- "@cipherstash/protect-ffi-win32-x64-msvc": "0.20.0",
73
- "@cipherstash/protect-ffi-linux-x64-gnu": "0.20.0",
74
- "@cipherstash/protect-ffi-linux-arm64-gnu": "0.20.0",
75
- "@cipherstash/protect-ffi-linux-x64-musl": "0.20.0"
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
  }