@vielzeug/vault 2.0.0 → 2.1.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.
Files changed (61) hide show
  1. package/README.md +42 -6
  2. package/dist/adapter-core.cjs +1 -1
  3. package/dist/adapter-core.cjs.map +1 -1
  4. package/dist/adapter-core.d.ts +1 -0
  5. package/dist/adapter-core.d.ts.map +1 -1
  6. package/dist/adapter-core.js +98 -108
  7. package/dist/adapter-core.js.map +1 -1
  8. package/dist/adapters/indexeddb.cjs +1 -1
  9. package/dist/adapters/indexeddb.cjs.map +1 -1
  10. package/dist/adapters/indexeddb.d.ts.map +1 -1
  11. package/dist/adapters/indexeddb.js +114 -113
  12. package/dist/adapters/indexeddb.js.map +1 -1
  13. package/dist/adapters/memory.cjs +1 -1
  14. package/dist/adapters/memory.js +59 -59
  15. package/dist/adapters/sqlite.cjs +42 -0
  16. package/dist/adapters/sqlite.cjs.map +1 -0
  17. package/dist/adapters/sqlite.d.ts +43 -0
  18. package/dist/adapters/sqlite.d.ts.map +1 -0
  19. package/dist/adapters/sqlite.js +401 -0
  20. package/dist/adapters/sqlite.js.map +1 -0
  21. package/dist/adapters/webstorage.cjs +1 -1
  22. package/dist/adapters/webstorage.js +25 -25
  23. package/dist/index.cjs +1 -1
  24. package/dist/index.d.ts +1 -6
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +4 -8
  27. package/dist/indexeddb.cjs +1 -0
  28. package/dist/indexeddb.d.ts +5 -0
  29. package/dist/indexeddb.d.ts.map +1 -0
  30. package/dist/indexeddb.js +3 -0
  31. package/dist/local-storage.cjs +1 -0
  32. package/dist/local-storage.d.ts +2 -0
  33. package/dist/local-storage.d.ts.map +1 -0
  34. package/dist/local-storage.js +2 -0
  35. package/dist/memory.cjs +1 -0
  36. package/dist/memory.d.ts +2 -0
  37. package/dist/memory.d.ts.map +1 -0
  38. package/dist/memory.js +2 -0
  39. package/dist/session-storage.cjs +1 -0
  40. package/dist/session-storage.d.ts +2 -0
  41. package/dist/session-storage.d.ts.map +1 -0
  42. package/dist/session-storage.js +2 -0
  43. package/dist/sqlite.cjs +1 -0
  44. package/dist/sqlite.d.ts +3 -0
  45. package/dist/sqlite.d.ts.map +1 -0
  46. package/dist/sqlite.js +2 -0
  47. package/dist/types.cjs.map +1 -1
  48. package/dist/types.d.ts +8 -2
  49. package/dist/types.d.ts.map +1 -1
  50. package/dist/types.js.map +1 -1
  51. package/dist/vault.cjs +1 -1
  52. package/dist/vault.cjs.map +1 -1
  53. package/dist/vault.iife.js +1 -1
  54. package/dist/vault.iife.js.map +1 -1
  55. package/dist/vault.js +1 -1
  56. package/dist/vault.js.map +1 -1
  57. package/package.json +48 -3
  58. package/dist/streaming.d.ts +0 -2
  59. package/dist/streaming.d.ts.map +0 -1
  60. package/dist/versioned-codec.d.ts +0 -2
  61. package/dist/versioned-codec.d.ts.map +0 -1
@@ -1,17 +1,17 @@
1
- import { encodeVaultKey as e, getRecordKey as t } from "../internal.js";
2
- import { isExpired as n, parseStored as r } from "../ttl.js";
1
+ import { isExpired as e, parseStored as t } from "../ttl.js";
2
+ import { encodeVaultKey as n, getRecordKey as r } from "../internal.js";
3
3
  import { buildAdapterOps as i } from "../adapter-core.js";
4
4
  //#region src/adapters/memory.ts
5
5
  function a(e) {
6
6
  if (typeof e != "object" || !e) return !1;
7
- let t = e;
8
- if (typeof t.table != "string" || typeof t.type != "string" || t.table === "__proto__" || t.table === "constructor" || t.table === "prototype") return !1;
9
- switch (t.type) {
7
+ let n = e;
8
+ if (typeof n.table != "string" || typeof n.type != "string" || n.table === "__proto__" || n.table === "constructor" || n.table === "prototype") return !1;
9
+ switch (n.type) {
10
10
  case "clear": return !0;
11
- case "delete": return typeof t.key == "string";
12
- case "deleteMany": return Array.isArray(t.keys) && t.keys.every((e) => typeof e == "string");
13
- case "put": return typeof t.key == "string" && r(t.stored) !== void 0;
14
- case "putAll": return Array.isArray(t.entries) && t.entries.every((e) => typeof e == "object" && !!e && typeof e.key == "string" && r(e.stored) !== void 0);
11
+ case "delete": return typeof n.key == "string";
12
+ case "deleteMany": return Array.isArray(n.keys) && n.keys.every((e) => typeof e == "string");
13
+ case "put": return typeof n.key == "string" && t(n.stored) !== void 0;
14
+ case "putAll": return Array.isArray(n.entries) && n.entries.every((e) => typeof e == "object" && !!e && typeof e.key == "string" && t(e.stored) !== void 0);
15
15
  default: return !1;
16
16
  }
17
17
  }
@@ -23,50 +23,50 @@ function o(o) {
23
23
  type: "clear"
24
24
  });
25
25
  },
