@cipherstash/stack 0.16.0 → 0.18.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 +52 -0
- package/dist/{chunk-6FD7OBGM.js → chunk-LLCCNKDL.js} +3 -3
- package/dist/chunk-LLCCNKDL.js.map +1 -0
- package/dist/{chunk-MD6742R6.js → chunk-VPOTNP4K.js} +1 -1
- package/dist/chunk-VPOTNP4K.js.map +1 -0
- package/dist/{chunk-4RNBI3UH.js → chunk-XWPGAHBZ.js} +1 -1
- package/dist/chunk-XWPGAHBZ.js.map +1 -0
- package/dist/{chunk-JDZ2QUUF.js → chunk-YWQXTZ5M.js} +4 -2
- package/dist/{chunk-JDZ2QUUF.js.map → chunk-YWQXTZ5M.js.map} +1 -1
- package/dist/{chunk-CY5B4LIF.js → chunk-ZYOZHZMJ.js} +160 -52
- package/dist/chunk-ZYOZHZMJ.js.map +1 -0
- package/dist/{client-BLbA6aFD.d.ts → client-CIsfZ2zg.d.ts} +17 -22
- package/dist/{client-C_7TF8EL.d.cts → client-Dt98Rugc.d.cts} +17 -22
- package/dist/client.cjs +2 -0
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -2
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1 -1
- package/dist/drizzle/index.cjs +6 -3
- package/dist/drizzle/index.cjs.map +1 -1
- package/dist/drizzle/index.d.cts +2 -2
- package/dist/drizzle/index.d.ts +2 -2
- package/dist/drizzle/index.js +6 -5
- package/dist/drizzle/index.js.map +1 -1
- package/dist/dynamodb/index.cjs +14 -4
- package/dist/dynamodb/index.cjs.map +1 -1
- package/dist/dynamodb/index.d.cts +12 -12
- package/dist/dynamodb/index.d.ts +12 -12
- package/dist/dynamodb/index.js +9 -3
- package/dist/dynamodb/index.js.map +1 -1
- package/dist/encryption/index.cjs +168 -50
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.d.cts +2 -2
- package/dist/encryption/index.d.ts +2 -2
- package/dist/encryption/index.js +25 -5
- package/dist/identity/index.cjs +2 -2
- package/dist/identity/index.cjs.map +1 -1
- package/dist/identity/index.js +3 -3
- package/dist/index.cjs +150 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -5
- package/dist/schema/index.cjs +3 -1
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/supabase/index.cjs +2 -2
- package/dist/supabase/index.cjs.map +1 -1
- package/dist/supabase/index.d.cts +2 -2
- package/dist/supabase/index.d.ts +2 -2
- package/dist/supabase/index.js +3 -3
- package/dist/{types-public-Dv-r6Ik0.d.ts → types-public-BTxqjmtv.d.cts} +95 -80
- package/dist/{types-public-Dv-r6Ik0.d.cts → types-public-BTxqjmtv.d.ts} +95 -80
- package/dist/types-public.cjs.map +1 -1
- package/dist/types-public.d.cts +1 -1
- package/dist/types-public.d.ts +1 -1
- package/dist/types-public.js +1 -1
- package/package.json +12 -12
- package/dist/chunk-4RNBI3UH.js.map +0 -1
- package/dist/chunk-6FD7OBGM.js.map +0 -1
- package/dist/chunk-CY5B4LIF.js.map +0 -1
- package/dist/chunk-MD6742R6.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { Encrypted as Encrypted$1, newClient, JsPlaintext } from '@cipherstash/protect-ffi';
|
|
2
|
+
import { Encrypted as Encrypted$1, newClient, EncryptedQuery as EncryptedQuery$1, JsPlaintext } from '@cipherstash/protect-ffi';
|
|
3
3
|
|
|
4
4
|
/** Brand symbol for nominal typing */
|
|
5
5
|
declare const __brand: unique symbol;
|
|
@@ -10,8 +10,18 @@ type Brand<T, B extends string> = T & {
|
|
|
10
10
|
type Client = Awaited<ReturnType<typeof newClient>> | undefined;
|
|
11
11
|
/** A branded type representing encrypted data. Cannot be accidentally used as plaintext. */
|
|
12
12
|
type EncryptedValue = Brand<Encrypted$1, 'encrypted'>;
|
|
13
|
-
/** Structural type representing encrypted data
|
|
13
|
+
/** Structural type representing encrypted data stored in the database. Always
|
|
14
|
+
* carries a ciphertext. See also `EncryptedValue` for branded nominal typing,
|
|
15
|
+
* and {@link EncryptedQuery} for the search-term shape returned by
|
|
16
|
+
* `encryptQuery`. */
|
|
14
17
|
type Encrypted = Encrypted$1;
|
|
18
|
+
/** Structural type representing an encrypted query term (search needle)
|
|
19
|
+
* returned by `encryptQuery` / `encryptQueryBulk` for scalar
|
|
20
|
+
* (`unique` / `match` / `ore`) lookups and `ste_vec_selector` JSON path
|
|
21
|
+
* queries. Carries no ciphertext — matched against stored values, never
|
|
22
|
+
* decrypted. JSON containment queries (`ste_vec_term`) return a
|
|
23
|
+
* storage-shaped {@link Encrypted} payload instead. */
|
|
24
|
+
type EncryptedQuery = EncryptedQuery$1;
|
|
15
25
|
type KeysetIdentifier = {
|
|
16
26
|
name: string;
|
|
17
27
|
} | {
|
|
@@ -73,10 +83,15 @@ type SearchTerm = {
|
|
|
73
83
|
table: EncryptedTable<EncryptedTableColumn>;
|
|
74
84
|
returnType?: EncryptedReturnType;
|
|
75
85
|
};
|
|
76
|
-
/** Encrypted search term result
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
86
|
+
/** Encrypted search term result. `eql` return type yields either a storage
|
|
87
|
+
* payload (`Encrypted`, for `ste_vec_term`) or a query-only term
|
|
88
|
+
* (`EncryptedQuery`, for scalar lookups and `ste_vec_selector`); the
|
|
89
|
+
* `composite-literal` return types yield a string. */
|
|
90
|
+
type EncryptedSearchTerm = Encrypted | EncryptedQuery | string;
|
|
91
|
+
/** Result of encryptQuery (single or batch). `eql` return type yields either a
|
|
92
|
+
* storage payload (`Encrypted`) or a query-only term (`EncryptedQuery`); the
|
|
93
|
+
* `composite-literal` return types yield a string. */
|
|
94
|
+
type EncryptedQueryResult = Encrypted | EncryptedQuery | string | null;
|
|
80
95
|
type EncryptedFields<T> = {
|
|
81
96
|
[K in keyof T as NonNullable<T[K]> extends Encrypted ? K : never]: T[K];
|
|
82
97
|
};
|
|
@@ -114,17 +129,17 @@ type EncryptedFromSchema<T, S extends EncryptedTableColumn> = {
|
|
|
114
129
|
};
|
|
115
130
|
type BulkEncryptPayload = Array<{
|
|
116
131
|
id?: string;
|
|
117
|
-
plaintext: JsPlaintext;
|
|
132
|
+
plaintext: JsPlaintext | null;
|
|
118
133
|
}>;
|
|
119
134
|
type BulkEncryptedData = Array<{
|
|
120
135
|
id?: string;
|
|
121
|
-
data: Encrypted;
|
|
136
|
+
data: Encrypted | null;
|
|
122
137
|
}>;
|
|
123
138
|
type BulkDecryptPayload = Array<{
|
|
124
139
|
id?: string;
|
|
125
|
-
data: Encrypted;
|
|
140
|
+
data: Encrypted | null;
|
|
126
141
|
}>;
|
|
127
|
-
type BulkDecryptedData = Array<DecryptionResult<JsPlaintext>>;
|
|
142
|
+
type BulkDecryptedData = Array<DecryptionResult<JsPlaintext | null>>;
|
|
128
143
|
type DecryptionSuccess<T> = {
|
|
129
144
|
error?: never;
|
|
130
145
|
data: T;
|
|
@@ -421,6 +436,12 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
421
436
|
} | undefined;
|
|
422
437
|
}>>;
|
|
423
438
|
}, "strip", z.ZodTypeAny, {
|
|
439
|
+
ore?: {} | undefined;
|
|
440
|
+
unique?: {
|
|
441
|
+
token_filters?: {
|
|
442
|
+
kind: "downcase";
|
|
443
|
+
}[] | undefined;
|
|
444
|
+
} | undefined;
|
|
424
445
|
match?: {
|
|
425
446
|
token_filters?: {
|
|
426
447
|
kind: "downcase";
|
|
@@ -435,12 +456,6 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
435
456
|
m?: number | undefined;
|
|
436
457
|
include_original?: boolean | undefined;
|
|
437
458
|
} | undefined;
|
|
438
|
-
ore?: {} | undefined;
|
|
439
|
-
unique?: {
|
|
440
|
-
token_filters?: {
|
|
441
|
-
kind: "downcase";
|
|
442
|
-
}[] | undefined;
|
|
443
|
-
} | undefined;
|
|
444
459
|
ste_vec?: {
|
|
445
460
|
prefix: string;
|
|
446
461
|
array_index_mode?: "all" | "none" | {
|
|
@@ -450,6 +465,12 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
450
465
|
} | undefined;
|
|
451
466
|
} | undefined;
|
|
452
467
|
}, {
|
|
468
|
+
ore?: {} | undefined;
|
|
469
|
+
unique?: {
|
|
470
|
+
token_filters?: {
|
|
471
|
+
kind: "downcase";
|
|
472
|
+
}[] | undefined;
|
|
473
|
+
} | undefined;
|
|
453
474
|
match?: {
|
|
454
475
|
token_filters?: {
|
|
455
476
|
kind: "downcase";
|
|
@@ -464,12 +485,6 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
464
485
|
m?: number | undefined;
|
|
465
486
|
include_original?: boolean | undefined;
|
|
466
487
|
} | undefined;
|
|
467
|
-
ore?: {} | undefined;
|
|
468
|
-
unique?: {
|
|
469
|
-
token_filters?: {
|
|
470
|
-
kind: "downcase";
|
|
471
|
-
}[] | undefined;
|
|
472
|
-
} | undefined;
|
|
473
488
|
ste_vec?: {
|
|
474
489
|
prefix: string;
|
|
475
490
|
array_index_mode?: "all" | "none" | {
|
|
@@ -480,8 +495,14 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
480
495
|
} | undefined;
|
|
481
496
|
}>>;
|
|
482
497
|
}, "strip", z.ZodTypeAny, {
|
|
483
|
-
cast_as: "string" | "number" | "bigint" | "boolean" | "
|
|
498
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "json" | "text";
|
|
484
499
|
indexes: {
|
|
500
|
+
ore?: {} | undefined;
|
|
501
|
+
unique?: {
|
|
502
|
+
token_filters?: {
|
|
503
|
+
kind: "downcase";
|
|
504
|
+
}[] | undefined;
|
|
505
|
+
} | undefined;
|
|
485
506
|
match?: {
|
|
486
507
|
token_filters?: {
|
|
487
508
|
kind: "downcase";
|
|
@@ -496,12 +517,6 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
496
517
|
m?: number | undefined;
|
|
497
518
|
include_original?: boolean | undefined;
|
|
498
519
|
} | undefined;
|
|
499
|
-
ore?: {} | undefined;
|
|
500
|
-
unique?: {
|
|
501
|
-
token_filters?: {
|
|
502
|
-
kind: "downcase";
|
|
503
|
-
}[] | undefined;
|
|
504
|
-
} | undefined;
|
|
505
520
|
ste_vec?: {
|
|
506
521
|
prefix: string;
|
|
507
522
|
array_index_mode?: "all" | "none" | {
|
|
@@ -512,8 +527,14 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
512
527
|
} | undefined;
|
|
513
528
|
};
|
|
514
529
|
}, {
|
|
515
|
-
cast_as?: "string" | "number" | "bigint" | "boolean" | "
|
|
530
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "json" | "text" | undefined;
|
|
516
531
|
indexes?: {
|
|
532
|
+
ore?: {} | undefined;
|
|
533
|
+
unique?: {
|
|
534
|
+
token_filters?: {
|
|
535
|
+
kind: "downcase";
|
|
536
|
+
}[] | undefined;
|
|
537
|
+
} | undefined;
|
|
517
538
|
match?: {
|
|
518
539
|
token_filters?: {
|
|
519
540
|
kind: "downcase";
|
|
@@ -528,12 +549,6 @@ declare const columnSchema: z.ZodDefault<z.ZodObject<{
|
|
|
528
549
|
m?: number | undefined;
|
|
529
550
|
include_original?: boolean | undefined;
|
|
530
551
|
} | undefined;
|
|
531
|
-
ore?: {} | undefined;
|
|
532
|
-
unique?: {
|
|
533
|
-
token_filters?: {
|
|
534
|
-
kind: "downcase";
|
|
535
|
-
}[] | undefined;
|
|
536
|
-
} | undefined;
|
|
537
552
|
ste_vec?: {
|
|
538
553
|
prefix: string;
|
|
539
554
|
array_index_mode?: "all" | "none" | {
|
|
@@ -653,6 +668,12 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
653
668
|
} | undefined;
|
|
654
669
|
}>>;
|
|
655
670
|
}, "strip", z.ZodTypeAny, {
|
|
671
|
+
ore?: {} | undefined;
|
|
672
|
+
unique?: {
|
|
673
|
+
token_filters?: {
|
|
674
|
+
kind: "downcase";
|
|
675
|
+
}[] | undefined;
|
|
676
|
+
} | undefined;
|
|
656
677
|
match?: {
|
|
657
678
|
token_filters?: {
|
|
658
679
|
kind: "downcase";
|
|
@@ -667,12 +688,6 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
667
688
|
m?: number | undefined;
|
|
668
689
|
include_original?: boolean | undefined;
|
|
669
690
|
} | undefined;
|
|
670
|
-
ore?: {} | undefined;
|
|
671
|
-
unique?: {
|
|
672
|
-
token_filters?: {
|
|
673
|
-
kind: "downcase";
|
|
674
|
-
}[] | undefined;
|
|
675
|
-
} | undefined;
|
|
676
691
|
ste_vec?: {
|
|
677
692
|
prefix: string;
|
|
678
693
|
array_index_mode?: "all" | "none" | {
|
|
@@ -682,6 +697,12 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
682
697
|
} | undefined;
|
|
683
698
|
} | undefined;
|
|
684
699
|
}, {
|
|
700
|
+
ore?: {} | undefined;
|
|
701
|
+
unique?: {
|
|
702
|
+
token_filters?: {
|
|
703
|
+
kind: "downcase";
|
|
704
|
+
}[] | undefined;
|
|
705
|
+
} | undefined;
|
|
685
706
|
match?: {
|
|
686
707
|
token_filters?: {
|
|
687
708
|
kind: "downcase";
|
|
@@ -696,12 +717,6 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
696
717
|
m?: number | undefined;
|
|
697
718
|
include_original?: boolean | undefined;
|
|
698
719
|
} | undefined;
|
|
699
|
-
ore?: {} | undefined;
|
|
700
|
-
unique?: {
|
|
701
|
-
token_filters?: {
|
|
702
|
-
kind: "downcase";
|
|
703
|
-
}[] | undefined;
|
|
704
|
-
} | undefined;
|
|
705
720
|
ste_vec?: {
|
|
706
721
|
prefix: string;
|
|
707
722
|
array_index_mode?: "all" | "none" | {
|
|
@@ -712,8 +727,14 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
712
727
|
} | undefined;
|
|
713
728
|
}>>;
|
|
714
729
|
}, "strip", z.ZodTypeAny, {
|
|
715
|
-
cast_as: "string" | "number" | "bigint" | "boolean" | "
|
|
730
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "json" | "text";
|
|
716
731
|
indexes: {
|
|
732
|
+
ore?: {} | undefined;
|
|
733
|
+
unique?: {
|
|
734
|
+
token_filters?: {
|
|
735
|
+
kind: "downcase";
|
|
736
|
+
}[] | undefined;
|
|
737
|
+
} | undefined;
|
|
717
738
|
match?: {
|
|
718
739
|
token_filters?: {
|
|
719
740
|
kind: "downcase";
|
|
@@ -728,12 +749,6 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
728
749
|
m?: number | undefined;
|
|
729
750
|
include_original?: boolean | undefined;
|
|
730
751
|
} | undefined;
|
|
731
|
-
ore?: {} | undefined;
|
|
732
|
-
unique?: {
|
|
733
|
-
token_filters?: {
|
|
734
|
-
kind: "downcase";
|
|
735
|
-
}[] | undefined;
|
|
736
|
-
} | undefined;
|
|
737
752
|
ste_vec?: {
|
|
738
753
|
prefix: string;
|
|
739
754
|
array_index_mode?: "all" | "none" | {
|
|
@@ -744,8 +759,14 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
744
759
|
} | undefined;
|
|
745
760
|
};
|
|
746
761
|
}, {
|
|
747
|
-
cast_as?: "string" | "number" | "bigint" | "boolean" | "
|
|
762
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "json" | "text" | undefined;
|
|
748
763
|
indexes?: {
|
|
764
|
+
ore?: {} | undefined;
|
|
765
|
+
unique?: {
|
|
766
|
+
token_filters?: {
|
|
767
|
+
kind: "downcase";
|
|
768
|
+
}[] | undefined;
|
|
769
|
+
} | undefined;
|
|
749
770
|
match?: {
|
|
750
771
|
token_filters?: {
|
|
751
772
|
kind: "downcase";
|
|
@@ -760,12 +781,6 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
760
781
|
m?: number | undefined;
|
|
761
782
|
include_original?: boolean | undefined;
|
|
762
783
|
} | undefined;
|
|
763
|
-
ore?: {} | undefined;
|
|
764
|
-
unique?: {
|
|
765
|
-
token_filters?: {
|
|
766
|
-
kind: "downcase";
|
|
767
|
-
}[] | undefined;
|
|
768
|
-
} | undefined;
|
|
769
784
|
ste_vec?: {
|
|
770
785
|
prefix: string;
|
|
771
786
|
array_index_mode?: "all" | "none" | {
|
|
@@ -779,8 +794,14 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
779
794
|
}, "strip", z.ZodTypeAny, {
|
|
780
795
|
v: number;
|
|
781
796
|
tables: Record<string, Record<string, {
|
|
782
|
-
cast_as: "string" | "number" | "bigint" | "boolean" | "
|
|
797
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "json" | "text";
|
|
783
798
|
indexes: {
|
|
799
|
+
ore?: {} | undefined;
|
|
800
|
+
unique?: {
|
|
801
|
+
token_filters?: {
|
|
802
|
+
kind: "downcase";
|
|
803
|
+
}[] | undefined;
|
|
804
|
+
} | undefined;
|
|
784
805
|
match?: {
|
|
785
806
|
token_filters?: {
|
|
786
807
|
kind: "downcase";
|
|
@@ -795,12 +816,6 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
795
816
|
m?: number | undefined;
|
|
796
817
|
include_original?: boolean | undefined;
|
|
797
818
|
} | undefined;
|
|
798
|
-
ore?: {} | undefined;
|
|
799
|
-
unique?: {
|
|
800
|
-
token_filters?: {
|
|
801
|
-
kind: "downcase";
|
|
802
|
-
}[] | undefined;
|
|
803
|
-
} | undefined;
|
|
804
819
|
ste_vec?: {
|
|
805
820
|
prefix: string;
|
|
806
821
|
array_index_mode?: "all" | "none" | {
|
|
@@ -814,8 +829,14 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
814
829
|
}, {
|
|
815
830
|
v: number;
|
|
816
831
|
tables?: Record<string, Record<string, {
|
|
817
|
-
cast_as?: "string" | "number" | "bigint" | "boolean" | "
|
|
832
|
+
cast_as?: "string" | "number" | "bigint" | "boolean" | "date" | "json" | "text" | undefined;
|
|
818
833
|
indexes?: {
|
|
834
|
+
ore?: {} | undefined;
|
|
835
|
+
unique?: {
|
|
836
|
+
token_filters?: {
|
|
837
|
+
kind: "downcase";
|
|
838
|
+
}[] | undefined;
|
|
839
|
+
} | undefined;
|
|
819
840
|
match?: {
|
|
820
841
|
token_filters?: {
|
|
821
842
|
kind: "downcase";
|
|
@@ -830,12 +851,6 @@ declare const encryptConfigSchema: z.ZodObject<{
|
|
|
830
851
|
m?: number | undefined;
|
|
831
852
|
include_original?: boolean | undefined;
|
|
832
853
|
} | undefined;
|
|
833
|
-
ore?: {} | undefined;
|
|
834
|
-
unique?: {
|
|
835
|
-
token_filters?: {
|
|
836
|
-
kind: "downcase";
|
|
837
|
-
}[] | undefined;
|
|
838
|
-
} | undefined;
|
|
839
854
|
ste_vec?: {
|
|
840
855
|
prefix: string;
|
|
841
856
|
array_index_mode?: "all" | "none" | {
|
|
@@ -903,7 +918,7 @@ declare class EncryptedField {
|
|
|
903
918
|
*/
|
|
904
919
|
dataType(castAs: CastAs): this;
|
|
905
920
|
build(): {
|
|
906
|
-
cast_as: "string" | "number" | "bigint" | "boolean" | "
|
|
921
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "json" | "text";
|
|
907
922
|
indexes: {};
|
|
908
923
|
};
|
|
909
924
|
getName(): string;
|
|
@@ -1022,7 +1037,7 @@ declare class EncryptedColumn {
|
|
|
1022
1037
|
*/
|
|
1023
1038
|
searchableJson(): this;
|
|
1024
1039
|
build(): {
|
|
1025
|
-
cast_as: "string" | "number" | "bigint" | "boolean" | "
|
|
1040
|
+
cast_as: "string" | "number" | "bigint" | "boolean" | "date" | "json" | "text";
|
|
1026
1041
|
indexes: {
|
|
1027
1042
|
ore?: OreIndexOpts;
|
|
1028
1043
|
unique?: UniqueIndexOpts;
|
|
@@ -1178,7 +1193,7 @@ declare function encryptedField(valueName: string): EncryptedField;
|
|
|
1178
1193
|
/**
|
|
1179
1194
|
* Build an encrypt config from a list of encrypted tables.
|
|
1180
1195
|
*
|
|
1181
|
-
* @param
|
|
1196
|
+
* @param protectTables - The list of encrypted tables to build the config from.
|
|
1182
1197
|
* @returns An encrypt config object.
|
|
1183
1198
|
*
|
|
1184
1199
|
* @example
|
|
@@ -1199,4 +1214,4 @@ declare function encryptedField(valueName: string): EncryptedField;
|
|
|
1199
1214
|
*/
|
|
1200
1215
|
declare function buildEncryptConfig(...protectTables: Array<EncryptedTable<EncryptedTableColumn>>): EncryptConfig;
|
|
1201
1216
|
|
|
1202
|
-
export { eqlCastAsEnum as A, type BulkDecryptedData as B, type CastAs as C, type Decrypted as D, type Encrypted as E, toEqlCastAs as F, type ClientConfig as G, type DecryptedFields as H, type InferEncrypted as I, type DecryptionResult as J, type KeysetIdentifier as K, type EncryptedFields as L, type MatchIndexOpts as M, type
|
|
1217
|
+
export { eqlCastAsEnum as A, type BulkDecryptedData as B, type CastAs as C, type Decrypted as D, type Encrypted as E, toEqlCastAs as F, type ClientConfig as G, type DecryptedFields as H, type InferEncrypted as I, type DecryptionResult as J, type KeysetIdentifier as K, type EncryptedFields as L, type MatchIndexOpts as M, type EncryptedQuery as N, type OreIndexOpts as O, type EncryptedSearchTerm as P, type QueryTypeName as Q, type OtherFields as R, type ScalarQueryTerm as S, type TokenFilter as T, type UniqueIndexOpts as U, type SearchTerm as V, queryTypes as W, encryptedField as a, encryptedTable as b, EncryptedTable as c, type EncryptedTableColumn as d, encryptedColumn as e, EncryptedColumn as f, type EncryptedValue as g, type EncryptedQueryResult as h, type Client as i, type BulkDecryptPayload as j, type BulkEncryptedData as k, type BulkEncryptPayload as l, type EncryptOptions as m, EncryptedField as n, type EncryptQueryOptions as o, type EncryptedReturnType as p, type EncryptConfig as q, type EncryptedFromSchema as r, type EncryptionClientConfig as s, type InferPlaintext as t, type ColumnSchema as u, type EqlCastAs as v, type SteVecIndexOpts as w, buildEncryptConfig as x, castAsEnum as y, encryptConfigSchema as z };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types-public.ts","../src/types.ts"],"sourcesContent":["/**\n * Public type re-exports for `@cipherstash/stack/types`.\n *\n * This module exposes only the public types from the internal types module.\n * Internal helpers (`queryTypeToFfi`, `queryTypeToQueryOp`, `FfiIndexTypeName`,\n * `QueryTermBase`) are excluded.\n */\n\n// Core types\nexport type {\n Client,\n EncryptedValue,\n Encrypted,\n} from '@/types'\n\n// Client configuration\nexport type {\n KeysetIdentifier,\n ClientConfig,\n EncryptionClientConfig,\n} from '@/types'\n\n// Encrypt / decrypt operation options and results\nexport type {\n EncryptOptions,\n EncryptedReturnType,\n SearchTerm,\n EncryptedSearchTerm,\n EncryptedQueryResult,\n} from '@/types'\n\n// Model field types\nexport type {\n EncryptedFields,\n OtherFields,\n DecryptedFields,\n Decrypted,\n} from '@/types'\n\n// Bulk operations\nexport type {\n BulkEncryptPayload,\n BulkEncryptedData,\n BulkDecryptPayload,\n BulkDecryptedData,\n DecryptionResult,\n} from '@/types'\n\n// Query types (public only)\nexport type {\n QueryTypeName,\n EncryptQueryOptions,\n ScalarQueryTerm,\n} from '@/types'\n\n// Runtime values\nexport { queryTypes } from '@/types'\n","import type {\n EncryptedColumn,\n EncryptedField,\n EncryptedTable,\n EncryptedTableColumn,\n} from '@/schema'\nimport type {\n Encrypted as CipherStashEncrypted,\n JsPlaintext,\n QueryOpName,\n newClient,\n} from '@cipherstash/protect-ffi'\n\n// ---------------------------------------------------------------------------\n// Branded type utilities\n// ---------------------------------------------------------------------------\n\n/** Brand symbol for nominal typing */\ndeclare const __brand: unique symbol\n\n/** Creates a branded type that is structurally incompatible with the base type */\ntype Brand<T, B extends string> = T & { readonly [__brand]: B }\n\n// ---------------------------------------------------------------------------\n// Core types\n// ---------------------------------------------------------------------------\n\nexport type Client = Awaited<ReturnType<typeof newClient>> | undefined\n\n/** A branded type representing encrypted data. Cannot be accidentally used as plaintext. */\nexport type EncryptedValue = Brand<CipherStashEncrypted, 'encrypted'>\n\n/** Structural type representing encrypted data. See also `EncryptedValue` for branded nominal typing. */\nexport type Encrypted = CipherStashEncrypted\n\n// ---------------------------------------------------------------------------\n// Client configuration\n// ---------------------------------------------------------------------------\n\nexport type KeysetIdentifier = { name: string } | { id: string }\n\nexport type ClientConfig = {\n /**\n * The CipherStash workspace CRN (Cloud Resource Name).\n * Format: `crn:<region>.aws:<workspace-id>`.\n * Can also be set via the `CS_WORKSPACE_CRN` environment variable.\n */\n workspaceCrn?: string\n\n /**\n * The API access key used for authenticating with the CipherStash API.\n * Can also be set via the `CS_CLIENT_ACCESS_KEY` environment variable.\n * Obtain this from the CipherStash dashboard after creating a workspace.\n */\n accessKey?: string\n\n /**\n * The client identifier used to authenticate with CipherStash services.\n * Can also be set via the `CS_CLIENT_ID` environment variable.\n * Generated during workspace onboarding in the CipherStash dashboard.\n */\n clientId?: string\n\n /**\n * The client key material used in combination with ZeroKMS for encryption operations.\n * Can also be set via the `CS_CLIENT_KEY` environment variable.\n * Generated during workspace onboarding in the CipherStash dashboard.\n */\n clientKey?: string\n\n /**\n * An optional keyset identifier for multi-tenant encryption.\n * Each keyset provides cryptographic isolation, giving each tenant its own keyspace.\n * Specify by name (`{ name: \"tenant-a\" }`) or UUID (`{ id: \"...\" }`).\n * Keysets are created and managed in the CipherStash dashboard.\n */\n keyset?: KeysetIdentifier\n}\n\ntype AtLeastOneCsTable<T> = [T, ...T[]]\n\nexport type EncryptionClientConfig = {\n schemas: AtLeastOneCsTable<EncryptedTable<EncryptedTableColumn>>\n config?: ClientConfig\n}\n\n// ---------------------------------------------------------------------------\n// Encrypt / decrypt operation options and results\n// ---------------------------------------------------------------------------\n\n/**\n * Options for single-value encrypt operations.\n * Use a column from your table schema (from {@link encryptedColumn}) or a nested\n * field (from {@link encryptedField}) as the target for encryption.\n */\nexport type EncryptOptions = {\n /** The column or nested field to encrypt into. From {@link EncryptedColumn} or {@link EncryptedField}. */\n column: EncryptedColumn | EncryptedField\n table: EncryptedTable<EncryptedTableColumn>\n}\n\n/** Format for encrypted query/search term return values */\nexport type EncryptedReturnType =\n | 'eql'\n | 'composite-literal'\n | 'escaped-composite-literal'\n\nexport type SearchTerm = {\n value: JsPlaintext\n column: EncryptedColumn\n table: EncryptedTable<EncryptedTableColumn>\n returnType?: EncryptedReturnType\n}\n\n/** Encrypted search term result: EQL object or composite literal string */\nexport type EncryptedSearchTerm = Encrypted | string\n\n/** Result of encryptQuery (single or batch): EQL or composite literal string */\nexport type EncryptedQueryResult = Encrypted | string\n\n// ---------------------------------------------------------------------------\n// Model field types (encrypted vs decrypted views)\n// ---------------------------------------------------------------------------\n\nexport type EncryptedFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted ? K : never]: T[K]\n}\n\nexport type OtherFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted ? never : K]: T[K]\n}\n\nexport type DecryptedFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted\n ? K\n : never]: null extends T[K] ? string | null : string\n}\n\n/** Model with encrypted fields replaced by plaintext (decrypted) values */\nexport type Decrypted<T> = OtherFields<T> & DecryptedFields<T>\n\n/**\n * Maps a plaintext model type to its encrypted form using the table schema.\n *\n * Fields whose keys match columns defined in `S` become `Encrypted`;\n * all other fields retain their original types from `T`.\n *\n * When `S` is the widened `EncryptedTableColumn` (e.g. when a user passes an\n * explicit `<User>` type argument without specifying `S`), the type degrades\n * gracefully to `T` — preserving backward compatibility.\n *\n * @typeParam T - The plaintext model type (e.g. `{ id: string; email: string }`)\n * @typeParam S - The table schema column definition, inferred from the `table` argument\n *\n * @example\n * ```typescript\n * type User = { id: string; email: string }\n * // With a schema that defines `email`:\n * type Encrypted = EncryptedFromSchema<User, { email: EncryptedColumn }>\n * // => { id: string; email: Encrypted }\n * ```\n */\nexport type EncryptedFromSchema<T, S extends EncryptedTableColumn> = {\n [K in keyof T]: [K] extends [keyof S]\n ? [S[K & keyof S]] extends [EncryptedColumn | EncryptedField]\n ? null extends T[K]\n ? Encrypted | null\n : Encrypted\n : T[K]\n : T[K]\n}\n\n// ---------------------------------------------------------------------------\n// Bulk operations\n// ---------------------------------------------------------------------------\n\nexport type BulkEncryptPayload = Array<{\n id?: string\n plaintext: JsPlaintext\n}>\n\nexport type BulkEncryptedData = Array<{ id?: string; data: Encrypted }>\nexport type BulkDecryptPayload = Array<{ id?: string; data: Encrypted }>\nexport type BulkDecryptedData = Array<DecryptionResult<JsPlaintext>>\n\ntype DecryptionSuccess<T> = { error?: never; data: T; id?: string }\ntype DecryptionError<T> = { error: T; id?: string; data?: never }\n\n/**\n * Result type for individual items in bulk decrypt operations.\n * Uses `error`/`data` fields (not `failure`/`data`) since bulk operations\n * can have per-item failures.\n */\nexport type DecryptionResult<T> = DecryptionSuccess<T> | DecryptionError<T>\n\n// ---------------------------------------------------------------------------\n// Query types (for searchable encryption / encryptQuery)\n// ---------------------------------------------------------------------------\n\n/**\n * User-facing query type names for encrypting query values.\n *\n * - `'equality'`: Exact match. [Exact Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)\n * - `'freeTextSearch'`: Text search. [Match Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)\n * - `'orderAndRange'`: Comparison and range. [Range Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)\n * - `'steVecSelector'`: JSONPath selector (e.g. `'$.user.email'`)\n * - `'steVecTerm'`: Containment (e.g. `{ role: 'admin' }`)\n * - `'searchableJson'`: Auto-infers selector or term from plaintext type (recommended)\n */\nexport type QueryTypeName =\n | 'orderAndRange'\n | 'freeTextSearch'\n | 'equality'\n | 'steVecSelector'\n | 'steVecTerm'\n | 'searchableJson'\n\n/** @internal */\nexport type FfiIndexTypeName = 'ore' | 'match' | 'unique' | 'ste_vec'\n\nexport const queryTypes = {\n orderAndRange: 'orderAndRange',\n freeTextSearch: 'freeTextSearch',\n equality: 'equality',\n steVecSelector: 'steVecSelector',\n steVecTerm: 'steVecTerm',\n searchableJson: 'searchableJson',\n} as const satisfies Record<string, QueryTypeName>\n\n/** @internal */\nexport const queryTypeToFfi: Record<QueryTypeName, FfiIndexTypeName> = {\n orderAndRange: 'ore',\n freeTextSearch: 'match',\n equality: 'unique',\n steVecSelector: 'ste_vec',\n steVecTerm: 'ste_vec',\n searchableJson: 'ste_vec',\n}\n\n/** @internal */\nexport const queryTypeToQueryOp: Partial<Record<QueryTypeName, QueryOpName>> = {\n steVecSelector: 'ste_vec_selector',\n steVecTerm: 'ste_vec_term',\n}\n\n/** @internal */\nexport type QueryTermBase = {\n column: EncryptedColumn\n table: EncryptedTable<EncryptedTableColumn>\n queryType?: QueryTypeName\n returnType?: EncryptedReturnType\n}\n\nexport type EncryptQueryOptions = QueryTermBase\n\nexport type ScalarQueryTerm = QueryTermBase & {\n value: JsPlaintext\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC4NO,IAAM,aAAa;AAAA,EACxB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,gBAAgB;AAClB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types-public.ts","../src/types.ts"],"sourcesContent":["/**\n * Public type re-exports for `@cipherstash/stack/types`.\n *\n * This module exposes only the public types from the internal types module.\n * Internal helpers (`queryTypeToFfi`, `queryTypeToQueryOp`, `FfiIndexTypeName`,\n * `QueryTermBase`) are excluded.\n */\n\n// Core types\nexport type {\n Client,\n EncryptedValue,\n Encrypted,\n EncryptedQuery,\n} from '@/types'\n\n// Client configuration\nexport type {\n KeysetIdentifier,\n ClientConfig,\n EncryptionClientConfig,\n} from '@/types'\n\n// Encrypt / decrypt operation options and results\nexport type {\n EncryptOptions,\n EncryptedReturnType,\n SearchTerm,\n EncryptedSearchTerm,\n EncryptedQueryResult,\n} from '@/types'\n\n// Model field types\nexport type {\n EncryptedFields,\n OtherFields,\n DecryptedFields,\n Decrypted,\n EncryptedFromSchema,\n} from '@/types'\n\n// Bulk operations\nexport type {\n BulkEncryptPayload,\n BulkEncryptedData,\n BulkDecryptPayload,\n BulkDecryptedData,\n DecryptionResult,\n} from '@/types'\n\n// Query types (public only)\nexport type {\n QueryTypeName,\n EncryptQueryOptions,\n ScalarQueryTerm,\n} from '@/types'\n\n// Runtime values\nexport { queryTypes } from '@/types'\n","import type {\n EncryptedColumn,\n EncryptedField,\n EncryptedTable,\n EncryptedTableColumn,\n // Imported type-only for the TSDoc {@link} references in the comments below.\n encryptedColumn,\n encryptedField,\n} from '@/schema'\nimport type {\n Encrypted as CipherStashEncrypted,\n EncryptedQuery as CipherStashEncryptedQuery,\n JsPlaintext,\n QueryOpName,\n newClient,\n} from '@cipherstash/protect-ffi'\n\n// ---------------------------------------------------------------------------\n// Branded type utilities\n// ---------------------------------------------------------------------------\n\n/** Brand symbol for nominal typing */\ndeclare const __brand: unique symbol\n\n/** Creates a branded type that is structurally incompatible with the base type */\ntype Brand<T, B extends string> = T & { readonly [__brand]: B }\n\n// ---------------------------------------------------------------------------\n// Core types\n// ---------------------------------------------------------------------------\n\nexport type Client = Awaited<ReturnType<typeof newClient>> | undefined\n\n/** A branded type representing encrypted data. Cannot be accidentally used as plaintext. */\nexport type EncryptedValue = Brand<CipherStashEncrypted, 'encrypted'>\n\n/** Structural type representing encrypted data stored in the database. Always\n * carries a ciphertext. See also `EncryptedValue` for branded nominal typing,\n * and {@link EncryptedQuery} for the search-term shape returned by\n * `encryptQuery`. */\nexport type Encrypted = CipherStashEncrypted\n\n/** Structural type representing an encrypted query term (search needle)\n * returned by `encryptQuery` / `encryptQueryBulk` for scalar\n * (`unique` / `match` / `ore`) lookups and `ste_vec_selector` JSON path\n * queries. Carries no ciphertext — matched against stored values, never\n * decrypted. JSON containment queries (`ste_vec_term`) return a\n * storage-shaped {@link Encrypted} payload instead. */\nexport type EncryptedQuery = CipherStashEncryptedQuery\n\n// ---------------------------------------------------------------------------\n// Client configuration\n// ---------------------------------------------------------------------------\n\nexport type KeysetIdentifier = { name: string } | { id: string }\n\nexport type ClientConfig = {\n /**\n * The CipherStash workspace CRN (Cloud Resource Name).\n * Format: `crn:<region>.aws:<workspace-id>`.\n * Can also be set via the `CS_WORKSPACE_CRN` environment variable.\n */\n workspaceCrn?: string\n\n /**\n * The API access key used for authenticating with the CipherStash API.\n * Can also be set via the `CS_CLIENT_ACCESS_KEY` environment variable.\n * Obtain this from the CipherStash dashboard after creating a workspace.\n */\n accessKey?: string\n\n /**\n * The client identifier used to authenticate with CipherStash services.\n * Can also be set via the `CS_CLIENT_ID` environment variable.\n * Generated during workspace onboarding in the CipherStash dashboard.\n */\n clientId?: string\n\n /**\n * The client key material used in combination with ZeroKMS for encryption operations.\n * Can also be set via the `CS_CLIENT_KEY` environment variable.\n * Generated during workspace onboarding in the CipherStash dashboard.\n */\n clientKey?: string\n\n /**\n * An optional keyset identifier for multi-tenant encryption.\n * Each keyset provides cryptographic isolation, giving each tenant its own keyspace.\n * Specify by name (`{ name: \"tenant-a\" }`) or UUID (`{ id: \"...\" }`).\n * Keysets are created and managed in the CipherStash dashboard.\n */\n keyset?: KeysetIdentifier\n}\n\ntype AtLeastOneCsTable<T> = [T, ...T[]]\n\nexport type EncryptionClientConfig = {\n schemas: AtLeastOneCsTable<EncryptedTable<EncryptedTableColumn>>\n config?: ClientConfig\n}\n\n// ---------------------------------------------------------------------------\n// Encrypt / decrypt operation options and results\n// ---------------------------------------------------------------------------\n\n/**\n * Options for single-value encrypt operations.\n * Use a column from your table schema (from {@link encryptedColumn}) or a nested\n * field (from {@link encryptedField}) as the target for encryption.\n */\nexport type EncryptOptions = {\n /** The column or nested field to encrypt into. From {@link EncryptedColumn} or {@link EncryptedField}. */\n column: EncryptedColumn | EncryptedField\n table: EncryptedTable<EncryptedTableColumn>\n}\n\n/** Format for encrypted query/search term return values */\nexport type EncryptedReturnType =\n | 'eql'\n | 'composite-literal'\n | 'escaped-composite-literal'\n\nexport type SearchTerm = {\n value: JsPlaintext\n column: EncryptedColumn\n table: EncryptedTable<EncryptedTableColumn>\n returnType?: EncryptedReturnType\n}\n\n/** Encrypted search term result. `eql` return type yields either a storage\n * payload (`Encrypted`, for `ste_vec_term`) or a query-only term\n * (`EncryptedQuery`, for scalar lookups and `ste_vec_selector`); the\n * `composite-literal` return types yield a string. */\nexport type EncryptedSearchTerm = Encrypted | EncryptedQuery | string\n\n/** Result of encryptQuery (single or batch). `eql` return type yields either a\n * storage payload (`Encrypted`) or a query-only term (`EncryptedQuery`); the\n * `composite-literal` return types yield a string. */\n// null elements appear in the batch path when a term has a null/undefined\n// value — the operation preserves position so callers can correlate results\n// with their input array.\nexport type EncryptedQueryResult =\n | Encrypted\n | EncryptedQuery\n | string\n | null\n\n// ---------------------------------------------------------------------------\n// Model field types (encrypted vs decrypted views)\n// ---------------------------------------------------------------------------\n\nexport type EncryptedFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted ? K : never]: T[K]\n}\n\nexport type OtherFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted ? never : K]: T[K]\n}\n\nexport type DecryptedFields<T> = {\n [K in keyof T as NonNullable<T[K]> extends Encrypted\n ? K\n : never]: null extends T[K] ? string | null : string\n}\n\n/** Model with encrypted fields replaced by plaintext (decrypted) values */\nexport type Decrypted<T> = OtherFields<T> & DecryptedFields<T>\n\n/**\n * Maps a plaintext model type to its encrypted form using the table schema.\n *\n * Fields whose keys match columns defined in `S` become `Encrypted`;\n * all other fields retain their original types from `T`.\n *\n * When `S` is the widened `EncryptedTableColumn` (e.g. when a user passes an\n * explicit `<User>` type argument without specifying `S`), the type degrades\n * gracefully to `T` — preserving backward compatibility.\n *\n * @typeParam T - The plaintext model type (e.g. `{ id: string; email: string }`)\n * @typeParam S - The table schema column definition, inferred from the `table` argument\n *\n * @example\n * ```typescript\n * type User = { id: string; email: string }\n * // With a schema that defines `email`:\n * type Encrypted = EncryptedFromSchema<User, { email: EncryptedColumn }>\n * // => { id: string; email: Encrypted }\n * ```\n */\nexport type EncryptedFromSchema<T, S extends EncryptedTableColumn> = {\n [K in keyof T]: [K] extends [keyof S]\n ? [S[K & keyof S]] extends [EncryptedColumn | EncryptedField]\n ? null extends T[K]\n ? Encrypted | null\n : Encrypted\n : T[K]\n : T[K]\n}\n\n// ---------------------------------------------------------------------------\n// Bulk operations\n// ---------------------------------------------------------------------------\n\n// Bulk payloads admit null elements — bulk operations pass them through\n// untouched (encrypt(null) -> null, decrypt(null) -> null) so callers can\n// process mixed nullable arrays without filtering ahead of time. The\n// runtime guards in the operation classes preserve the null in the\n// position-stable output.\nexport type BulkEncryptPayload = Array<{\n id?: string\n plaintext: JsPlaintext | null\n}>\n\nexport type BulkEncryptedData = Array<{ id?: string; data: Encrypted | null }>\nexport type BulkDecryptPayload = Array<{ id?: string; data: Encrypted | null }>\nexport type BulkDecryptedData = Array<DecryptionResult<JsPlaintext | null>>\n\ntype DecryptionSuccess<T> = { error?: never; data: T; id?: string }\ntype DecryptionError<T> = { error: T; id?: string; data?: never }\n\n/**\n * Result type for individual items in bulk decrypt operations.\n * Uses `error`/`data` fields (not `failure`/`data`) since bulk operations\n * can have per-item failures.\n */\nexport type DecryptionResult<T> = DecryptionSuccess<T> | DecryptionError<T>\n\n// ---------------------------------------------------------------------------\n// Query types (for searchable encryption / encryptQuery)\n// ---------------------------------------------------------------------------\n\n/**\n * User-facing query type names for encrypting query values.\n *\n * - `'equality'`: Exact match. [Exact Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)\n * - `'freeTextSearch'`: Text search. [Match Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)\n * - `'orderAndRange'`: Comparison and range. [Range Queries](https://cipherstash.com/docs/stack/cipherstash/encryption/searchable-encryption)\n * - `'steVecSelector'`: JSONPath selector (e.g. `'$.user.email'`)\n * - `'steVecTerm'`: Containment (e.g. `{ role: 'admin' }`)\n * - `'searchableJson'`: Auto-infers selector or term from plaintext type (recommended)\n */\nexport type QueryTypeName =\n | 'orderAndRange'\n | 'freeTextSearch'\n | 'equality'\n | 'steVecSelector'\n | 'steVecTerm'\n | 'searchableJson'\n\n/** @internal */\nexport type FfiIndexTypeName = 'ore' | 'match' | 'unique' | 'ste_vec'\n\nexport const queryTypes = {\n orderAndRange: 'orderAndRange',\n freeTextSearch: 'freeTextSearch',\n equality: 'equality',\n steVecSelector: 'steVecSelector',\n steVecTerm: 'steVecTerm',\n searchableJson: 'searchableJson',\n} as const satisfies Record<string, QueryTypeName>\n\n/** @internal */\nexport const queryTypeToFfi: Record<QueryTypeName, FfiIndexTypeName> = {\n orderAndRange: 'ore',\n freeTextSearch: 'match',\n equality: 'unique',\n steVecSelector: 'ste_vec',\n steVecTerm: 'ste_vec',\n searchableJson: 'ste_vec',\n}\n\n/** @internal */\nexport const queryTypeToQueryOp: Partial<Record<QueryTypeName, QueryOpName>> = {\n steVecSelector: 'ste_vec_selector',\n steVecTerm: 'ste_vec_term',\n}\n\n/** @internal */\nexport type QueryTermBase = {\n column: EncryptedColumn\n table: EncryptedTable<EncryptedTableColumn>\n queryType?: QueryTypeName\n returnType?: EncryptedReturnType\n}\n\nexport type EncryptQueryOptions = QueryTermBase\n\nexport type ScalarQueryTerm = QueryTermBase & {\n value: JsPlaintext\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC4PO,IAAM,aAAa;AAAA,EACxB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,gBAAgB;AAClB;","names":[]}
|
package/dist/types-public.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { j as BulkDecryptPayload, B as BulkDecryptedData, l as BulkEncryptPayload, k as BulkEncryptedData, i as Client, G as ClientConfig, D as Decrypted, H as DecryptedFields, J as DecryptionResult, m as EncryptOptions, o as EncryptQueryOptions, E as Encrypted, L as EncryptedFields, h as EncryptedQueryResult, p as EncryptedReturnType,
|
|
1
|
+
export { j as BulkDecryptPayload, B as BulkDecryptedData, l as BulkEncryptPayload, k as BulkEncryptedData, i as Client, G as ClientConfig, D as Decrypted, H as DecryptedFields, J as DecryptionResult, m as EncryptOptions, o as EncryptQueryOptions, E as Encrypted, L as EncryptedFields, r as EncryptedFromSchema, N as EncryptedQuery, h as EncryptedQueryResult, p as EncryptedReturnType, P as EncryptedSearchTerm, g as EncryptedValue, s as EncryptionClientConfig, K as KeysetIdentifier, R as OtherFields, Q as QueryTypeName, S as ScalarQueryTerm, V as SearchTerm, W as queryTypes } from './types-public-BTxqjmtv.cjs';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import '@cipherstash/protect-ffi';
|
package/dist/types-public.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { j as BulkDecryptPayload, B as BulkDecryptedData, l as BulkEncryptPayload, k as BulkEncryptedData, i as Client, G as ClientConfig, D as Decrypted, H as DecryptedFields, J as DecryptionResult, m as EncryptOptions, o as EncryptQueryOptions, E as Encrypted, L as EncryptedFields, h as EncryptedQueryResult, p as EncryptedReturnType,
|
|
1
|
+
export { j as BulkDecryptPayload, B as BulkDecryptedData, l as BulkEncryptPayload, k as BulkEncryptedData, i as Client, G as ClientConfig, D as Decrypted, H as DecryptedFields, J as DecryptionResult, m as EncryptOptions, o as EncryptQueryOptions, E as Encrypted, L as EncryptedFields, r as EncryptedFromSchema, N as EncryptedQuery, h as EncryptedQueryResult, p as EncryptedReturnType, P as EncryptedSearchTerm, g as EncryptedValue, s as EncryptionClientConfig, K as KeysetIdentifier, R as OtherFields, Q as QueryTypeName, S as ScalarQueryTerm, V as SearchTerm, W as queryTypes } from './types-public-BTxqjmtv.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import '@cipherstash/protect-ffi';
|
package/dist/types-public.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cipherstash/stack",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "CipherStash Stack for TypeScript and JavaScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"encrypted",
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
"stack"
|
|
12
12
|
],
|
|
13
13
|
"bugs": {
|
|
14
|
-
"url": "https://github.com/cipherstash/
|
|
14
|
+
"url": "https://github.com/cipherstash/stack/issues"
|
|
15
15
|
},
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/cipherstash/
|
|
18
|
+
"url": "git+https://github.com/cipherstash/stack.git",
|
|
19
19
|
"directory": "packages/stack"
|
|
20
20
|
},
|
|
21
21
|
"license": "MIT",
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
"./package.json": "./package.json"
|
|
180
180
|
},
|
|
181
181
|
"devDependencies": {
|
|
182
|
-
"@clack/prompts": "^
|
|
182
|
+
"@clack/prompts": "^1.4.0",
|
|
183
183
|
"@supabase/supabase-js": "^2.105.4",
|
|
184
184
|
"@types/uuid": "^11.0.0",
|
|
185
185
|
"dotenv": "17.4.2",
|
|
@@ -187,20 +187,20 @@
|
|
|
187
187
|
"execa": "^9.5.2",
|
|
188
188
|
"json-schema-to-typescript": "^15.0.2",
|
|
189
189
|
"postgres": "^3.4.8",
|
|
190
|
-
"tsup": "8.
|
|
191
|
-
"tsx": "4.
|
|
192
|
-
"typescript": "5.
|
|
193
|
-
"vitest": "3.
|
|
190
|
+
"tsup": "8.5.1",
|
|
191
|
+
"tsx": "4.22.1",
|
|
192
|
+
"typescript": "5.9.3",
|
|
193
|
+
"vitest": "3.2.4"
|
|
194
194
|
},
|
|
195
195
|
"publishConfig": {
|
|
196
196
|
"access": "public"
|
|
197
197
|
},
|
|
198
198
|
"dependencies": {
|
|
199
199
|
"@byteslice/result": "0.2.0",
|
|
200
|
-
"@cipherstash/protect-ffi": "0.
|
|
201
|
-
"evlog": "1.
|
|
200
|
+
"@cipherstash/protect-ffi": "0.23.0",
|
|
201
|
+
"evlog": "1.11.0",
|
|
202
202
|
"uuid": "14.0.0",
|
|
203
|
-
"zod": "3.
|
|
203
|
+
"zod": "3.25.76"
|
|
204
204
|
},
|
|
205
205
|
"peerDependencies": {
|
|
206
206
|
"@supabase/supabase-js": ">=2",
|
|
@@ -215,7 +215,7 @@
|
|
|
215
215
|
}
|
|
216
216
|
},
|
|
217
217
|
"engines": {
|
|
218
|
-
"node": ">=
|
|
218
|
+
"node": ">=22"
|
|
219
219
|
},
|
|
220
220
|
"scripts": {
|
|
221
221
|
"build": "tsup",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/encryption/helpers/index.ts"],"sourcesContent":["import type { Encrypted, EncryptedQueryResult, KeysetIdentifier } from '@/types'\nimport type {\n Encrypted as CipherStashEncrypted,\n KeysetIdentifier as KeysetIdentifierFfi,\n} from '@cipherstash/protect-ffi'\n\nexport type EncryptedPgComposite = {\n data: Encrypted\n}\n\n/**\n * Helper function to transform an encrypted payload into a PostgreSQL composite type.\n * Use this when inserting data via Supabase or similar clients.\n */\nexport function encryptedToPgComposite(obj: Encrypted): EncryptedPgComposite {\n return {\n data: obj,\n }\n}\n\n/**\n * Helper function to transform an encrypted payload into a PostgreSQL composite literal string.\n * Use this when querying with `.eq()` or similar equality operations in Supabase.\n *\n * @example\n * ```typescript\n * const literal = encryptedToCompositeLiteral(encrypted)\n * await supabase.from('table').select().eq('column', literal)\n * ```\n */\nexport function encryptedToCompositeLiteral(obj: CipherStashEncrypted): string {\n return `(${JSON.stringify(JSON.stringify(obj))})`\n}\n\n/**\n * Helper function to transform an encrypted payload into an escaped PostgreSQL composite literal string.\n * Use this when you need the composite literal format to be escaped as a string value.\n *\n * @example\n * ```typescript\n * const escapedLiteral = encryptedToEscapedCompositeLiteral(encrypted)\n * ```\n */\nexport function encryptedToEscapedCompositeLiteral(\n obj: CipherStashEncrypted,\n): string {\n return JSON.stringify(encryptedToCompositeLiteral(obj))\n}\n\n/**\n * Format an encrypted result based on the requested return type.\n *\n * - `'composite-literal'` → PostgreSQL composite literal string `(\"json\")`\n * - `'escaped-composite-literal'` → escaped variant `\"(\\\"json\\\")\"`\n * - default (`'eql'` or omitted) → raw encrypted object\n */\nexport function formatEncryptedResult(\n encrypted: CipherStashEncrypted,\n returnType?: string,\n): EncryptedQueryResult {\n if (returnType === 'composite-literal') {\n return encryptedToCompositeLiteral(encrypted)\n }\n if (returnType === 'escaped-composite-literal') {\n return encryptedToEscapedCompositeLiteral(encrypted)\n }\n return encrypted\n}\n\n/**\n * Helper function to transform a model's encrypted fields into PostgreSQL composite types\n */\nexport function modelToEncryptedPgComposites<T extends Record<string, unknown>>(\n model: T,\n): T {\n const result: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(model)) {\n if (isEncryptedPayload(value)) {\n result[key] = encryptedToPgComposite(value)\n } else {\n result[key] = value\n }\n }\n\n return result as T\n}\n\n/**\n * Helper function to transform multiple models' encrypted fields into PostgreSQL composite types\n */\nexport function bulkModelsToEncryptedPgComposites<\n T extends Record<string, unknown>,\n>(models: T[]): T[] {\n return models.map((model) => modelToEncryptedPgComposites(model))\n}\n\nexport function toFfiKeysetIdentifier(\n keyset: KeysetIdentifier | undefined,\n): KeysetIdentifierFfi | undefined {\n if (!keyset) return undefined\n\n if ('name' in keyset) {\n return { Name: keyset.name }\n }\n\n return { Uuid: keyset.id }\n}\n\n/**\n * Helper function to check if a value is an encrypted payload\n */\nexport function isEncryptedPayload(value: unknown): value is Encrypted {\n if (value === null) return false\n if (typeof value !== 'object') return false\n\n const obj = value as Record<string, unknown>\n\n // Must have version field (number)\n if (!('v' in obj) || typeof obj.v !== 'number') return false\n\n // Must have index field (object)\n if (!('i' in obj) || typeof obj.i !== 'object') return false\n\n // Must have either ciphertext (c) or searchable vector (sv)\n if (!('c' in obj) && !('sv' in obj)) return false\n\n return true\n}\n\nexport {\n toJsonPath,\n buildNestedObject,\n parseJsonbPath,\n} from './jsonb'\n"],"mappings":";AAcO,SAAS,uBAAuB,KAAsC;AAC3E,SAAO;AAAA,IACL,MAAM;AAAA,EACR;AACF;AAYO,SAAS,4BAA4B,KAAmC;AAC7E,SAAO,IAAI,KAAK,UAAU,KAAK,UAAU,GAAG,CAAC,CAAC;AAChD;AAWO,SAAS,mCACd,KACQ;AACR,SAAO,KAAK,UAAU,4BAA4B,GAAG,CAAC;AACxD;AASO,SAAS,sBACd,WACA,YACsB;AACtB,MAAI,eAAe,qBAAqB;AACtC,WAAO,4BAA4B,SAAS;AAAA,EAC9C;AACA,MAAI,eAAe,6BAA6B;AAC9C,WAAO,mCAAmC,SAAS;AAAA,EACrD;AACA,SAAO;AACT;AAKO,SAAS,6BACd,OACG;AACH,QAAM,SAAkC,CAAC;AAEzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,mBAAmB,KAAK,GAAG;AAC7B,aAAO,GAAG,IAAI,uBAAuB,KAAK;AAAA,IAC5C,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,kCAEd,QAAkB;AAClB,SAAO,OAAO,IAAI,CAAC,UAAU,6BAA6B,KAAK,CAAC;AAClE;AAEO,SAAS,sBACd,QACiC;AACjC,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI,UAAU,QAAQ;AACpB,WAAO,EAAE,MAAM,OAAO,KAAK;AAAA,EAC7B;AAEA,SAAO,EAAE,MAAM,OAAO,GAAG;AAC3B;AAKO,SAAS,mBAAmB,OAAoC;AACrE,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,OAAO,UAAU,SAAU,QAAO;AAEtC,QAAM,MAAM;AAGZ,MAAI,EAAE,OAAO,QAAQ,OAAO,IAAI,MAAM,SAAU,QAAO;AAGvD,MAAI,EAAE,OAAO,QAAQ,OAAO,IAAI,MAAM,SAAU,QAAO;AAGvD,MAAI,EAAE,OAAO,QAAQ,EAAE,QAAQ,KAAM,QAAO;AAE5C,SAAO;AACT;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/evlog@1.9.0/node_modules/evlog/src/utils.ts","../../../node_modules/.pnpm/evlog@1.9.0/node_modules/evlog/src/logger.ts","../src/utils/logger/index.ts"],"sourcesContent":["import type { EnvironmentContext, LogLevel } from './types'\n\nexport function formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${Math.round(ms)}ms`\n }\n return `${(ms / 1000).toFixed(2)}s`\n}\n\nexport function isServer(): boolean {\n return typeof window === 'undefined'\n}\n\nexport function isClient(): boolean {\n return typeof window !== 'undefined'\n}\n\nexport function isDev(): boolean {\n if (typeof process !== 'undefined') {\n return process.env.NODE_ENV !== 'production'\n }\n if (typeof window !== 'undefined') {\n return true\n }\n return false\n}\n\nexport function detectEnvironment(): Partial<EnvironmentContext> {\n const env = typeof process !== 'undefined' ? process.env : {}\n const defaultEnvironment = isDev() ? 'development' : 'production'\n\n return {\n environment: env.NODE_ENV || defaultEnvironment,\n service: env.SERVICE_NAME || 'app',\n version: env.APP_VERSION,\n commitHash: env.COMMIT_SHA\n || env.GITHUB_SHA\n || env.VERCEL_GIT_COMMIT_SHA\n || env.CF_PAGES_COMMIT_SHA,\n region: env.VERCEL_REGION\n || env.AWS_REGION\n || env.FLY_REGION\n || env.CF_REGION,\n }\n}\n\nexport function getConsoleMethod(level: LogLevel): LogLevel {\n return level\n}\n\nexport const colors = {\n reset: '\\x1B[0m',\n bold: '\\x1B[1m',\n dim: '\\x1B[2m',\n red: '\\x1B[31m',\n green: '\\x1B[32m',\n yellow: '\\x1B[33m',\n blue: '\\x1B[34m',\n magenta: '\\x1B[35m',\n cyan: '\\x1B[36m',\n white: '\\x1B[37m',\n gray: '\\x1B[90m',\n} as const\n\nexport function getLevelColor(level: string): string {\n switch (level) {\n case 'error':\n return colors.red\n case 'warn':\n return colors.yellow\n case 'info':\n return colors.cyan\n case 'debug':\n return colors.gray\n default:\n return colors.white\n }\n}\n\n/** Headers that should never be passed to hooks for security */\nexport const SENSITIVE_HEADERS = [\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'x-auth-token',\n 'proxy-authorization',\n]\n\nexport function filterSafeHeaders(headers: Record<string, string>): Record<string, string> {\n const safeHeaders: Record<string, string> = {}\n\n for (const [key, value] of Object.entries(headers)) {\n if (!SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n safeHeaders[key] = value\n }\n }\n\n return safeHeaders\n}\n\n/**\n * Match a path against a glob pattern.\n * Supports * (any chars except /) and ** (any chars including /).\n */\nexport function matchesPattern(path: string, pattern: string): boolean {\n const regexPattern = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&') // Escape special regex chars except * and ?\n .replace(/\\*\\*/g, '{{GLOBSTAR}}') // Temp placeholder for **\n .replace(/\\*/g, '[^/]*') // * matches anything except /\n .replace(/{{GLOBSTAR}}/g, '.*') // ** matches anything including /\n .replace(/\\?/g, '[^/]') // ? matches single char except /\n\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(path)\n}\n","import type { DrainContext, EnvironmentContext, FieldContext, Log, LogLevel, LoggerConfig, RequestLogger, RequestLoggerOptions, SamplingConfig, TailSamplingContext, WideEvent } from './types'\nimport { colors, detectEnvironment, formatDuration, getConsoleMethod, getLevelColor, isDev, matchesPattern } from './utils'\n\nfunction isPlainObject(val: unknown): val is Record<string, unknown> {\n return val !== null && typeof val === 'object' && !Array.isArray(val)\n}\n\nfunction deepDefaults(base: Record<string, unknown>, defaults: Record<string, unknown>): Record<string, unknown> {\n const result = { ...base }\n for (const key in defaults) {\n const baseVal = result[key]\n const defaultVal = defaults[key]\n if (baseVal === undefined || baseVal === null) {\n result[key] = defaultVal\n } else if (isPlainObject(baseVal) && isPlainObject(defaultVal)) {\n result[key] = deepDefaults(baseVal, defaultVal)\n }\n }\n return result\n}\n\nlet globalEnv: EnvironmentContext = {\n service: 'app',\n environment: 'development',\n}\n\nlet globalPretty = isDev()\nlet globalSampling: SamplingConfig = {}\nlet globalStringify = true\nlet globalDrain: ((ctx: DrainContext) => void | Promise<void>) | undefined\nlet globalEnabled = true\n\n/**\n * Initialize the logger with configuration.\n * Call this once at application startup.\n */\nexport function initLogger(config: LoggerConfig = {}): void {\n globalEnabled = config.enabled ?? true\n const detected = detectEnvironment()\n\n globalEnv = {\n service: config.env?.service ?? detected.service ?? 'app',\n environment: config.env?.environment ?? detected.environment ?? 'development',\n version: config.env?.version ?? detected.version,\n commitHash: config.env?.commitHash ?? detected.commitHash,\n region: config.env?.region ?? detected.region,\n }\n\n globalPretty = config.pretty ?? isDev()\n globalSampling = config.sampling ?? {}\n globalStringify = config.stringify ?? true\n globalDrain = config.drain\n}\n\n/**\n * Check if logging is globally enabled.\n */\nexport function isEnabled(): boolean {\n return globalEnabled\n}\n\n/**\n * Determine if a log at the given level should be emitted based on sampling config.\n * Error level defaults to 100% (always logged) unless explicitly configured otherwise.\n */\nfunction shouldSample(level: LogLevel): boolean {\n const { rates } = globalSampling\n if (!rates) {\n return true // No sampling configured, log everything\n }\n\n // Error defaults to 100% unless explicitly set\n const percentage = level === 'error' && rates.error === undefined\n ? 100\n : rates[level] ?? 100\n\n // 0% = never log, 100% = always log\n if (percentage <= 0) return false\n if (percentage >= 100) return true\n\n return Math.random() * 100 < percentage\n}\n\n/**\n * Evaluate tail sampling conditions to determine if a log should be force-kept.\n * Returns true if ANY condition matches (OR logic).\n */\nexport function shouldKeep(ctx: TailSamplingContext): boolean {\n const { keep } = globalSampling\n if (!keep?.length) return false\n\n return keep.some((condition) => {\n if (condition.status !== undefined && ctx.status !== undefined && ctx.status >= condition.status) {\n return true\n }\n if (condition.duration !== undefined && ctx.duration !== undefined && ctx.duration >= condition.duration) {\n return true\n }\n if (condition.path && ctx.path && matchesPattern(ctx.path, condition.path)) {\n return true\n }\n return false\n })\n}\n\nfunction emitWideEvent(level: LogLevel, event: Record<string, unknown>, skipSamplingCheck = false): WideEvent | null {\n if (!globalEnabled) return null\n\n if (!skipSamplingCheck && !shouldSample(level)) {\n return null\n }\n\n const formatted: WideEvent = {\n timestamp: new Date().toISOString(),\n level,\n ...globalEnv,\n ...event,\n }\n\n if (globalPretty) {\n prettyPrintWideEvent(formatted)\n } else if (globalStringify) {\n console[getConsoleMethod(level)](JSON.stringify(formatted))\n } else {\n console[getConsoleMethod(level)](formatted)\n }\n\n if (globalDrain) {\n Promise.resolve(globalDrain({ event: formatted })).catch((err) => {\n console.error('[evlog] drain failed:', err)\n })\n }\n\n return formatted\n}\n\nfunction emitTaggedLog(level: LogLevel, tag: string, message: string): void {\n if (!globalEnabled) return\n\n if (globalPretty) {\n if (!shouldSample(level)) {\n return\n }\n const color = getLevelColor(level)\n const timestamp = new Date().toISOString().slice(11, 23)\n console.log(`${colors.dim}${timestamp}${colors.reset} ${color}[${tag}]${colors.reset} ${message}`)\n return\n }\n emitWideEvent(level, { tag, message })\n}\n\nfunction formatValue(value: unknown): string {\n if (value === null || value === undefined) {\n return String(value)\n }\n if (typeof value === 'object') {\n // Flatten object to key=value pairs\n const pairs: string[] = []\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (v !== undefined && v !== null) {\n if (typeof v === 'object') {\n // For nested objects, show as JSON\n pairs.push(`${k}=${JSON.stringify(v)}`)\n } else {\n pairs.push(`${k}=${v}`)\n }\n }\n }\n return pairs.join(' ')\n }\n return String(value)\n}\n\nfunction prettyPrintWideEvent(event: Record<string, unknown>): void {\n const { timestamp, level, service, environment, version, ...rest } = event\n const levelColor = getLevelColor(level as string)\n const ts = (timestamp as string).slice(11, 23)\n\n let header = `${colors.dim}${ts}${colors.reset} ${levelColor}${(level as string).toUpperCase()}${colors.reset}`\n header += ` ${colors.cyan}[${service}]${colors.reset}`\n\n if (rest.method && rest.path) {\n header += ` ${rest.method} ${rest.path}`\n delete rest.method\n delete rest.path\n }\n\n if (rest.status) {\n const statusColor = (rest.status as number) >= 400 ? colors.red : colors.green\n header += ` ${statusColor}${rest.status}${colors.reset}`\n delete rest.status\n }\n\n if (rest.duration) {\n header += ` ${colors.dim}in ${rest.duration}${colors.reset}`\n delete rest.duration\n }\n\n console.log(header)\n\n const entries = Object.entries(rest).filter(([_, v]) => v !== undefined)\n const lastIndex = entries.length - 1\n\n entries.forEach(([key, value], index) => {\n const isLast = index === lastIndex\n const prefix = isLast ? '└─' : '├─'\n const formatted = formatValue(value)\n console.log(` ${colors.dim}${prefix}${colors.reset} ${colors.cyan}${key}:${colors.reset} ${formatted}`)\n })\n}\n\nfunction createLogMethod(level: LogLevel) {\n return function logMethod(tagOrEvent: string | Record<string, unknown>, message?: string): void {\n if (typeof tagOrEvent === 'string' && message !== undefined) {\n emitTaggedLog(level, tagOrEvent, message)\n } else if (typeof tagOrEvent === 'object') {\n emitWideEvent(level, tagOrEvent)\n } else {\n emitTaggedLog(level, 'log', String(tagOrEvent))\n }\n }\n}\n\n/**\n * Simple logging API - as easy as console.log\n *\n * @example\n * ```ts\n * log.info('auth', 'User logged in')\n * log.error({ action: 'payment', error: 'failed' })\n * ```\n */\nconst _log: Log = {\n info: createLogMethod('info'),\n error: createLogMethod('error'),\n warn: createLogMethod('warn'),\n debug: createLogMethod('debug'),\n}\n\nexport { _log as log }\n\nconst noopLogger: RequestLogger = {\n set() {},\n error() {},\n info() {},\n warn() {},\n emit() {\n return null\n },\n getContext() {\n return {}\n },\n}\n\n/**\n * Create a request-scoped logger for building wide events.\n *\n * @example\n * ```ts\n * const log = createRequestLogger({ method: 'POST', path: '/checkout' })\n * log.set({ user: { id: '123' } })\n * log.set({ cart: { items: 3 } })\n * log.emit()\n * ```\n */\nexport function createRequestLogger<T extends object = Record<string, unknown>>(options: RequestLoggerOptions = {}): RequestLogger<T> {\n if (!globalEnabled) return noopLogger as RequestLogger<T>\n\n const startTime = Date.now()\n let context: Record<string, unknown> = {\n method: options.method,\n path: options.path,\n requestId: options.requestId,\n }\n let hasError = false\n let hasWarn = false\n\n function addRequestLog(level: 'info' | 'warn', message: string): void {\n const entry = {\n level,\n message,\n timestamp: new Date().toISOString(),\n }\n\n const requestLogs = Array.isArray(context.requestLogs)\n ? [...context.requestLogs, entry]\n : [entry]\n\n context = {\n ...context,\n requestLogs,\n }\n }\n\n return {\n set(data: FieldContext<T>): void {\n context = deepDefaults(data as Record<string, unknown>, context) as Record<string, unknown>\n },\n\n error(error: Error | string, errorContext?: FieldContext<T>): void {\n hasError = true\n const err = typeof error === 'string' ? new Error(error) : error\n\n const errorData = {\n ...(errorContext as Record<string, unknown>),\n error: {\n name: err.name,\n message: err.message,\n stack: err.stack,\n ...('status' in err && { status: (err as Record<string, unknown>).status }),\n ...('statusText' in err && { statusText: (err as Record<string, unknown>).statusText }),\n ...('statusCode' in err && { statusCode: (err as Record<string, unknown>).statusCode }),\n ...('statusMessage' in err && { statusMessage: (err as Record<string, unknown>).statusMessage }),\n ...('data' in err && { data: (err as Record<string, unknown>).data }),\n ...('cause' in err && { cause: (err as unknown as Record<string, unknown>).cause }),\n },\n }\n context = deepDefaults(errorData, context) as Record<string, unknown>\n },\n\n info(message: string, infoContext?: FieldContext<T>): void {\n addRequestLog('info', message)\n if (infoContext) {\n const { requestLogs: _, ...rest } = infoContext as Record<string, unknown>\n context = deepDefaults(rest, context) as Record<string, unknown>\n }\n },\n\n warn(message: string, warnContext?: FieldContext<T>): void {\n hasWarn = true\n addRequestLog('warn', message)\n if (warnContext) {\n const { requestLogs: _, ...rest } = warnContext as Record<string, unknown>\n context = deepDefaults(rest, context) as Record<string, unknown>\n }\n },\n\n emit(overrides?: FieldContext<T> & { _forceKeep?: boolean }): WideEvent | null {\n const durationMs = Date.now() - startTime\n const duration = formatDuration(durationMs)\n const level: LogLevel = hasError ? 'error' : hasWarn ? 'warn' : 'info'\n\n // Extract _forceKeep from overrides (set by evlog:emit:keep hook)\n const { _forceKeep, ...restOverrides } = (overrides ?? {}) as Record<string, unknown> & { _forceKeep?: boolean }\n\n // Build tail sampling context\n const tailCtx: TailSamplingContext = {\n status: (context.status ?? restOverrides.status) as number | undefined,\n duration: durationMs,\n path: context.path as string | undefined,\n method: context.method as string | undefined,\n context: { ...context, ...restOverrides },\n }\n\n // Tail sampling: force keep if hook or built-in conditions match\n const forceKeep = _forceKeep || shouldKeep(tailCtx)\n\n // Apply head sampling only if not force-kept\n if (!forceKeep && !shouldSample(level)) {\n return null\n }\n\n return emitWideEvent(level, {\n ...context,\n ...restOverrides,\n duration,\n }, true)\n },\n\n getContext(): FieldContext<T> & Record<string, unknown> {\n return { ...context }\n },\n }\n}\n\n/**\n * Get the current environment context.\n */\nexport function getEnvironment(): EnvironmentContext {\n return { ...globalEnv }\n}\n","import { createRequestLogger, initLogger } from 'evlog'\n\n/**\n * Log level for the Stack logger.\n *\n * Configured via the `STASH_STACK_LOG` environment variable.\n *\n * - `'error'` — Only errors (default when `STASH_STACK_LOG` is not set).\n * - `'info'` — Info and errors.\n * - `'debug'` — Debug, info, and errors.\n */\nexport type LogLevel = 'debug' | 'info' | 'error'\n\nconst validLevels: readonly LogLevel[] = ['debug', 'info', 'error'] as const\n\nfunction levelFromEnv(): LogLevel {\n const env = process.env.STASH_STACK_LOG\n if (env && validLevels.includes(env as LogLevel)) return env as LogLevel\n return 'error'\n}\n\nfunction samplingRatesForLevel(level: LogLevel): Record<string, number> {\n // evlog uses sampling rates: 100 = always emit, 0 = never emit\n switch (level) {\n case 'debug':\n return { debug: 100, info: 100, warn: 100, error: 100 }\n case 'info':\n return { debug: 0, info: 100, warn: 100, error: 100 }\n case 'error':\n default:\n return { debug: 0, info: 0, warn: 0, error: 100 }\n }\n}\n\nlet initialized = false\n\n/**\n * Initialize the Stack logger.\n *\n * The log level is read from the `STASH_STACK_LOG` environment variable.\n * When the variable is not set, the default is `'error'` (errors only).\n *\n * @internal\n */\nexport function initStackLogger(): void {\n if (initialized) return\n initialized = true\n\n const level = levelFromEnv()\n const rates = samplingRatesForLevel(level)\n\n initLogger({\n env: { service: '@cipherstash/stack' },\n enabled: true,\n sampling: { rates },\n })\n}\n\n// Auto-init with defaults on first import\ninitStackLogger()\n\nexport { createRequestLogger }\n\n// Stringify only the first arg (the message string); drop subsequent args\n// which may contain sensitive objects (e.g. encryptConfig, plaintext).\nfunction safeMessage(args: unknown[]): string {\n return typeof args[0] === 'string' ? args[0] : ''\n}\n\n// Logger for simple one-off logs used across Stack interfaces.\nexport const logger = {\n debug(...args: unknown[]) {\n const log = createRequestLogger()\n log.set({\n level: 'debug',\n source: '@cipherstash/stack',\n message: safeMessage(args),\n })\n log.emit()\n },\n info(...args: unknown[]) {\n const log = createRequestLogger()\n log.set({ source: '@cipherstash/stack' })\n log.info(safeMessage(args))\n log.emit()\n },\n warn(...args: unknown[]) {\n const log = createRequestLogger()\n log.warn(safeMessage(args))\n log.emit()\n },\n error(...args: unknown[]) {\n const log = createRequestLogger()\n log.error(safeMessage(args))\n log.emit()\n },\n}\n"],"mappings":"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","names":[]}
|