aegis-lock 2.0.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/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # aegis-lock
2
+
3
+ **Database-agnostic client-side AES-256-GCM field-level encryption.**
4
+
5
+ Encrypt sensitive fields before they leave the browser or server. Decrypt after select. Zero plaintext hits the wire or your database. Works with **Supabase**, **MongoDB**, or any database via custom adapters.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install aegis-lock
11
+ ```
12
+
13
+ ## Quick Start — Supabase
14
+
15
+ ```typescript
16
+ import { createClient } from "@supabase/supabase-js";
17
+ import { AegisClient, SupabaseAdapter, generateKey, exportKey } from "aegis-lock";
18
+
19
+ const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
20
+ const adapter = new SupabaseAdapter(supabase);
21
+
22
+ const key = await generateKey();
23
+ const exported = await exportKey(key); // save this securely!
24
+
25
+ const aegis = new AegisClient(adapter, key, {
26
+ secure_fields: ["encrypted_content", "ssn", "credit_card"],
27
+ });
28
+
29
+ // Insert — fields are auto-encrypted
30
+ await aegis.insert("secure_fields", {
31
+ record_id: "some-uuid",
32
+ encrypted_content: "Top secret",
33
+ });
34
+
35
+ // Select — fields are auto-decrypted
36
+ const { data } = await aegis.select("secure_fields");
37
+ ```
38
+
39
+ ## Quick Start — MongoDB
40
+
41
+ ```typescript
42
+ import { MongoClient } from "mongodb";
43
+ import { AegisClient, MongoDBAdapter, generateKey } from "aegis-lock";
44
+
45
+ const mongo = new MongoClient("mongodb://localhost:27017");
46
+ await mongo.connect();
47
+ const adapter = new MongoDBAdapter(mongo.db("myapp"));
48
+
49
+ const key = await generateKey();
50
+
51
+ const aegis = new AegisClient(adapter, key, {
52
+ users: ["ssn", "credit_card"],
53
+ });
54
+
55
+ await aegis.insert("users", { name: "Alice", ssn: "123-45-6789" });
56
+ const { data } = await aegis.select("users", { column: "name", value: "Alice" });
57
+ // data[0].ssn → "123-45-6789" (decrypted)
58
+ ```
59
+
60
+ ## Custom Adapter
61
+
62
+ Implement the `DatabaseAdapter` interface for any database:
63
+
64
+ ```typescript
65
+ import { DatabaseAdapter, AegisClient } from "aegis-lock";
66
+
67
+ class MyAdapter implements DatabaseAdapter {
68
+ async insert(table: string, data: Record<string, unknown>) {
69
+ // your insert logic
70
+ return { data: [data], error: null };
71
+ }
72
+ async select(table: string, query?) {
73
+ // your select logic
74
+ return { data: [], error: null };
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## API
80
+
81
+ ### `new AegisClient(adapter, key, encryptedFields)`
82
+ - `adapter` — any `DatabaseAdapter` (SupabaseAdapter, MongoDBAdapter, or custom)
83
+ - `key` — CryptoKey from `generateKey()` or `importKey()`
84
+ - `encryptedFields` — `Record<tableName, fieldName[]>`
85
+
86
+ ### Adapters
87
+ - `new SupabaseAdapter(supabaseClient)`
88
+ - `new MongoDBAdapter(mongoDb)`
89
+
90
+ ### Crypto
91
+ - `generateKey()` / `exportKey(key)` / `importKey(base64)`
92
+ - `encrypt(plaintext, key)` / `decrypt(payload, key)`
93
+
94
+ ## How It Works
95
+
96
+ - **Web Crypto API** (AES-256-GCM) — runs in any modern browser or edge runtime
97
+ - Each row gets a unique **IV** stored alongside the ciphertext
98
+ - Encryption/decryption happens client-side — your server never sees plaintext
99
+ - Database-agnostic: swap adapters without changing application code
100
+
101
+ ## License
102
+
103
+ MIT
@@ -0,0 +1,44 @@
1
+ import type { DatabaseAdapter } from "../types";
2
+ /**
3
+ * MongoDB adapter for aegis-mern.
4
+ *
5
+ * Works with any MongoDB client that exposes a `db()` method (e.g. the official
6
+ * `mongodb` Node.js driver). Pass the Db instance directly.
7
+ *
8
+ * Usage:
9
+ * ```ts
10
+ * import { MongoClient } from "mongodb";
11
+ * import { MongoDBAdapter } from "aegis-mern/adapters/mongodb";
12
+ *
13
+ * const client = new MongoClient(uri);
14
+ * await client.connect();
15
+ * const adapter = new MongoDBAdapter(client.db("mydb"));
16
+ * ```
17
+ */
18
+ export declare class MongoDBAdapter implements DatabaseAdapter {
19
+ private db;
20
+ constructor(db: any);
21
+ insert(table: string, data: Record<string, unknown>): Promise<{
22
+ data: {
23
+ _id: any;
24
+ }[];
25
+ error: null;
26
+ } | {
27
+ data: null;
28
+ error: unknown;
29
+ }>;
30
+ select(table: string, query?: {
31
+ column?: string;
32
+ value?: unknown;
33
+ limit?: number;
34
+ }): Promise<{
35
+ data: Record<string, unknown>[];
36
+ error: null;
37
+ } | {
38
+ data: null;
39
+ error: unknown;
40
+ }>;
41
+ /** Access the underlying MongoDB Db instance. */
42
+ get database(): any;
43
+ }
44
+ //# sourceMappingURL=mongodb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mongodb.d.ts","sourceRoot":"","sources":["../../adapters/mongodb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,EAAE,CAAM;gBAEJ,EAAE,EAAE,GAAG;IAIb,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;IAWnD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;cAY7D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;;;;;;IAMpD,iDAAiD;IACjD,IAAI,QAAQ,QAEX;CACF"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * MongoDB adapter for aegis-mern.
3
+ *
4
+ * Works with any MongoDB client that exposes a `db()` method (e.g. the official
5
+ * `mongodb` Node.js driver). Pass the Db instance directly.
6
+ *
7
+ * Usage:
8
+ * ```ts
9
+ * import { MongoClient } from "mongodb";
10
+ * import { MongoDBAdapter } from "aegis-mern/adapters/mongodb";
11
+ *
12
+ * const client = new MongoClient(uri);
13
+ * await client.connect();
14
+ * const adapter = new MongoDBAdapter(client.db("mydb"));
15
+ * ```
16
+ */
17
+ export class MongoDBAdapter {
18
+ constructor(db) {
19
+ this.db = db;
20
+ }
21
+ async insert(table, data) {
22
+ try {
23
+ const collection = this.db.collection(table);
24
+ const result = await collection.insertOne(data);
25
+ const inserted = { ...data, _id: result.insertedId };
26
+ return { data: [inserted], error: null };
27
+ }
28
+ catch (error) {
29
+ return { data: null, error };
30
+ }
31
+ }
32
+ async select(table, query) {
33
+ try {
34
+ const collection = this.db.collection(table);
35
+ const filter = {};
36
+ if (query?.column && query?.value !== undefined) {
37
+ filter[query.column] = query.value;
38
+ }
39
+ let cursor = collection.find(filter);
40
+ if (query?.limit) {
41
+ cursor = cursor.limit(query.limit);
42
+ }
43
+ const data = await cursor.toArray();
44
+ return { data: data, error: null };
45
+ }
46
+ catch (error) {
47
+ return { data: null, error };
48
+ }
49
+ }
50
+ /** Access the underlying MongoDB Db instance. */
51
+ get database() {
52
+ return this.db;
53
+ }
54
+ }
55
+ //# sourceMappingURL=mongodb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mongodb.js","sourceRoot":"","sources":["../../adapters/mongodb.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,cAAc;IAGzB,YAAY,EAAO;QACjB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,IAA6B;QACvD,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAChD,MAAM,QAAQ,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;YACrD,OAAO,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC3C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAA4D;QACtF,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,MAAM,GAA4B,EAAE,CAAC;YAC3C,IAAI,KAAK,EAAE,MAAM,IAAI,KAAK,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;gBAChD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;YACrC,CAAC;YACD,IAAI,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrC,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;gBACjB,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrC,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,OAAO,EAAE,IAAI,EAAE,IAAiC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAClE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,EAAE,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,22 @@
1
+ import type { SupabaseClient } from "@supabase/supabase-js";
2
+ import type { DatabaseAdapter } from "../types";
3
+ /** Supabase adapter for aegis-mern. */
4
+ export declare class SupabaseAdapter implements DatabaseAdapter {
5
+ private supabase;
6
+ constructor(supabase: SupabaseClient);
7
+ insert(table: string, data: Record<string, unknown>): Promise<{
8
+ data: Record<string, unknown>[] | null;
9
+ error: import("@supabase/postgrest-js").PostgrestError | null;
10
+ }>;
11
+ select(table: string, query?: {
12
+ column?: string;
13
+ value?: unknown;
14
+ limit?: number;
15
+ }): Promise<{
16
+ data: Record<string, unknown>[] | null;
17
+ error: import("@supabase/postgrest-js").PostgrestError | null;
18
+ }>;
19
+ /** Access the underlying Supabase client for non-encrypted ops. */
20
+ get client(): SupabaseClient<any, "public", "public", any, any>;
21
+ }
22
+ //# sourceMappingURL=supabase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../adapters/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,uCAAuC;AACvC,qBAAa,eAAgB,YAAW,eAAe;IACrD,OAAO,CAAC,QAAQ,CAAiB;gBAErB,QAAQ,EAAE,cAAc;IAI9B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;cAE9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI;;;IAGrD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;cAS/D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI;;;IAGzD,mEAAmE;IACnE,IAAI,MAAM,sDAET;CACF"}
@@ -0,0 +1,26 @@
1
+ /** Supabase adapter for aegis-mern. */
2
+ export class SupabaseAdapter {
3
+ constructor(supabase) {
4
+ this.supabase = supabase;
5
+ }
6
+ async insert(table, data) {
7
+ const { data: result, error } = await this.supabase.from(table).insert(data).select();
8
+ return { data: result, error };
9
+ }
10
+ async select(table, query) {
11
+ let q = this.supabase.from(table).select("*");
12
+ if (query?.column && query?.value !== undefined) {
13
+ q = q.eq(query.column, query.value);
14
+ }
15
+ if (query?.limit) {
16
+ q = q.limit(query.limit);
17
+ }
18
+ const { data, error } = await q;
19
+ return { data: data, error };
20
+ }
21
+ /** Access the underlying Supabase client for non-encrypted ops. */
22
+ get client() {
23
+ return this.supabase;
24
+ }
25
+ }
26
+ //# sourceMappingURL=supabase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supabase.js","sourceRoot":"","sources":["../../adapters/supabase.ts"],"names":[],"mappings":"AAGA,uCAAuC;AACvC,MAAM,OAAO,eAAe;IAG1B,YAAY,QAAwB;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,IAA6B;QACvD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QACtF,OAAO,EAAE,IAAI,EAAE,MAA0C,EAAE,KAAK,EAAE,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAA4D;QACtF,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,KAAK,EAAE,MAAM,IAAI,KAAK,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YAChD,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;YACjB,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,CAAC;QAChC,OAAO,EAAE,IAAI,EAAE,IAAwC,EAAE,KAAK,EAAE,CAAC;IACnE,CAAC;IAED,mEAAmE;IACnE,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1,33 @@
1
+ import type { DatabaseAdapter } from "./types";
2
+ export declare class AegisClient {
3
+ private adapter;
4
+ private key;
5
+ private encryptedFields;
6
+ constructor(adapter: DatabaseAdapter, key: CryptoKey, encryptedFields: Record<string, string[]>);
7
+ /** Insert a row, auto-encrypting configured fields. Returns a shared IV for the row. */
8
+ insert(table: string, data: Record<string, unknown>): Promise<{
9
+ data: Record<string, unknown>[] | null;
10
+ error: unknown;
11
+ }>;
12
+ /** Select rows, auto-decrypting configured fields. */
13
+ select(table: string, query?: {
14
+ column?: string;
15
+ value?: unknown;
16
+ limit?: number;
17
+ }): Promise<{
18
+ data: Record<string, unknown>[] | null;
19
+ error: unknown;
20
+ }>;
21
+ /** Select rows WITHOUT decrypting — exposes raw ciphertext. */
22
+ selectRaw(table: string, query?: {
23
+ column?: string;
24
+ value?: unknown;
25
+ limit?: number;
26
+ }): Promise<{
27
+ data: Record<string, unknown>[] | null;
28
+ error: unknown;
29
+ }>;
30
+ /** Access the underlying database adapter. */
31
+ get db(): DatabaseAdapter;
32
+ }
33
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAG/C,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,eAAe,CAA2B;gBAEtC,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAM/F,wFAAwF;IAClF,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;IAsBzD,sDAAsD;IAChD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;IAgCxF,+DAA+D;IACzD,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;IAI3F,8CAA8C;IAC9C,IAAI,EAAE,IAAI,eAAe,CAExB;CACF"}
package/dist/client.js ADDED
@@ -0,0 +1,62 @@
1
+ import { encrypt, decrypt } from "./crypto";
2
+ export class AegisClient {
3
+ constructor(adapter, key, encryptedFields) {
4
+ this.adapter = adapter;
5
+ this.key = key;
6
+ this.encryptedFields = encryptedFields;
7
+ }
8
+ /** Insert a row, auto-encrypting configured fields. Returns a shared IV for the row. */
9
+ async insert(table, data) {
10
+ const fields = this.encryptedFields[table] || [];
11
+ const row = { ...data };
12
+ // Generate a single IV and reuse it for all fields in this row
13
+ const ivBuffer = crypto.getRandomValues(new Uint8Array(12));
14
+ const sharedIv = btoa(String.fromCharCode(...ivBuffer));
15
+ for (const field of fields) {
16
+ if (row[field] != null) {
17
+ const { ciphertext } = await encrypt(String(row[field]), this.key, ivBuffer);
18
+ row[field] = ciphertext;
19
+ }
20
+ }
21
+ if (fields.length > 0) {
22
+ row.iv = sharedIv;
23
+ }
24
+ return this.adapter.insert(table, row);
25
+ }
26
+ /** Select rows, auto-decrypting configured fields. */
27
+ async select(table, query) {
28
+ const { data, error } = await this.adapter.select(table, query);
29
+ if (error || !data)
30
+ return { data, error };
31
+ const fields = this.encryptedFields[table] || [];
32
+ if (fields.length === 0)
33
+ return { data, error };
34
+ const decrypted = await Promise.all(data.map(async (row) => {
35
+ const decRow = { ...row };
36
+ const iv = row.iv;
37
+ if (!iv)
38
+ return decRow;
39
+ for (const field of fields) {
40
+ if (decRow[field] != null) {
41
+ try {
42
+ decRow[field] = await decrypt({ ciphertext: String(decRow[field]), iv }, this.key);
43
+ }
44
+ catch {
45
+ // leave as ciphertext if decryption fails
46
+ }
47
+ }
48
+ }
49
+ return decRow;
50
+ }));
51
+ return { data: decrypted, error };
52
+ }
53
+ /** Select rows WITHOUT decrypting — exposes raw ciphertext. */
54
+ async selectRaw(table, query) {
55
+ return this.adapter.select(table, query);
56
+ }
57
+ /** Access the underlying database adapter. */
58
+ get db() {
59
+ return this.adapter;
60
+ }
61
+ }
62
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { EncryptedPayload } from "./types";
2
+ export declare function generateKey(): Promise<CryptoKey>;
3
+ export declare function exportKey(key: CryptoKey): Promise<string>;
4
+ export declare function importKey(base64: string): Promise<CryptoKey>;
5
+ export declare function encrypt(plaintext: string, key: CryptoKey, existingIv?: Uint8Array): Promise<EncryptedPayload>;
6
+ export declare function decrypt(payload: EncryptedPayload, key: CryptoKey): Promise<string>;
7
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAK3C,wBAAsB,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAMtD;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/D;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAMlE;AAED,wBAAsB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAQnH;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAKxF"}
package/dist/crypto.js ADDED
@@ -0,0 +1,32 @@
1
+ const ALGO = "AES-GCM";
2
+ const KEY_LENGTH = 256;
3
+ export async function generateKey() {
4
+ return crypto.subtle.generateKey({ name: ALGO, length: KEY_LENGTH }, true, ["encrypt", "decrypt"]);
5
+ }
6
+ export async function exportKey(key) {
7
+ const raw = await crypto.subtle.exportKey("raw", key);
8
+ return btoa(String.fromCharCode(...new Uint8Array(raw)));
9
+ }
10
+ export async function importKey(base64) {
11
+ const raw = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
12
+ return crypto.subtle.importKey("raw", raw, { name: ALGO, length: KEY_LENGTH }, true, [
13
+ "encrypt",
14
+ "decrypt",
15
+ ]);
16
+ }
17
+ export async function encrypt(plaintext, key, existingIv) {
18
+ const iv = existingIv ? new Uint8Array(existingIv) : crypto.getRandomValues(new Uint8Array(12));
19
+ const encoded = new TextEncoder().encode(plaintext);
20
+ const cipherBuffer = await crypto.subtle.encrypt({ name: ALGO, iv }, key, encoded);
21
+ return {
22
+ ciphertext: btoa(String.fromCharCode(...new Uint8Array(cipherBuffer))),
23
+ iv: btoa(String.fromCharCode(...iv)),
24
+ };
25
+ }
26
+ export async function decrypt(payload, key) {
27
+ const cipherBytes = Uint8Array.from(atob(payload.ciphertext), (c) => c.charCodeAt(0));
28
+ const iv = Uint8Array.from(atob(payload.iv), (c) => c.charCodeAt(0));
29
+ const decrypted = await crypto.subtle.decrypt({ name: ALGO, iv }, key, cipherBytes);
30
+ return new TextDecoder().decode(decrypted);
31
+ }
32
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"AAEA,MAAM,IAAI,GAAG,SAAS,CAAC;AACvB,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,WAAW,CAC9B,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,EAClC,IAAI,EACJ,CAAC,SAAS,EAAE,SAAS,CAAC,CACvB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAc;IAC5C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc;IAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE;QACnF,SAAS;QACT,SAAS;KACV,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,SAAiB,EAAE,GAAc,EAAE,UAAuB;IACtF,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IAChG,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACnF,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;QACtE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAyB,EAAE,GAAc;IACrE,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACtF,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;IACpF,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { AegisClient } from "./client";
2
+ export { generateKey, exportKey, importKey, encrypt, decrypt } from "./crypto";
3
+ export { SupabaseAdapter } from "./adapters/supabase";
4
+ export { MongoDBAdapter } from "./adapters/mongodb";
5
+ export type { AegisConfig, EncryptedPayload, AegisKeyPair, DatabaseAdapter } from "./types";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { AegisClient } from "./client";
2
+ export { generateKey, exportKey, importKey, encrypt, decrypt } from "./crypto";
3
+ export { SupabaseAdapter } from "./adapters/supabase";
4
+ export { MongoDBAdapter } from "./adapters/mongodb";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /** Generic database adapter interface — implement this for any database. */
2
+ export interface DatabaseAdapter {
3
+ /** Insert a row into a table/collection. Returns the inserted data. */
4
+ insert(table: string, data: Record<string, unknown>): Promise<{
5
+ data: Record<string, unknown>[] | null;
6
+ error: unknown;
7
+ }>;
8
+ /** Select rows from a table/collection with optional filters. */
9
+ select(table: string, query?: {
10
+ column?: string;
11
+ value?: unknown;
12
+ limit?: number;
13
+ }): Promise<{
14
+ data: Record<string, unknown>[] | null;
15
+ error: unknown;
16
+ }>;
17
+ }
18
+ export interface AegisConfig {
19
+ adapter: DatabaseAdapter;
20
+ encryptedFields: Record<string, string[]>;
21
+ }
22
+ export interface EncryptedPayload {
23
+ ciphertext: string;
24
+ iv: string;
25
+ }
26
+ export interface AegisKeyPair {
27
+ key: CryptoKey;
28
+ exported: string;
29
+ }
30
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAE1H,iEAAiE;IACjE,MAAM,CACJ,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3D,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACxE;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "aegis-lock",
3
+ "version": "2.0.0",
4
+ "description": "Database-agnostic client-side AES-256-GCM field-level encryption. Works with Supabase, MongoDB, or any database via pluggable adapters.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ },
14
+ "./adapters/supabase": {
15
+ "import": "./dist/adapters/supabase.js",
16
+ "types": "./dist/adapters/supabase.d.ts"
17
+ },
18
+ "./adapters/mongodb": {
19
+ "import": "./dist/adapters/mongodb.js",
20
+ "types": "./dist/adapters/mongodb.d.ts"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md"
26
+ ],
27
+ "scripts": {
28
+ "build": "tsc -p tsconfig.build.json",
29
+ "prepublishOnly": "npm run build"
30
+ },
31
+ "keywords": [
32
+ "encryption",
33
+ "aes-gcm",
34
+ "supabase",
35
+ "mongodb",
36
+ "mern",
37
+ "client-side-encryption",
38
+ "field-level-encryption",
39
+ "database-agnostic",
40
+ "aegis",
41
+ "security",
42
+ "crypto"
43
+ ],
44
+ "author": "",
45
+ "license": "MIT",
46
+ "peerDependencies": {
47
+ "@supabase/supabase-js": "^2.0.0"
48
+ },
49
+ "peerDependenciesMeta": {
50
+ "@supabase/supabase-js": {
51
+ "optional": true
52
+ }
53
+ },
54
+ "devDependencies": {
55
+ "@supabase/supabase-js": "^2.0.0",
56
+ "typescript": "^5.9.3"
57
+ }
58
+ }