26
- async count(e) {
27
- let t = p(e), i = 0;
28
- for (let [e, a] of t) {
29
- let o = r(a);
30
- !o || n(o.expiresAt) ? t.delete(e) : i += 1;
26
+ async count(n) {
27
+ let r = p(n), i = 0;
28
+ for (let [n, a] of r) {
29
+ let o = t(a);
30
+ !o || e(o.expiresAt) ? r.delete(n) : i += 1;
31
31
  }
32
32
  return i;
33
33
  },
34
- async delete(t, i) {
35
- let a = p(t), o = e(i), s = r(a.get(o));
34
+ async delete(r, i) {
35
+ let a = p(r), o = n(i), s = t(a.get(o));
36
36
  a.delete(o);
37
- let c = s !== void 0 && !n(s.expiresAt);
37
+ let c = s !== void 0 && !e(s.expiresAt);
38
38
  return c && m?.postMessage({
39
39
  key: o,
40
- table: t,
40
+ table: r,
41
41
  type: "delete"
42
42
  }), c;
43
43
  },
44
- async deleteMany(t, i) {
44
+ async deleteMany(r, i) {
45
45
  let a = 0, o = [];
46
46
  for (let s of i) {
47
- let i = e(s), c = r(p(t).get(i));
48
- p(t).delete(i), c !== void 0 && !n(c.expiresAt) && (a += 1, o.push(i));
47
+ let i = n(s), c = t(p(r).get(i));
48
+ p(r).delete(i), c !== void 0 && !e(c.expiresAt) && (a += 1, o.push(i));
49
49
  }
50
50
  return o.length > 0 && m?.postMessage({
51
51
  keys: o,
52
- table: t,
52
+ table: r,
53
53
  type: "deleteMany"
54
54
  }), a;
55
55
  },
56
56
  dispose: m ? async () => m.close() : void 0,
57
- async get(t, i) {
58
- let a = p(t), o = e(i), s = r(a.get(o));
59
- if (!s || n(s.expiresAt)) {
57
+ async get(r, i) {
58
+ let a = p(r), o = n(i), s = t(a.get(o));
59
+ if (!s || e(s.expiresAt)) {
60
60
  a.delete(o);
61
61
  return;
62
62
  }
63
63
  return s.value;
64
64
  },
65
- async getAll(e) {
66
- let t = p(e), i = [];
67
- for (let [e, a] of t) {
68
- let o = r(a);
69
- !o || n(o.expiresAt) ? t.delete(e) : i.push(o.value);
65
+ async getAll(n) {
66
+ let r = p(n), i = [];
67
+ for (let [n, a] of r) {
68
+ let o = t(a);
69
+ !o || e(o.expiresAt) ? r.delete(n) : i.push(o.value);
70
70
  }
71
71
  return i;
72
72
  },
@@ -76,59 +76,59 @@ function o(o) {
76
76
  async has(e, t) {
77
77
  return await h.get(e, t) !== void 0;
78
78
  },
79
- async pruneExpiredInTable(e) {
80
- let t = p(e), i = 0;
81
- for (let [e, a] of t) {
82
- let o = r(a);
83
- (!o || n(o.expiresAt)) && (t.delete(e), i += 1);
79
+ async pruneExpiredInTable(n) {
80
+ let r = p(n), i = 0;
81
+ for (let [n, a] of r) {
82
+ let o = t(a);
83
+ (!o || e(o.expiresAt)) && (r.delete(n), i += 1);
84
84
  }
85
85
  return i;
86
86
  },
87
- async put(n, r, i) {
88
- let a = e(t(u, n, r)), o = i === void 0 ? { value: r } : {
87
+ async put(e, t, i) {
88
+ let a = n(r(u, e, t)), o = i === void 0 ? { value: t } : {
89
89
  expiresAt: Date.now() + i,
90
- value: r
90
+ value: t
91
91
  };
92
- p(n).set(a, o), m?.postMessage({
92
+ p(e).set(a, o), m?.postMessage({
93
93
  key: a,
94
94
  stored: o,
95
- table: n,
95
+ table: e,
96
96
  type: "put"
97
97
  });
98
98
  },
99
- async putAll(n, r, i) {
99
+ async putAll(e, t, i) {
100
100
  let a = i === void 0 ? void 0 : Date.now() + i, o = [];
101
- for (let i of r) {
102
- let r = e(t(u, n, i)), s = a === void 0 ? { value: i } : {
101
+ for (let i of t) {
102
+ let t = n(r(u, e, i)), s = a === void 0 ? { value: i } : {
103
103
  expiresAt: a,
104
104
  value: i
105
105
  };
106
- p(n).set(r, s), o.push({
107
- key: r,
106
+ p(e).set(t, s), o.push({
107
+ key: t,
108
108
  stored: s
109
109
  });
110
110
  }
111
111
  o.length > 0 && m?.postMessage({
112
112
  entries: o,
113
- table: n,
113
+ table: e,
114
114
  type: "putAll"
115
115
  });
116
116
  }
117
117
  };
118
118
  return i(u, h, {
119
119
  logger: s,
120
- onCrossTabMessage: m ? (t) => (m.onmessage = (n) => {
121
- if (!a(n.data)) return;
122
- let i = n.data;
120
+ onCrossTabMessage: m ? (e) => (m.onmessage = (r) => {
121
+ if (!a(r.data)) return;
122
+ let i = r.data;
123
123
  if (!f.has(i.table)) return;
124
- let o = p(i.table), s = (t, n) => {
125
- let a = r(n), s = u[i.table]?.key, c = d?.[i.table];
124
+ let o = p(i.table), s = (e, r) => {
125
+ let a = t(r), s = u[i.table]?.key, c = d?.[i.table];
126
126
  if (!a || !s) return !1;
127
127
  try {
128
- let n = c ? c.parse(a.value) : a.value;
129
- return e(n[s]) === t && (o.set(t, a.expiresAt === void 0 ? { value: n } : {
128
+ let t = c ? c.parse(a.value) : a.value;
129
+ return n(t[s]) === e && (o.set(e, a.expiresAt === void 0 ? { value: t } : {
130
130
  expiresAt: a.expiresAt,
131
- value: n
131
+ value: t
132
132
  }), !0);
133
133
  } catch {
134
134
  return !1;
@@ -136,19 +136,19 @@ function o(o) {
136
136
  };
137
137
  switch (i.type) {
138
138
  case "clear":
139
- o.clear(), t(i.table);
139
+ o.clear(), e(i.table);
140
140
  break;
141
141
  case "delete":
142
- o.delete(i.key), t(i.table);
142
+ o.delete(i.key), e(i.table);
143
143
  break;
144
144
  case "deleteMany":
145
145
  for (let e of i.keys) o.delete(e);
146
- t(i.table);
146
+ e(i.table);
147
147
  break;
148
148
  case "put":
149
- s(i.key, i.stored) && t(i.table);
149
+ s(i.key, i.stored) && e(i.table);
150
150
  break;
151
- case "putAll": i.entries.some((e) => s(e.key, e.stored)) && t(i.table);
151
+ case "putAll": i.entries.some((e) => s(e.key, e.stored)) && e(i.table);
152
152
  }
153
153
  }, () => {
154
154
  m.onmessage = null;
@@ -0,0 +1,42 @@
1
+ const e=require("../errors.cjs"),t=require("../ttl.cjs"),n=require("../internal.cjs"),r=require("../adapter-core.cjs");var i=new WeakMap,a=`"__vielzeug_vault_records"`,o=`"__vielzeug_vault_metadata"`,s=1,c=100,l=class{tail=Promise.resolve();async acquire(){let e,t=this.tail;return this.tail=new Promise(t=>{e=t}),await t,()=>e?.()}async run(e){let t=await this.acquire();try{return await e()}finally{t()}}};function u(e){let t=i.get(e);if(t)return t;let n=new l,r={batchActive:!1,executor:n,initialized:n.run(()=>d(e)),listeners:new Set};return i.set(e,r),r}function d(e){e.exec(`
2
+ CREATE TABLE IF NOT EXISTS ${o} (
3
+ namespace TEXT PRIMARY KEY,
4
+ format_version INTEGER NOT NULL
5
+ );
6
+ CREATE TABLE IF NOT EXISTS ${a} (
7
+ namespace TEXT NOT NULL,
8
+ table_name TEXT NOT NULL,
9
+ key_tag TEXT NOT NULL,
10
+ key_kind TEXT NOT NULL,
11
+ key_number REAL,
12
+ key_string TEXT,
13
+ value_json TEXT NOT NULL,
14
+ expires_at INTEGER,
15
+ PRIMARY KEY (namespace, table_name, key_tag)
16
+ );
17
+ CREATE INDEX IF NOT EXISTS "__vielzeug_vault_records_expiration"
18
+ ON ${a} (namespace, table_name, expires_at);
19
+ CREATE INDEX IF NOT EXISTS "__vielzeug_vault_records_number_key"
20
+ ON ${a} (namespace, table_name, key_kind, key_number);
21
+ CREATE INDEX IF NOT EXISTS "__vielzeug_vault_records_string_key"
22
+ ON ${a} (namespace, table_name, key_kind, key_string);
23
+ `)}function f(t,n){let r=x(t,`SELECT format_version FROM ${o} WHERE namespace = ?`,[n]);if(r===void 0){b(t,`INSERT INTO ${o} (namespace, format_version) VALUES (?, ?)`,[n,s]);return}if(r.format_version!==s)throw new e.VaultError(`SQLite storage format for "${n}" is not supported`)}function p(t){if(t.length===0)throw new e.VaultError(`createSQLite: name must not be empty`)}function m(t,n,r){if(t===null||typeof t==`boolean`||typeof t==`string`)return;if(typeof t==`number`){if(Number.isFinite(t))return;throw new e.VaultError(`SQLite serialization failed at ${r}: numbers must be finite`)}if(typeof t!=`object`)throw new e.VaultError(`SQLite serialization failed at ${r}: expected a JSON-compatible value`);if(n.has(t))throw new e.VaultError(`SQLite serialization failed at ${r}: circular references are not supported`);if(Array.isArray(t)){n.add(t);for(let e=0;e<t.length;e+=1)m(t[e],n,`${r}[${String(e)}]`);n.delete(t);return}let i=Object.getPrototypeOf(t);if(i!==null&&i!==Object.prototype)throw new e.VaultError(`SQLite serialization failed at ${r}: expected a plain object`);n.add(t);for(let[e,i]of Object.entries(t))m(i,n,`${r}.${e}`);n.delete(t)}function h(e){return m(e,new Set,`record`),JSON.stringify(e)}function g(t){try{let n=JSON.parse(t);if(typeof n!=`object`||!n||Array.isArray(n))throw new e.VaultError(`stored record is not a JSON object`);return n}catch(t){throw e.VaultError.is(t)?t:new e.VaultError(`stored record contains invalid JSON`,{cause:t})}}function _(e){let t=n.encodeVaultKey(e);return typeof e==`number`?{encoded:t,kind:`number`,number:e,string:null}:{encoded:t,kind:`string`,number:null,string:e}}function v(t){let n=t.value_json,r=t.expires_at,i=t.row_id;if(typeof n!=`string`||typeof i!=`number`||!Number.isInteger(i))throw new e.VaultError(`SQLite storage contains a malformed record`);if(r!==null&&(typeof r!=`number`||!Number.isFinite(r)))throw new e.VaultError(`SQLite storage contains a malformed expiration timestamp`);return{expiresAt:typeof r==`number`?r:void 0,json:n,rowId:i}}function y(e,t,n){let r=e.prepare(t);try{return n(r)}finally{r.finalize?.()}}function b(e,t,n=[]){return y(e,t,e=>e.run(...n))}function x(e,t,n=[]){return y(e,t,e=>e.get(...n))}function S(e,t,n=[]){return y(e,t,e=>e.all(...n))}function C(e,t,n){b(e,`DELETE FROM ${a}
24
+ WHERE namespace = ? AND table_name = ? AND expires_at IS NOT NULL AND expires_at <= ?`,[t,n,Date.now()])}function w(e,n){let r=v(n);if(t.isExpired(r.expiresAt)){b(e,`DELETE FROM ${a} WHERE rowid = ?`,[r.rowId]);return}return g(r.json)}function T(e,t,n,r=``,i=[]){return C(e,t,n),S(e,`SELECT rowid AS row_id, expires_at, value_json
25
+ FROM ${a}
26
+ WHERE namespace = ? AND table_name = ?${r}
27
+ ORDER BY rowid`,[t,n,...i]).flatMap(t=>{let n=w(e,t);return n===void 0?[]:[n]})}function E(t,r,i){let o=(e,n)=>{let i=_(n),o=x(t,`SELECT rowid AS row_id, expires_at, value_json
28
+ FROM ${a}
29
+ WHERE namespace = ? AND table_name = ? AND key_tag = ?`,[r,e,i.encoded]);return o===void 0?void 0:w(t,o)},s={async clear(e){b(t,`DELETE FROM ${a} WHERE namespace = ? AND table_name = ?`,[r,e])},async count(n){C(t,r,n);let i=x(t,`SELECT COUNT(*) AS count FROM ${a} WHERE namespace = ? AND table_name = ?`,[r,n])?.count;if(typeof i!=`number`)throw new e.VaultError(`SQLite storage returned an invalid count`);return i},async delete(e,n){let i=o(e,n)!==void 0,s=_(n);return b(t,`DELETE FROM ${a} WHERE namespace = ? AND table_name = ? AND key_tag = ?`,[r,e,s.encoded]),i},async deleteMany(e,t){let n=0;for(let r of t)await s.delete(e,r)&&(n+=1);return n},async get(e,t){return o(e,t)},async getAll(e){return T(t,r,e)},async getAllKeys(e){return(await s.getAll(e)).map(t=>n.getRecordKey(i,e,t))},async getByKeyRange(e,n){if(n.type===`eq`)return T(t,r,e,` AND key_tag = ?`,[_(n.value).encoded]);if(n.type===`between`){if(typeof n.lower!=typeof n.upper||typeof n.lower!=`number`&&typeof n.lower!=`string`)return T(t,r,e);let i=typeof n.lower==`number`?`key_number`:`key_string`;return T(t,r,e,` AND key_kind = ? AND ${i} >= ? AND ${i} <= ?`,[typeof n.lower==`number`?`number`:`string`,n.lower,n.upper])}return T(t,r,e,` AND key_kind = ? AND substr(key_string, 1, length(?)) = ?`,[`string`,n.prefix,n.prefix])},async getMany(e,t){return t.map(t=>o(e,t))},async getRawCount(n){let i=x(t,`SELECT COUNT(*) AS count FROM ${a} WHERE namespace = ? AND table_name = ?`,[r,n])?.count;if(typeof i!=`number`)throw new e.VaultError(`SQLite storage returned an invalid count`);return i},async has(e,t){return o(e,t)!==void 0},async pruneAllExpired(){let e={};for(let t of Object.keys(i))e[t]=await s.pruneExpiredInTable(t);return e},async pruneExpiredInTable(e){let n=await s.getRawCount(e);return C(t,r,e),n-await s.getRawCount(e)},async put(e,o,s){let c=_(n.getRecordKey(i,e,o)),l=s===void 0?null:Date.now()+s;b(t,`INSERT INTO ${a}
30
+ (namespace, table_name, key_tag, key_kind, key_number, key_string, value_json, expires_at)
31
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
32
+ ON CONFLICT(namespace, table_name, key_tag) DO UPDATE SET
33
+ key_kind = excluded.key_kind,
34
+ key_number = excluded.key_number,
35
+ key_string = excluded.key_string,
36
+ value_json = excluded.value_json,
37
+ expires_at = excluded.expires_at`,[r,e,c.encoded,c.kind,c.number,c.string,h(o),l])},async putAll(e,t,n){for(let r of t)await s.put(e,r,n)}};return s}function D(t){let{closeOnDispose:n=!1,database:i,logger:o,name:s,onMetrics:l,schema:d,validators:m}=t;p(s);let h=u(i),g=h.executor.run(async()=>{await h.initialized,f(i,s)}),_,y=E(i,s,d),b=e=>h.executor.run(async()=>(await h.initialized,await g,e())),x=Object.fromEntries(Object.entries(y).map(([t,n])=>[t,(...t)=>{if(h.batchActive)throw new e.VaultError(`cannot call a SQLite store sharing this connection from batch(); use the transaction context instead`);return b(()=>n(...t))}])),C,T=r.buildAdapterOps(d,x,{logger:o,onCrossTabMessage(e){let t=(t,n)=>{t===s&&Object.hasOwn(d,n)&&e(n)};return _=t,h.listeners.add(t),()=>{h.listeners.delete(t),_===t&&(_=void 0)}},onMetrics:l,onMutation(e){for(let t of h.listeners)t!==_&&t(s,e)},onTransactions:t=>{C=async(n,a)=>{if(r.assertBatchTables(n),h.batchActive)throw new e.VaultError(`cannot call a SQLite store sharing this connection from batch(); use the transaction context instead`);return h.executor.run(async()=>{await h.initialized,await g;let o=new Set,c=E(i,s,d),l=r.buildTxContext(d,c,e=>o.add(e),t.validate,new Set(n)),u=!1,f=!1;h.batchActive=!0;try{i.exec(`BEGIN IMMEDIATE`),u=!0;let e=await a(l);i.exec(`COMMIT`),f=!0;for(let e of o)t.notifyMutation(e);return e}catch(t){if(u&&!f)try{i.exec(`ROLLBACK`)}catch(t){throw new e.VaultError(`SQLite batch rollback failed`,{cause:t})}throw t}finally{h.batchActive=!1}})}},schema:d,validators:m});if(!C)throw new e.VaultError(`SQLite transaction capability was not initialized`);let D={...T,batch:C,iterate(t){if(T.disposed)throw new e.VaultDisposedError(`"${s}" is disposed`);return{[Symbol.asyncIterator](){let n=!1,r=0,o,l=[],u=0,d=()=>{o?.(),o=void 0},f=()=>{l=S(i,`SELECT rowid AS row_id, expires_at, value_json
38
+ FROM ${a}
39
+ WHERE namespace = ? AND table_name = ? AND rowid > ?
40
+ ORDER BY rowid
41
+ LIMIT ?`,[s,t,r,c]),u=0};return{async next(){if(n)return{done:!0,value:void 0};if(h.batchActive)throw new e.VaultError(`cannot call a SQLite store sharing this connection from batch(); use the transaction context instead`);try{for(o||(o=await h.executor.acquire(),await h.initialized,await g);;){if(u>=l.length&&(f(),l.length===0))return n=!0,d(),{done:!0,value:void 0};let e=l[u++];r=v(e).rowId;let t=w(i,e);if(t!==void 0)return{done:!1,value:t}}}catch(e){throw n=!0,d(),e}},async return(e){return n=!0,d(),{done:!0,value:e}},async throw(e){throw n=!0,d(),e}}}}}};if(n){let e=D.dispose.bind(D),t;D.dispose=async()=>{await e(),t??=h.executor.run(()=>i.close?.()),await t},D[Symbol.asyncDispose]=async()=>{await D.dispose()}}return D}exports.createSQLite=D;
42
+ //# sourceMappingURL=sqlite.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.cjs","names":[],"sources":["../../src/adapters/sqlite.ts"],"sourcesContent":["import type {\n AnySchema,\n BaseAdapterOptions,\n IterableVaultStore,\n KeyOf,\n RecordOf,\n TransactionalVaultStore,\n} from '../types';\n\nimport {\n assertBatchTables,\n buildAdapterOps,\n buildTxContext,\n type BatchImpl,\n type StorageBackend,\n} from '../adapter-core';\nimport { VaultDisposedError, VaultError } from '../errors';\nimport { encodeVaultKey, getRecordKey } from '../internal';\nimport { isExpired } from '../ttl';\n\nexport type SQLiteParameter = null | number | string;\ntype SQLiteRow = Record<string, unknown>;\n\n/**\n * A synchronous SQLite statement with positional parameter binding.\n *\n * Adapters for drivers whose native statement API differs can implement this\n * structural protocol without adding a runtime dependency to Vault.\n */\nexport interface SQLiteStatement {\n all(...parameters: SQLiteParameter[]): readonly SQLiteRow[];\n finalize?(): void;\n get(...parameters: SQLiteParameter[]): SQLiteRow | undefined;\n run(...parameters: SQLiteParameter[]): unknown;\n}\n\n/**\n * A runtime-neutral synchronous SQLite connection.\n *\n * Node's `DatabaseSync`, Bun's `Database`, and Deno's `@db/sqlite` `Database`\n * satisfy this protocol directly.\n */\nexport interface SQLiteDatabase {\n close?(): void;\n exec(sql: string): void;\n prepare(sql: string): SQLiteStatement;\n}\n\nexport type SQLiteVaultOptions<S extends AnySchema> = BaseAdapterOptions<S> & {\n /** Closes the caller-provided connection during store disposal when true. */\n closeOnDispose?: boolean;\n database: SQLiteDatabase;\n /** Namespace that isolates this store's records in the shared connection. */\n name: string;\n};\n\n/** SQLite provides atomic batches and lazy keyset-paginated iteration. */\nexport interface SQLiteVaultStore<S extends AnySchema> extends TransactionalVaultStore<S>, IterableVaultStore<S> {}\n\ntype ConnectionState = {\n batchActive: boolean;\n executor: ConnectionExecutor;\n initialized: Promise<void>;\n listeners: Set<ConnectionListener>;\n};\ntype ConnectionListener = (name: string, table: string) => void;\ntype KeyColumns = { encoded: string; kind: 'number' | 'string'; number: number | null; string: string | null };\ntype StoredRow = { expiresAt: number | undefined; json: string; rowId: number };\n\nconst connectionStates = new WeakMap<SQLiteDatabase, ConnectionState>();\nconst RECORDS_TABLE = '\"__vielzeug_vault_records\"';\nconst METADATA_TABLE = '\"__vielzeug_vault_metadata\"';\nconst STORAGE_FORMAT_VERSION = 1;\nconst ITERATION_PAGE_SIZE = 100;\n\nclass ConnectionExecutor {\n private tail: Promise<void> = Promise.resolve();\n\n async acquire(): Promise<() => void> {\n let release: (() => void) | undefined;\n const previous = this.tail;\n\n this.tail = new Promise<void>((resolve) => {\n release = resolve;\n });\n await previous;\n\n return () => release?.();\n }\n\n async run<T>(work: () => T | Promise<T>): Promise<T> {\n const release = await this.acquire();\n\n try {\n return await work();\n } finally {\n release();\n }\n }\n}\n\nfunction getConnectionState(database: SQLiteDatabase): ConnectionState {\n const current = connectionStates.get(database);\n\n if (current) return current;\n\n const executor = new ConnectionExecutor();\n const state: ConnectionState = {\n batchActive: false,\n executor,\n initialized: executor.run(() => initializeDatabase(database)),\n listeners: new Set(),\n };\n\n connectionStates.set(database, state);\n\n return state;\n}\n\nfunction initializeDatabase(database: SQLiteDatabase): void {\n database.exec(\n `\n CREATE TABLE IF NOT EXISTS ${METADATA_TABLE} (\n namespace TEXT PRIMARY KEY,\n format_version INTEGER NOT NULL\n );\n CREATE TABLE IF NOT EXISTS ${RECORDS_TABLE} (\n namespace TEXT NOT NULL,\n table_name TEXT NOT NULL,\n key_tag TEXT NOT NULL,\n key_kind TEXT NOT NULL,\n key_number REAL,\n key_string TEXT,\n value_json TEXT NOT NULL,\n expires_at INTEGER,\n PRIMARY KEY (namespace, table_name, key_tag)\n );\n CREATE INDEX IF NOT EXISTS \"__vielzeug_vault_records_expiration\"\n ON ${RECORDS_TABLE} (namespace, table_name, expires_at);\n CREATE INDEX IF NOT EXISTS \"__vielzeug_vault_records_number_key\"\n ON ${RECORDS_TABLE} (namespace, table_name, key_kind, key_number);\n CREATE INDEX IF NOT EXISTS \"__vielzeug_vault_records_string_key\"\n ON ${RECORDS_TABLE} (namespace, table_name, key_kind, key_string);\n `,\n );\n}\n\nfunction initializeNamespace(database: SQLiteDatabase, name: string): void {\n const row = get(database, `SELECT format_version FROM ${METADATA_TABLE} WHERE namespace = ?`, [name]);\n\n if (row === undefined) {\n run(database, `INSERT INTO ${METADATA_TABLE} (namespace, format_version) VALUES (?, ?)`, [\n name,\n STORAGE_FORMAT_VERSION,\n ]);\n\n return;\n }\n\n if (row['format_version'] !== STORAGE_FORMAT_VERSION) {\n throw new VaultError(`SQLite storage format for \"${name}\" is not supported`);\n }\n}\n\nfunction assertName(name: string): void {\n if (name.length === 0) throw new VaultError('createSQLite: name must not be empty');\n}\n\nfunction assertJsonValue(value: unknown, seen: Set<object>, path: string): void {\n if (value === null || typeof value === 'boolean' || typeof value === 'string') return;\n\n if (typeof value === 'number') {\n if (Number.isFinite(value)) return;\n\n throw new VaultError(`SQLite serialization failed at ${path}: numbers must be finite`);\n }\n\n if (typeof value !== 'object') {\n throw new VaultError(`SQLite serialization failed at ${path}: expected a JSON-compatible value`);\n }\n\n if (seen.has(value))\n throw new VaultError(`SQLite serialization failed at ${path}: circular references are not supported`);\n\n if (Array.isArray(value)) {\n seen.add(value);\n\n for (let index = 0; index < value.length; index += 1) {\n assertJsonValue(value[index], seen, `${path}[${String(index)}]`);\n }\n\n seen.delete(value);\n\n return;\n }\n\n const prototype = Object.getPrototypeOf(value);\n\n if (prototype !== null && prototype !== Object.prototype) {\n throw new VaultError(`SQLite serialization failed at ${path}: expected a plain object`);\n }\n\n seen.add(value);\n\n for (const [key, nested] of Object.entries(value)) {\n assertJsonValue(nested, seen, `${path}.${key}`);\n }\n\n seen.delete(value);\n}\n\nfunction encodeJson(value: object): string {\n assertJsonValue(value, new Set(), 'record');\n\n return JSON.stringify(value);\n}\n\nfunction decodeJson(json: string): object {\n try {\n const value: unknown = JSON.parse(json);\n\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new VaultError('stored record is not a JSON object');\n }\n\n return value;\n } catch (error) {\n if (VaultError.is(error)) throw error;\n\n throw new VaultError('stored record contains invalid JSON', { cause: error });\n }\n}\n\nfunction toKeyColumns(key: number | string): KeyColumns {\n const encoded = encodeVaultKey(key);\n\n return typeof key === 'number'\n ? { encoded, kind: 'number', number: key, string: null }\n : { encoded, kind: 'string', number: null, string: key };\n}\n\nfunction getStoredRow(row: SQLiteRow): StoredRow {\n const json = row['value_json'];\n const rawExpiresAt = row['expires_at'];\n const rowId = row['row_id'];\n\n if (typeof json !== 'string' || typeof rowId !== 'number' || !Number.isInteger(rowId)) {\n throw new VaultError('SQLite storage contains a malformed record');\n }\n\n if (rawExpiresAt !== null && (typeof rawExpiresAt !== 'number' || !Number.isFinite(rawExpiresAt))) {\n throw new VaultError('SQLite storage contains a malformed expiration timestamp');\n }\n\n const expiresAt = typeof rawExpiresAt === 'number' ? rawExpiresAt : undefined;\n\n return { expiresAt, json, rowId };\n}\n\nfunction withStatement<T>(database: SQLiteDatabase, sql: string, work: (statement: SQLiteStatement) => T): T {\n const statement = database.prepare(sql);\n\n try {\n return work(statement);\n } finally {\n statement.finalize?.();\n }\n}\n\nfunction run(database: SQLiteDatabase, sql: string, parameters: SQLiteParameter[] = []): unknown {\n return withStatement(database, sql, (statement) => statement.run(...parameters));\n}\n\nfunction get(database: SQLiteDatabase, sql: string, parameters: SQLiteParameter[] = []): SQLiteRow | undefined {\n return withStatement(database, sql, (statement) => statement.get(...parameters));\n}\n\nfunction all(database: SQLiteDatabase, sql: string, parameters: SQLiteParameter[] = []): readonly SQLiteRow[] {\n return withStatement(database, sql, (statement) => statement.all(...parameters));\n}\n\nfunction deleteExpired(database: SQLiteDatabase, name: string, table: string): void {\n run(\n database,\n `DELETE FROM ${RECORDS_TABLE}\n WHERE namespace = ? AND table_name = ? AND expires_at IS NOT NULL AND expires_at <= ?`,\n [name, table, Date.now()],\n );\n}\n\nfunction decodeLiveRecord<T extends object>(database: SQLiteDatabase, row: SQLiteRow): T | undefined {\n const stored = getStoredRow(row);\n\n if (isExpired(stored.expiresAt)) {\n run(database, `DELETE FROM ${RECORDS_TABLE} WHERE rowid = ?`, [stored.rowId]);\n\n return undefined;\n }\n\n return decodeJson(stored.json) as T;\n}\n\nfunction getAllLive<T extends object>(\n database: SQLiteDatabase,\n name: string,\n table: string,\n filterSql = '',\n filterParameters: SQLiteParameter[] = [],\n): T[] {\n deleteExpired(database, name, table);\n\n const records = all(\n database,\n `SELECT rowid AS row_id, expires_at, value_json\n FROM ${RECORDS_TABLE}\n WHERE namespace = ? AND table_name = ?${filterSql}\n ORDER BY rowid`,\n [name, table, ...filterParameters],\n );\n\n return records.flatMap((row) => {\n const record = decodeLiveRecord<T>(database, row);\n\n return record === undefined ? [] : [record];\n });\n}\n\nfunction createDirectCore<S extends AnySchema, K extends keyof S & string>(\n database: SQLiteDatabase,\n name: string,\n schema: S,\n): StorageBackend<S, K> {\n const getRecord = <T extends K>(table: T, key: KeyOf<S, T>): RecordOf<S, T> | undefined => {\n const columns = toKeyColumns(key);\n const row = get(\n database,\n `SELECT rowid AS row_id, expires_at, value_json\n FROM ${RECORDS_TABLE}\n WHERE namespace = ? AND table_name = ? AND key_tag = ?`,\n [name, table, columns.encoded],\n );\n\n return row === undefined ? undefined : decodeLiveRecord<RecordOf<S, T>>(database, row);\n };\n\n const core: StorageBackend<S, K> = {\n async clear(table) {\n run(database, `DELETE FROM ${RECORDS_TABLE} WHERE namespace = ? AND table_name = ?`, [name, table]);\n },\n async count(table) {\n deleteExpired(database, name, table);\n\n const row = get(\n database,\n `SELECT COUNT(*) AS count FROM ${RECORDS_TABLE} WHERE namespace = ? AND table_name = ?`,\n [name, table],\n );\n const count = row?.['count'];\n\n if (typeof count !== 'number') throw new VaultError('SQLite storage returned an invalid count');\n\n return count;\n },\n async delete(table, key) {\n const live = getRecord(table, key) !== undefined;\n const columns = toKeyColumns(key);\n\n run(database, `DELETE FROM ${RECORDS_TABLE} WHERE namespace = ? AND table_name = ? AND key_tag = ?`, [\n name,\n table,\n columns.encoded,\n ]);\n\n return live;\n },\n async deleteMany(table, keys) {\n let deleted = 0;\n\n for (const key of keys) {\n if (await core.delete(table, key)) deleted += 1;\n }\n\n return deleted;\n },\n async get(table, key) {\n return getRecord(table, key);\n },\n async getAll(table) {\n return getAllLive<RecordOf<S, typeof table>>(database, name, table);\n },\n async getAllKeys(table) {\n return (await core.getAll(table)).map((record) => getRecordKey(schema, table, record));\n },\n async getByKeyRange(table, range) {\n if (range.type === 'eq')\n return getAllLive<RecordOf<S, typeof table>>(database, name, table, ' AND key_tag = ?', [\n toKeyColumns(range.value as KeyOf<S, typeof table>).encoded,\n ]);\n\n if (range.type === 'between') {\n if (\n typeof range.lower !== typeof range.upper ||\n (typeof range.lower !== 'number' && typeof range.lower !== 'string')\n ) {\n return getAllLive<RecordOf<S, typeof table>>(database, name, table);\n }\n\n const column = typeof range.lower === 'number' ? 'key_number' : 'key_string';\n\n return getAllLive<RecordOf<S, typeof table>>(\n database,\n name,\n table,\n ` AND key_kind = ? AND ${column} >= ? AND ${column} <= ?`,\n [typeof range.lower === 'number' ? 'number' : 'string', range.lower, range.upper as string | number],\n );\n }\n\n return getAllLive<RecordOf<S, typeof table>>(\n database,\n name,\n table,\n ' AND key_kind = ? AND substr(key_string, 1, length(?)) = ?',\n ['string', range.prefix, range.prefix],\n );\n },\n async getMany(table, keys) {\n return keys.map((key) => getRecord(table, key));\n },\n async getRawCount(table) {\n const row = get(\n database,\n `SELECT COUNT(*) AS count FROM ${RECORDS_TABLE} WHERE namespace = ? AND table_name = ?`,\n [name, table],\n );\n const count = row?.['count'];\n\n if (typeof count !== 'number') throw new VaultError('SQLite storage returned an invalid count');\n\n return count;\n },\n async has(table, key) {\n return getRecord(table, key) !== undefined;\n },\n async pruneAllExpired() {\n const results: Record<string, number> = {};\n\n for (const table of Object.keys(schema)) {\n results[table] = await core.pruneExpiredInTable(table as K);\n }\n\n return results;\n },\n async pruneExpiredInTable(table) {\n const before = await core.getRawCount!(table);\n\n deleteExpired(database, name, table);\n\n return before - (await core.getRawCount!(table));\n },\n async put(table, value, ttl) {\n const key = getRecordKey(schema, table, value);\n const columns = toKeyColumns(key);\n const expiresAt = ttl === undefined ? null : Date.now() + ttl;\n\n run(\n database,\n `INSERT INTO ${RECORDS_TABLE}\n (namespace, table_name, key_tag, key_kind, key_number, key_string, value_json, expires_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(namespace, table_name, key_tag) DO UPDATE SET\n key_kind = excluded.key_kind,\n key_number = excluded.key_number,\n key_string = excluded.key_string,\n value_json = excluded.value_json,\n expires_at = excluded.expires_at`,\n [name, table, columns.encoded, columns.kind, columns.number, columns.string, encodeJson(value), expiresAt],\n );\n },\n async putAll(table, values, ttl) {\n for (const value of values) {\n await core.put(table, value, ttl);\n }\n },\n };\n\n return core;\n}\n\n/**\n * Creates a SQLite-backed Vault store. The connection is caller-owned unless\n * `closeOnDispose` is explicitly enabled.\n */\nexport function createSQLite<S extends AnySchema>(options: SQLiteVaultOptions<S>): SQLiteVaultStore<S> {\n const { closeOnDispose = false, database, logger, name, onMetrics, schema, validators } = options;\n\n assertName(name);\n\n const state = getConnectionState(database);\n const namespaceReady = state.executor.run(async () => {\n await state.initialized;\n initializeNamespace(database, name);\n });\n let ownListener: ConnectionListener | undefined;\n\n const directCore = createDirectCore(database, name, schema);\n const withConnection = <T>(work: () => Promise<T>): Promise<T> =>\n state.executor.run(async () => {\n await state.initialized;\n await namespaceReady;\n\n return work();\n });\n const guardedCore = Object.fromEntries(\n Object.entries(directCore).map(([method, implementation]) => [\n method,\n (...arguments_: unknown[]) => {\n if (state.batchActive) {\n throw new VaultError(\n 'cannot call a SQLite store sharing this connection from batch(); use the transaction context instead',\n );\n }\n\n return withConnection(() => (implementation as (...args: unknown[]) => Promise<unknown>)(...arguments_));\n },\n ]),\n ) as StorageBackend<S>;\n\n let batch: BatchImpl<S> | undefined;\n const adapter = buildAdapterOps(schema, guardedCore, {\n logger,\n onCrossTabMessage(notify) {\n const listener: ConnectionListener = (eventName, table) => {\n if (eventName === name && Object.hasOwn(schema, table)) notify(table as keyof S & string);\n };\n\n ownListener = listener;\n state.listeners.add(listener);\n\n return () => {\n state.listeners.delete(listener);\n\n if (ownListener === listener) ownListener = undefined;\n };\n },\n onMetrics,\n onMutation(table) {\n for (const listener of state.listeners) {\n if (listener !== ownListener) listener(name, table);\n }\n },\n onTransactions: (deps) => {\n batch = async (tables, fn) => {\n assertBatchTables(tables);\n\n if (state.batchActive) {\n throw new VaultError(\n 'cannot call a SQLite store sharing this connection from batch(); use the transaction context instead',\n );\n }\n\n return state.executor.run(async () => {\n await state.initialized;\n await namespaceReady;\n\n const dirtyTables = new Set<keyof S & string>();\n const txCore = createDirectCore<S, keyof S & string>(database, name, schema);\n const tx = buildTxContext(\n schema,\n txCore,\n (table) => dirtyTables.add(table),\n deps.validate,\n new Set<string>(tables),\n );\n let transactionStarted = false;\n let committed = false;\n\n state.batchActive = true;\n\n try {\n database.exec('BEGIN IMMEDIATE');\n transactionStarted = true;\n\n const result = await fn(tx);\n\n database.exec('COMMIT');\n committed = true;\n\n for (const table of dirtyTables) {\n deps.notifyMutation(table);\n }\n\n return result;\n } catch (error) {\n if (transactionStarted && !committed) {\n try {\n database.exec('ROLLBACK');\n } catch (rollbackError) {\n throw new VaultError('SQLite batch rollback failed', { cause: rollbackError });\n }\n }\n\n throw error;\n } finally {\n state.batchActive = false;\n }\n });\n };\n },\n schema,\n validators,\n });\n\n if (!batch) throw new VaultError('SQLite transaction capability was not initialized');\n\n const store: SQLiteVaultStore<S> = {\n ...adapter,\n batch,\n iterate<K extends keyof S & string>(table: K): AsyncIterable<RecordOf<S, K>> {\n if (adapter.disposed) throw new VaultDisposedError(`\"${name}\" is disposed`);\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<RecordOf<S, K>> {\n let completed = false;\n let lastRowId = 0;\n let lease: (() => void) | undefined;\n let rows: readonly SQLiteRow[] = [];\n let index = 0;\n\n const release = (): void => {\n lease?.();\n lease = undefined;\n };\n const loadNextPage = (): void => {\n rows = all(\n database,\n `SELECT rowid AS row_id, expires_at, value_json\n FROM ${RECORDS_TABLE}\n WHERE namespace = ? AND table_name = ? AND rowid > ?\n ORDER BY rowid\n LIMIT ?`,\n [name, table, lastRowId, ITERATION_PAGE_SIZE],\n );\n index = 0;\n };\n\n return {\n async next(): Promise<IteratorResult<RecordOf<S, K>>> {\n if (completed) return { done: true, value: undefined };\n\n if (state.batchActive) {\n throw new VaultError(\n 'cannot call a SQLite store sharing this connection from batch(); use the transaction context instead',\n );\n }\n\n try {\n if (!lease) {\n lease = await state.executor.acquire();\n await state.initialized;\n await namespaceReady;\n }\n\n while (true) {\n if (index >= rows.length) {\n loadNextPage();\n\n if (rows.length === 0) {\n completed = true;\n release();\n\n return { done: true, value: undefined };\n }\n }\n\n const row = rows[index++];\n const stored = getStoredRow(row);\n\n lastRowId = stored.rowId;\n\n const value = decodeLiveRecord<RecordOf<S, K>>(database, row);\n\n if (value !== undefined) return { done: false, value };\n }\n } catch (error) {\n completed = true;\n release();\n\n throw error;\n }\n },\n async return(value?: unknown): Promise<IteratorResult<RecordOf<S, K>>> {\n completed = true;\n release();\n\n return { done: true, value: value as RecordOf<S, K> };\n },\n async throw(error?: unknown): Promise<IteratorResult<RecordOf<S, K>>> {\n completed = true;\n release();\n\n throw error;\n },\n };\n },\n };\n },\n };\n\n if (closeOnDispose) {\n const dispose = store.dispose.bind(store);\n let closePromise: Promise<void> | undefined;\n\n store.dispose = async (): Promise<void> => {\n await dispose();\n closePromise ??= state.executor.run(() => database.close?.());\n await closePromise;\n };\n store[Symbol.asyncDispose] = async (): Promise<void> => {\n await store.dispose();\n };\n }\n\n return store;\n}\n"],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { AnySchema, BaseAdapterOptions, IterableVaultStore, TransactionalVaultStore } from '../types';
2
+ export type SQLiteParameter = null | number | string;
3
+ type SQLiteRow = Record<string, unknown>;
4
+ /**
5
+ * A synchronous SQLite statement with positional parameter binding.
6
+ *
7
+ * Adapters for drivers whose native statement API differs can implement this
8
+ * structural protocol without adding a runtime dependency to Vault.
9
+ */
10
+ export interface SQLiteStatement {
11
+ all(...parameters: SQLiteParameter[]): readonly SQLiteRow[];
12
+ finalize?(): void;
13
+ get(...parameters: SQLiteParameter[]): SQLiteRow | undefined;
14
+ run(...parameters: SQLiteParameter[]): unknown;
15
+ }
16
+ /**
17
+ * A runtime-neutral synchronous SQLite connection.
18
+ *
19
+ * Node's `DatabaseSync`, Bun's `Database`, and Deno's `@db/sqlite` `Database`
20
+ * satisfy this protocol directly.
21
+ */
22
+ export interface SQLiteDatabase {
23
+ close?(): void;
24
+ exec(sql: string): void;
25
+ prepare(sql: string): SQLiteStatement;
26
+ }
27
+ export type SQLiteVaultOptions<S extends AnySchema> = BaseAdapterOptions<S> & {
28
+ /** Closes the caller-provided connection during store disposal when true. */
29
+ closeOnDispose?: boolean;
30
+ database: SQLiteDatabase;
31
+ /** Namespace that isolates this store's records in the shared connection. */
32
+ name: string;
33
+ };
34
+ /** SQLite provides atomic batches and lazy keyset-paginated iteration. */
35
+ export interface SQLiteVaultStore<S extends AnySchema> extends TransactionalVaultStore<S>, IterableVaultStore<S> {
36
+ }
37
+ /**
38
+ * Creates a SQLite-backed Vault store. The connection is caller-owned unless
39
+ * `closeOnDispose` is explicitly enabled.
40
+ */
41
+ export declare function createSQLite<S extends AnySchema>(options: SQLiteVaultOptions<S>): SQLiteVaultStore<S>;
42
+ export {};
43
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/adapters/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,kBAAkB,EAClB,kBAAkB,EAGlB,uBAAuB,EACxB,MAAM,UAAU,CAAC;AAalB,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AACrD,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,GAAG,UAAU,EAAE,eAAe,EAAE,GAAG,SAAS,SAAS,EAAE,CAAC;IAC5D,QAAQ,CAAC,IAAI,IAAI,CAAC;IAClB,GAAG,CAAC,GAAG,UAAU,EAAE,eAAe,EAAE,GAAG,SAAS,GAAG,SAAS,CAAC;IAC7D,GAAG,CAAC,GAAG,UAAU,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;CAChD;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,IAAI,IAAI,CAAC;IACf,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;CACvC;AAED,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,SAAS,IAAI,kBAAkB,CAAC,CAAC,CAAC,GAAG;IAC5E,6EAA6E;IAC7E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,SAAS,CAAE,SAAQ,uBAAuB,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC;CAAG;AAgbnH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAuOrG"}