@mstone6969/vault 0.1.0 → 0.2.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 +38 -4
- package/dist/index.js +4 -3
- package/dist/index.js.map +4 -4
- package/dist/stores/memory.d.ts +1 -0
- package/dist/stores/memory.d.ts.map +1 -1
- package/dist/stores/sqlite.d.ts +1 -0
- package/dist/stores/sqlite.d.ts.map +1 -1
- package/dist/stores/sqlite.js +11 -4
- package/dist/stores/sqlite.js.map +3 -3
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vault.d.ts +8 -2
- package/dist/vault.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ const vault = new Vault({
|
|
|
21
21
|
await vault.put("alice", "stripe_key", "sk_live_…")
|
|
22
22
|
|
|
23
23
|
await vault.list("alice")
|
|
24
|
-
// [{ owner: "alice", name: "stripe_key", createdAt: …, updatedAt: … }]
|
|
24
|
+
// [{ owner: "alice", name: "stripe_key", metadata: {}, createdAt: …, updatedAt: … }]
|
|
25
25
|
// — no value, ever
|
|
26
26
|
|
|
27
27
|
await vault.open("alice", "stripe_key") // "sk_live_…"
|
|
@@ -30,6 +30,27 @@ await vault.open("alice", "stripe_key") // "sk_live_…"
|
|
|
30
30
|
Everything is scoped by an owner, so one vault serves many accounts and two
|
|
31
31
|
people can both keep a `token` without seeing each other's.
|
|
32
32
|
|
|
33
|
+
## Metadata
|
|
34
|
+
|
|
35
|
+
A value is sealed, but the facts *about* it usually should not be. `put` takes
|
|
36
|
+
a map of non-secret strings that `list` returns as-is:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
await vault.put("alice", "deploy", privateKey, {
|
|
40
|
+
kind: "ssh",
|
|
41
|
+
publicKey: "ssh-ed25519 AAAA…",
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
await vault.list("alice")
|
|
45
|
+
// [{ name: "deploy", metadata: { kind: "ssh", publicKey: "ssh-ed25519 AAAA…" }, … }]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
That is what lets a listing say what something is — which login a password
|
|
49
|
+
belongs to, which public key pairs with a sealed private one — without opening
|
|
50
|
+
anything. Replacing a value replaces its metadata too.
|
|
51
|
+
|
|
52
|
+
It is stored in the clear. Put nothing in it you would not show.
|
|
53
|
+
|
|
33
54
|
## References
|
|
34
55
|
|
|
35
56
|
Configuration can name a secret instead of holding one. `resolve` swaps
|
|
@@ -68,7 +89,12 @@ methods, all scoped by owner, all dealing in sealed strings and never plaintext:
|
|
|
68
89
|
type VaultStore = {
|
|
69
90
|
get(owner: string, name: string): Promise<SecretRecord | null>
|
|
70
91
|
list(owner: string): Promise<SecretRecord[]>
|
|
71
|
-
put(record: {
|
|
92
|
+
put(record: {
|
|
93
|
+
owner: string
|
|
94
|
+
name: string
|
|
95
|
+
sealed: string
|
|
96
|
+
metadata: Record<string, string>
|
|
97
|
+
}): Promise<SecretRecord>
|
|
72
98
|
remove(owner: string, name: string): Promise<boolean>
|
|
73
99
|
}
|
|
74
100
|
```
|
|
@@ -90,8 +116,8 @@ The key never leaves your process, and the package never writes it anywhere.
|
|
|
90
116
|
| | |
|
|
91
117
|
| --- | --- |
|
|
92
118
|
| `new Vault({ key, store, prefix? })` | Key is base64 or an imported `CryptoKey` |
|
|
93
|
-
| `put(owner, name, value)` | Store or replace; returns a summary, no value |
|
|
94
|
-
| `list(owner)` | Names and
|
|
119
|
+
| `put(owner, name, value, metadata?)` | Store or replace; returns a summary, no value |
|
|
120
|
+
| `list(owner)` | Names, dates and metadata, sorted by name |
|
|
95
121
|
| `open(owner, name)` | The plaintext — keep it in memory |
|
|
96
122
|
| `has(owner, name)` | Whether it exists |
|
|
97
123
|
| `remove(owner, name)` | `false` if there was nothing to remove |
|
|
@@ -102,6 +128,14 @@ Names are up to 64 characters of letters, numbers, dot, dash or underscore.
|
|
|
102
128
|
Bad input throws `VaultError` (with a suggested HTTP `status`); key and
|
|
103
129
|
ciphertext problems throw `VaultKeyError`.
|
|
104
130
|
|
|
131
|
+
## Versions
|
|
132
|
+
|
|
133
|
+
**0.2.0** — `put` takes optional non-secret `metadata`, and `SecretRecord`
|
|
134
|
+
carries it. Existing calls keep working: metadata defaults to `{}`. A
|
|
135
|
+
`SqliteStore` table written by 0.1.0 gains the column on open.
|
|
136
|
+
|
|
137
|
+
**0.1.0** — first release.
|
|
138
|
+
|
|
105
139
|
## Development
|
|
106
140
|
|
|
107
141
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -63,7 +63,7 @@ class Vault {
|
|
|
63
63
|
const records = await this.store.list(owner);
|
|
64
64
|
return records.map(({ sealed: _sealed, ...summary }) => summary).sort((a, b) => a.name.localeCompare(b.name));
|
|
65
65
|
}
|
|
66
|
-
async put(owner, name, value) {
|
|
66
|
+
async put(owner, name, value, metadata = {}) {
|
|
67
67
|
const clean = this.checkName(name);
|
|
68
68
|
if (!value)
|
|
69
69
|
throw new VaultError("A secret needs a value.");
|
|
@@ -71,7 +71,8 @@ class Vault {
|
|
|
71
71
|
const { sealed: _sealed, ...summary } = await this.store.put({
|
|
72
72
|
owner,
|
|
73
73
|
name: clean,
|
|
74
|
-
sealed
|
|
74
|
+
sealed,
|
|
75
|
+
metadata
|
|
75
76
|
});
|
|
76
77
|
return summary;
|
|
77
78
|
}
|
|
@@ -144,5 +145,5 @@ export {
|
|
|
144
145
|
DEFAULT_PREFIX
|
|
145
146
|
};
|
|
146
147
|
|
|
147
|
-
//# debugId=
|
|
148
|
+
//# debugId=75E38B9D900E6BB164756E2164756E21
|
|
148
149
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/** A caller mistake: a bad name, an empty value, a missing secret. */\nexport class VaultError extends Error {\n constructor(\n message: string,\n /** Suggested HTTP status, for callers putting this behind an API. */\n readonly status: number = 422\n ) {\n super(message)\n this.name = \"VaultError\"\n }\n}\n\n/** The key is the wrong shape, or cannot open what it was given. */\nexport class VaultKeyError extends VaultError {\n constructor(message: string) {\n super(message, 500)\n this.name = \"VaultKeyError\"\n }\n}\n",
|
|
6
6
|
"import { VaultKeyError } from \"./errors\"\n\n/**\n * AES-256-GCM. Sealed values are `iv:payload`, both base64: the IV is fresh per\n * write, and GCM's tag means a tampered value fails to open rather than\n * decrypting to something wrong.\n */\nconst IV_BYTES = 12\nconst KEY_BYTES = 32\n\n/** A new random key, base64 encoded — store it somewhere safe. */\nexport function generateKey(): string {\n return Buffer.from(crypto.getRandomValues(new Uint8Array(KEY_BYTES))).toString(\"base64\")\n}\n\n/** Imports a base64 key produced by `generateKey`. */\nexport async function importKey(base64Key: string): Promise<CryptoKey> {\n const raw = Buffer.from(base64Key, \"base64\")\n if (raw.length !== KEY_BYTES) {\n throw new VaultKeyError(\n `A vault key must be ${KEY_BYTES} bytes, base64 encoded — got ${raw.length}.`\n )\n }\n return crypto.subtle.importKey(\"raw\", raw, \"AES-GCM\", false, [\"encrypt\", \"decrypt\"])\n}\n\nexport async function seal(key: CryptoKey, plaintext: string): Promise<string> {\n const iv = crypto.getRandomValues(new Uint8Array(IV_BYTES))\n const sealed = await crypto.subtle.encrypt(\n { name: \"AES-GCM\", iv },\n key,\n new TextEncoder().encode(plaintext)\n )\n return `${Buffer.from(iv).toString(\"base64\")}:${Buffer.from(sealed).toString(\"base64\")}`\n}\n\nexport async function open(key: CryptoKey, sealed: string): Promise<string> {\n const [iv, payload] = sealed.split(\":\")\n if (!iv || !payload) {\n throw new VaultKeyError(\"A sealed value must look like iv:payload.\")\n }\n\n try {\n const opened = await crypto.subtle.decrypt(\n { name: \"AES-GCM\", iv: Buffer.from(iv, \"base64\") },\n key,\n Buffer.from(payload, \"base64\")\n )\n return new TextDecoder().decode(opened)\n } catch {\n throw new VaultKeyError(\n \"That value could not be opened — wrong key, or it has been altered.\"\n )\n }\n}\n",
|
|
7
|
-
"import { importKey, open, seal } from \"./crypto\"\nimport { VaultError } from \"./errors\"\nimport type { SecretSummary, VaultStore } from \"./types\"\n\n/** How a stored value is referenced from configuration. */\nexport const DEFAULT_PREFIX = \"@vault:\"\n\nconst NAME_PATTERN = /^[A-Za-z0-9_.-]{1,64}$/\n\nexport type VaultOptions = {\n /** Base64 key from `generateKey()`, or an already imported CryptoKey. */\n key: string | CryptoKey\n store: VaultStore\n /** Reference prefix, `@vault:` unless you say otherwise. */\n prefix?: string\n}\n\n/**\n * A write-only credential store: values go in, and only `open` and `resolve`\n * take them out again. Listing never exposes a value, so a vault can back an\n * API without a reveal endpoint.\n */\nexport class Vault {\n private readonly key: Promise<CryptoKey>\n private readonly store: VaultStore\n readonly prefix: string\n\n constructor({ key, store, prefix = DEFAULT_PREFIX }: VaultOptions) {\n this.key = typeof key === \"string\" ? importKey(key) : Promise.resolve(key)\n this.store = store\n this.prefix = prefix\n }\n\n /** Names and dates for one owner. Never values. */\n async list(owner: string): Promise<SecretSummary[]> {\n const records = await this.store.list(owner)\n return records\n .map(({ sealed: _sealed, ...summary }) => summary)\n .sort((a, b) => a.name.localeCompare(b.name))\n }\n\n
|
|
8
|
-
"import type { SecretRecord, VaultStore } from \"../types\"\n\n/** Keeps sealed values in a Map. Handy for tests and short-lived processes. */\nexport class MemoryStore implements VaultStore {\n private readonly records = new Map<string, SecretRecord>()\n\n private static key(owner: string, name: string): string {\n return `${owner} ${name}`\n }\n\n async get(owner: string, name: string): Promise<SecretRecord | null> {\n return this.records.get(MemoryStore.key(owner, name)) ?? null\n }\n\n async list(owner: string): Promise<SecretRecord[]> {\n return [...this.records.values()].filter((record) => record.owner === owner)\n }\n\n async put(record: {\n owner: string\n name: string\n sealed: string\n }): Promise<SecretRecord> {\n const key = MemoryStore.key(record.owner, record.name)\n const now = new Date()\n const stored: SecretRecord = {\n ...record,\n // Replacing a value keeps the date it was first stored.\n createdAt: this.records.get(key)?.createdAt ?? now,\n updatedAt: now,\n }\n this.records.set(key, stored)\n return stored\n }\n\n async remove(owner: string, name: string): Promise<boolean> {\n return this.records.delete(MemoryStore.key(owner, name))\n }\n}\n"
|
|
7
|
+
"import { importKey, open, seal } from \"./crypto\"\nimport { VaultError } from \"./errors\"\nimport type { SecretSummary, VaultStore } from \"./types\"\n\n/** How a stored value is referenced from configuration. */\nexport const DEFAULT_PREFIX = \"@vault:\"\n\nconst NAME_PATTERN = /^[A-Za-z0-9_.-]{1,64}$/\n\nexport type VaultOptions = {\n /** Base64 key from `generateKey()`, or an already imported CryptoKey. */\n key: string | CryptoKey\n store: VaultStore\n /** Reference prefix, `@vault:` unless you say otherwise. */\n prefix?: string\n}\n\n/**\n * A write-only credential store: values go in, and only `open` and `resolve`\n * take them out again. Listing never exposes a value, so a vault can back an\n * API without a reveal endpoint.\n */\nexport class Vault {\n private readonly key: Promise<CryptoKey>\n private readonly store: VaultStore\n readonly prefix: string\n\n constructor({ key, store, prefix = DEFAULT_PREFIX }: VaultOptions) {\n this.key = typeof key === \"string\" ? importKey(key) : Promise.resolve(key)\n this.store = store\n this.prefix = prefix\n }\n\n /** Names and dates for one owner. Never values. */\n async list(owner: string): Promise<SecretSummary[]> {\n const records = await this.store.list(owner)\n return records\n .map(({ sealed: _sealed, ...summary }) => summary)\n .sort((a, b) => a.name.localeCompare(b.name))\n }\n\n /**\n * Stores a value, replacing whatever was under that name.\n *\n * `metadata` is kept in the clear and comes back from `list`, so it must\n * hold nothing secret — a credential's kind, or the username it belongs to,\n * not the password.\n */\n async put(\n owner: string,\n name: string,\n value: string,\n metadata: Record<string, string> = {}\n ): Promise<SecretSummary> {\n const clean = this.checkName(name)\n if (!value) throw new VaultError(\"A secret needs a value.\")\n\n const sealed = await seal(await this.key, value)\n const { sealed: _sealed, ...summary } = await this.store.put({\n owner,\n name: clean,\n sealed,\n metadata,\n })\n return summary\n }\n\n /** True when the owner has a secret under that name. */\n async has(owner: string, name: string): Promise<boolean> {\n return (await this.store.get(owner, this.checkName(name))) !== null\n }\n\n /** Removes a secret, returning false if it wasn't there. */\n remove(owner: string, name: string): Promise<boolean> {\n return this.store.remove(owner, this.checkName(name))\n }\n\n /**\n * Reads one value back. The only way plaintext leaves the vault — keep it\n * in memory and out of logs and responses.\n */\n async open(owner: string, name: string): Promise<string> {\n const record = await this.store.get(owner, this.checkName(name))\n if (!record) throw new VaultError(`No secret named \"${name}\" in the vault.`, 404)\n return open(await this.key, record.sealed)\n }\n\n /**\n * Substitutes `@vault:<name>` references in a set of values — an\n * environment, a config object — leaving everything else alone.\n *\n * A reference to a secret that isn't there throws: running with a blank\n * credential is worse than not running.\n */\n async resolve(\n owner: string,\n values: Record<string, string>\n ): Promise<Record<string, string>> {\n const references = Object.entries(values).filter(([, value]) =>\n value.startsWith(this.prefix)\n )\n if (references.length === 0) return values\n\n const resolved = { ...values }\n for (const [key, value] of references) {\n resolved[key] = await this.open(owner, value.slice(this.prefix.length).trim())\n }\n return resolved\n }\n\n private checkName(name: string): string {\n const clean = String(name ?? \"\").trim()\n if (!NAME_PATTERN.test(clean)) {\n throw new VaultError(\n \"A name can be up to 64 characters: letters, numbers, dot, dash or underscore.\"\n )\n }\n return clean\n }\n}\n",
|
|
8
|
+
"import type { SecretRecord, VaultStore } from \"../types\"\n\n/** Keeps sealed values in a Map. Handy for tests and short-lived processes. */\nexport class MemoryStore implements VaultStore {\n private readonly records = new Map<string, SecretRecord>()\n\n private static key(owner: string, name: string): string {\n return `${owner} ${name}`\n }\n\n async get(owner: string, name: string): Promise<SecretRecord | null> {\n return this.records.get(MemoryStore.key(owner, name)) ?? null\n }\n\n async list(owner: string): Promise<SecretRecord[]> {\n return [...this.records.values()].filter((record) => record.owner === owner)\n }\n\n async put(record: {\n owner: string\n name: string\n sealed: string\n metadata: Record<string, string>\n }): Promise<SecretRecord> {\n const key = MemoryStore.key(record.owner, record.name)\n const now = new Date()\n const stored: SecretRecord = {\n ...record,\n // Replacing a value keeps the date it was first stored.\n createdAt: this.records.get(key)?.createdAt ?? now,\n updatedAt: now,\n }\n this.records.set(key, stored)\n return stored\n }\n\n async remove(owner: string, name: string): Promise<boolean> {\n return this.records.delete(MemoryStore.key(owner, name))\n }\n}\n"
|
|
9
9
|
],
|
|
10
|
-
"mappings": ";AACO,MAAM,mBAAmB,MAAM;AAAA,EAIrB;AAAA,EAHb,WAAW,CACP,SAES,SAAiB,KAC5B;AAAA,IACE,MAAM,OAAO;AAAA,IAFJ;AAAA,IAGT,KAAK,OAAO;AAAA;AAEpB;AAAA;AAGO,MAAM,sBAAsB,WAAW;AAAA,EAC1C,WAAW,CAAC,SAAiB;AAAA,IACzB,MAAM,SAAS,GAAG;AAAA,IAClB,KAAK,OAAO;AAAA;AAEpB;;;ACXA,IAAM,WAAW;AACjB,IAAM,YAAY;AAGX,SAAS,WAAW,GAAW;AAAA,EAClC,OAAO,OAAO,KAAK,OAAO,gBAAgB,IAAI,WAAW,SAAS,CAAC,CAAC,EAAE,SAAS,QAAQ;AAAA;AAI3F,eAAsB,SAAS,CAAC,WAAuC;AAAA,EACnE,MAAM,MAAM,OAAO,KAAK,WAAW,QAAQ;AAAA,EAC3C,IAAI,IAAI,WAAW,WAAW;AAAA,IAC1B,MAAM,IAAI,cACN,uBAAuB,yCAAwC,IAAI,SACvE;AAAA,EACJ;AAAA,EACA,OAAO,OAAO,OAAO,UAAU,OAAO,KAAK,WAAW,OAAO,CAAC,WAAW,SAAS,CAAC;AAAA;AAGvF,eAAsB,IAAI,CAAC,KAAgB,WAAoC;AAAA,EAC3E,MAAM,KAAK,OAAO,gBAAgB,IAAI,WAAW,QAAQ,CAAC;AAAA,EAC1D,MAAM,SAAS,MAAM,OAAO,OAAO,QAC/B,EAAE,MAAM,WAAW,GAAG,GACtB,KACA,IAAI,YAAY,EAAE,OAAO,SAAS,CACtC;AAAA,EACA,OAAO,GAAG,OAAO,KAAK,EAAE,EAAE,SAAS,QAAQ,KAAK,OAAO,KAAK,MAAM,EAAE,SAAS,QAAQ;AAAA;AAGzF,eAAsB,IAAI,CAAC,KAAgB,QAAiC;AAAA,EACxE,OAAO,IAAI,WAAW,OAAO,MAAM,GAAG;AAAA,EACtC,IAAI,CAAC,MAAM,CAAC,SAAS;AAAA,IACjB,MAAM,IAAI,cAAc,2CAA2C;AAAA,EACvE;AAAA,EAEA,IAAI;AAAA,IACA,MAAM,SAAS,MAAM,OAAO,OAAO,QAC/B,EAAE,MAAM,WAAW,IAAI,OAAO,KAAK,IAAI,QAAQ,EAAE,GACjD,KACA,OAAO,KAAK,SAAS,QAAQ,CACjC;AAAA,IACA,OAAO,IAAI,YAAY,EAAE,OAAO,MAAM;AAAA,IACxC,MAAM;AAAA,IACJ,MAAM,IAAI,cACN,qEACJ;AAAA;AAAA;;;AC/CD,IAAM,iBAAiB;AAE9B,IAAM,eAAe;AAAA;AAed,MAAM,MAAM;AAAA,EACE;AAAA,EACA;AAAA,EACR;AAAA,EAET,WAAW,GAAG,KAAK,OAAO,SAAS,kBAAgC;AAAA,IAC/D,KAAK,MAAM,OAAO,QAAQ,WAAW,UAAU,GAAG,IAAI,QAAQ,QAAQ,GAAG;AAAA,IACzE,KAAK,QAAQ;AAAA,IACb,KAAK,SAAS;AAAA;AAAA,OAIZ,KAAI,CAAC,OAAyC;AAAA,IAChD,MAAM,UAAU,MAAM,KAAK,MAAM,KAAK,KAAK;AAAA,IAC3C,OAAO,QACF,IAAI,GAAG,QAAQ,YAAY,cAAc,OAAO,EAChD,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA;AAAA,
|
|
11
|
-
"debugId": "
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "75E38B9D900E6BB164756E2164756E21",
|
|
12
12
|
"names": []
|
|
13
13
|
}
|
package/dist/stores/memory.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/stores/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAExD,+EAA+E;AAC/E,qBAAa,WAAY,YAAW,UAAU;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAE1D,OAAO,CAAC,MAAM,CAAC,GAAG;IAIZ,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAI9D,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAI5C,GAAG,CAAC,MAAM,EAAE;QACd,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/stores/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAExD,+EAA+E;AAC/E,qBAAa,WAAY,YAAW,UAAU;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAE1D,OAAO,CAAC,MAAM,CAAC,GAAG;IAIZ,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAI9D,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAI5C,GAAG,CAAC,MAAM,EAAE;QACd,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACnC,GAAG,OAAO,CAAC,YAAY,CAAC;IAanB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG9D"}
|
package/dist/stores/sqlite.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare class SqliteStore implements VaultStore {
|
|
|
15
15
|
owner: string;
|
|
16
16
|
name: string;
|
|
17
17
|
sealed: string;
|
|
18
|
+
metadata: Record<string, string>;
|
|
18
19
|
}): Promise<SecretRecord>;
|
|
19
20
|
remove(owner: string, name: string): Promise<boolean>;
|
|
20
21
|
/** Closes the underlying database. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/stores/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/stores/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAWxD;;;GAGG;AACH,qBAAa,WAAY,YAAW,UAAU;IAC1C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAU;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;gBAElB,QAAQ,GAAE,MAAM,GAAG,QAAqB,EAAE,KAAK,SAAkB;IAuB7E,OAAO,CAAC,MAAM,CAAC,QAAQ;IAWjB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAS9D,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAO5C,GAAG,CAAC,MAAM,EAAE;QACd,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACnC,GAAG,OAAO,CAAC,YAAY,CAAC;IAyBnB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS3D,sCAAsC;IACtC,KAAK,IAAI,IAAI;CAGhB"}
|
package/dist/stores/sqlite.js
CHANGED
|
@@ -12,16 +12,22 @@ class SqliteStore {
|
|
|
12
12
|
owner TEXT NOT NULL,
|
|
13
13
|
name TEXT NOT NULL,
|
|
14
14
|
sealed TEXT NOT NULL,
|
|
15
|
+
metadata TEXT,
|
|
15
16
|
created_at INTEGER NOT NULL,
|
|
16
17
|
updated_at INTEGER NOT NULL,
|
|
17
18
|
PRIMARY KEY (owner, name)
|
|
18
19
|
)`);
|
|
20
|
+
const columns = this.db.query(`PRAGMA table_info(${this.table})`).all();
|
|
21
|
+
if (!columns.some((column) => column.name === "metadata")) {
|
|
22
|
+
this.db.run(`ALTER TABLE ${this.table} ADD COLUMN metadata TEXT`);
|
|
23
|
+
}
|
|
19
24
|
}
|
|
20
25
|
static toRecord(row) {
|
|
21
26
|
return {
|
|
22
27
|
owner: row.owner,
|
|
23
28
|
name: row.name,
|
|
24
29
|
sealed: row.sealed,
|
|
30
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : {},
|
|
25
31
|
createdAt: new Date(row.created_at),
|
|
26
32
|
updatedAt: new Date(row.updated_at)
|
|
27
33
|
};
|
|
@@ -35,10 +41,11 @@ class SqliteStore {
|
|
|
35
41
|
}
|
|
36
42
|
async put(record) {
|
|
37
43
|
const now = Date.now();
|
|
38
|
-
this.db.query(`INSERT INTO ${this.table} (owner, name, sealed, created_at, updated_at)
|
|
39
|
-
VALUES (?, ?, ?, ?, ?)
|
|
44
|
+
this.db.query(`INSERT INTO ${this.table} (owner, name, sealed, metadata, created_at, updated_at)
|
|
45
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
40
46
|
ON CONFLICT(owner, name)
|
|
41
|
-
DO UPDATE SET sealed = excluded.sealed,
|
|
47
|
+
DO UPDATE SET sealed = excluded.sealed, metadata = excluded.metadata,
|
|
48
|
+
updated_at = excluded.updated_at`).run(record.owner, record.name, record.sealed, JSON.stringify(record.metadata), now, now);
|
|
42
49
|
const stored = await this.get(record.owner, record.name);
|
|
43
50
|
if (!stored)
|
|
44
51
|
throw new Error("The secret vanished immediately after writing it.");
|
|
@@ -59,5 +66,5 @@ export {
|
|
|
59
66
|
SqliteStore
|
|
60
67
|
};
|
|
61
68
|
|
|
62
|
-
//# debugId=
|
|
69
|
+
//# debugId=6FCBF9C9F6B3EDC164756E2164756E21
|
|
63
70
|
//# sourceMappingURL=sqlite.js.map
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/stores/sqlite.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { Database } from \"bun:sqlite\"\nimport type { SecretRecord, VaultStore } from \"../types\"\n\ntype Row = {\n owner: string\n name: string\n sealed: string\n created_at: number\n updated_at: number\n}\n\n/**\n * Keeps sealed values in SQLite through `bun:sqlite`. Pass a file path,\n * \":memory:\", or a Database you already opened.\n */\nexport class SqliteStore implements VaultStore {\n private readonly db: Database\n private readonly table: string\n\n constructor(database: string | Database = \":memory:\", table = \"vault_secrets\") {\n this.db = typeof database === \"string\" ? new Database(database) : database\n this.table = table\n this.db.run(\n `CREATE TABLE IF NOT EXISTS ${this.table} (\n owner TEXT NOT NULL,\n name TEXT NOT NULL,\n sealed TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY (owner, name)\n )`\n )\n }\n\n private static toRecord(row: Row): SecretRecord {\n return {\n owner: row.owner,\n name: row.name,\n sealed: row.sealed,\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n }\n }\n\n async get(owner: string, name: string): Promise<SecretRecord | null> {\n const row = this.db\n .query<Row, [string, string]>(\n `SELECT * FROM ${this.table} WHERE owner = ? AND name = ?`\n )\n .get(owner, name)\n return row ? SqliteStore.toRecord(row) : null\n }\n\n async list(owner: string): Promise<SecretRecord[]> {\n return this.db\n .query<Row, [string]>(`SELECT * FROM ${this.table} WHERE owner = ?`)\n .all(owner)\n .map(SqliteStore.toRecord)\n }\n\n async put(record: {\n owner: string\n name: string\n sealed: string\n }): Promise<SecretRecord> {\n const now = Date.now()\n // Replacing a value keeps the row's original created_at.\n this.db\n .query(\n `INSERT INTO ${this.table} (owner, name, sealed, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(owner, name)\n DO UPDATE SET sealed = excluded.sealed, updated_at = excluded.updated_at`\n )\n .run(record.owner
|
|
5
|
+
"import { Database } from \"bun:sqlite\"\nimport type { SecretRecord, VaultStore } from \"../types\"\n\ntype Row = {\n owner: string\n name: string\n sealed: string\n metadata: string | null\n created_at: number\n updated_at: number\n}\n\n/**\n * Keeps sealed values in SQLite through `bun:sqlite`. Pass a file path,\n * \":memory:\", or a Database you already opened.\n */\nexport class SqliteStore implements VaultStore {\n private readonly db: Database\n private readonly table: string\n\n constructor(database: string | Database = \":memory:\", table = \"vault_secrets\") {\n this.db = typeof database === \"string\" ? new Database(database) : database\n this.table = table\n this.db.run(\n `CREATE TABLE IF NOT EXISTS ${this.table} (\n owner TEXT NOT NULL,\n name TEXT NOT NULL,\n sealed TEXT NOT NULL,\n metadata TEXT,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY (owner, name)\n )`\n )\n // A table written by an earlier version has no metadata column.\n const columns = this.db\n .query<{ name: string }, []>(`PRAGMA table_info(${this.table})`)\n .all()\n if (!columns.some((column) => column.name === \"metadata\")) {\n this.db.run(`ALTER TABLE ${this.table} ADD COLUMN metadata TEXT`)\n }\n }\n\n private static toRecord(row: Row): SecretRecord {\n return {\n owner: row.owner,\n name: row.name,\n sealed: row.sealed,\n metadata: row.metadata ? (JSON.parse(row.metadata) as Record<string, string>) : {},\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n }\n }\n\n async get(owner: string, name: string): Promise<SecretRecord | null> {\n const row = this.db\n .query<Row, [string, string]>(\n `SELECT * FROM ${this.table} WHERE owner = ? AND name = ?`\n )\n .get(owner, name)\n return row ? SqliteStore.toRecord(row) : null\n }\n\n async list(owner: string): Promise<SecretRecord[]> {\n return this.db\n .query<Row, [string]>(`SELECT * FROM ${this.table} WHERE owner = ?`)\n .all(owner)\n .map(SqliteStore.toRecord)\n }\n\n async put(record: {\n owner: string\n name: string\n sealed: string\n metadata: Record<string, string>\n }): Promise<SecretRecord> {\n const now = Date.now()\n // Replacing a value keeps the row's original created_at.\n this.db\n .query(\n `INSERT INTO ${this.table} (owner, name, sealed, metadata, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(owner, name)\n DO UPDATE SET sealed = excluded.sealed, metadata = excluded.metadata,\n updated_at = excluded.updated_at`\n )\n .run(\n record.owner,\n record.name,\n record.sealed,\n JSON.stringify(record.metadata),\n now,\n now\n )\n\n const stored = await this.get(record.owner, record.name)\n if (!stored) throw new Error(\"The secret vanished immediately after writing it.\")\n return stored\n }\n\n async remove(owner: string, name: string): Promise<boolean> {\n const existing = await this.get(owner, name)\n if (!existing) return false\n this.db\n .query(`DELETE FROM ${this.table} WHERE owner = ? AND name = ?`)\n .run(owner, name)\n return true\n }\n\n /** Closes the underlying database. */\n close(): void {\n this.db.close()\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;AAAA;AAAA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;AAAA;AAAA;AAgBO,MAAM,YAAkC;AAAA,EAC1B;AAAA,EACA;AAAA,EAEjB,WAAW,CAAC,WAA8B,YAAY,QAAQ,iBAAiB;AAAA,IAC3E,KAAK,KAAK,OAAO,aAAa,WAAW,IAAI,SAAS,QAAQ,IAAI;AAAA,IAClE,KAAK,QAAQ;AAAA,IACb,KAAK,GAAG,IACJ,8BAA8B,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cASvC;AAAA,IAEA,MAAM,UAAU,KAAK,GAChB,MAA4B,qBAAqB,KAAK,QAAQ,EAC9D,IAAI;AAAA,IACT,IAAI,CAAC,QAAQ,KAAK,CAAC,WAAW,OAAO,SAAS,UAAU,GAAG;AAAA,MACvD,KAAK,GAAG,IAAI,eAAe,KAAK,gCAAgC;AAAA,IACpE;AAAA;AAAA,SAGW,QAAQ,CAAC,KAAwB;AAAA,IAC5C,OAAO;AAAA,MACH,OAAO,IAAI;AAAA,MACX,MAAM,IAAI;AAAA,MACV,QAAQ,IAAI;AAAA,MACZ,UAAU,IAAI,WAAY,KAAK,MAAM,IAAI,QAAQ,IAA+B,CAAC;AAAA,MACjF,WAAW,IAAI,KAAK,IAAI,UAAU;AAAA,MAClC,WAAW,IAAI,KAAK,IAAI,UAAU;AAAA,IACtC;AAAA;AAAA,OAGE,IAAG,CAAC,OAAe,MAA4C;AAAA,IACjE,MAAM,MAAM,KAAK,GACZ,MACG,iBAAiB,KAAK,oCAC1B,EACC,IAAI,OAAO,IAAI;AAAA,IACpB,OAAO,MAAM,YAAY,SAAS,GAAG,IAAI;AAAA;AAAA,OAGvC,KAAI,CAAC,OAAwC;AAAA,IAC/C,OAAO,KAAK,GACP,MAAqB,iBAAiB,KAAK,uBAAuB,EAClE,IAAI,KAAK,EACT,IAAI,YAAY,QAAQ;AAAA;AAAA,OAG3B,IAAG,CAAC,QAKgB;AAAA,IACtB,MAAM,MAAM,KAAK,IAAI;AAAA,IAErB,KAAK,GACA,MACG,eAAe,KAAK;AAAA;AAAA;AAAA;AAAA,gEAKxB,EACC,IACG,OAAO,OACP,OAAO,MACP,OAAO,QACP,KAAK,UAAU,OAAO,QAAQ,GAC9B,KACA,GACJ;AAAA,IAEJ,MAAM,SAAS,MAAM,KAAK,IAAI,OAAO,OAAO,OAAO,IAAI;AAAA,IACvD,IAAI,CAAC;AAAA,MAAQ,MAAM,IAAI,MAAM,mDAAmD;AAAA,IAChF,OAAO;AAAA;AAAA,OAGL,OAAM,CAAC,OAAe,MAAgC;AAAA,IACxD,MAAM,WAAW,MAAM,KAAK,IAAI,OAAO,IAAI;AAAA,IAC3C,IAAI,CAAC;AAAA,MAAU,OAAO;AAAA,IACtB,KAAK,GACA,MAAM,eAAe,KAAK,oCAAoC,EAC9D,IAAI,OAAO,IAAI;AAAA,IACpB,OAAO;AAAA;AAAA,EAIX,KAAK,GAAS;AAAA,IACV,KAAK,GAAG,MAAM;AAAA;AAEtB;",
|
|
8
|
+
"debugId": "6FCBF9C9F6B3EDC164756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -4,6 +4,12 @@ export type SecretRecord = {
|
|
|
4
4
|
name: string;
|
|
5
5
|
/** Sealed value, `iv:payload`. Never the plaintext. */
|
|
6
6
|
sealed: string;
|
|
7
|
+
/**
|
|
8
|
+
* Non-secret facts about the value, stored in the clear and returned by
|
|
9
|
+
* `list`: what kind of credential it is, which username it belongs to, a
|
|
10
|
+
* public key — anything safe to show beside the name.
|
|
11
|
+
*/
|
|
12
|
+
metadata: Record<string, string>;
|
|
7
13
|
createdAt: Date;
|
|
8
14
|
updatedAt: Date;
|
|
9
15
|
};
|
|
@@ -23,6 +29,7 @@ export type VaultStore = {
|
|
|
23
29
|
owner: string;
|
|
24
30
|
name: string;
|
|
25
31
|
sealed: string;
|
|
32
|
+
metadata: Record<string, string>;
|
|
26
33
|
}): Promise<SecretRecord>;
|
|
27
34
|
remove(owner: string, name: string): Promise<boolean>;
|
|
28
35
|
};
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,MAAM,YAAY,GAAG;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,CAAA;CAClB,CAAA;AAED,mEAAmE;AACnE,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAA;AAExD;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG;IACrB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAC9D,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAC5C,oDAAoD;IACpD,GAAG,CAAC,MAAM,EAAE;QACR,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,MAAM,YAAY,GAAG;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,CAAA;CAClB,CAAA;AAED,mEAAmE;AACnE,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAA;AAExD;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG;IACrB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAC9D,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAC5C,oDAAoD;IACpD,GAAG,CAAC,MAAM,EAAE;QACR,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACnC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACzB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACxD,CAAA"}
|
package/dist/vault.d.ts
CHANGED
|
@@ -20,8 +20,14 @@ export declare class Vault {
|
|
|
20
20
|
constructor({ key, store, prefix }: VaultOptions);
|
|
21
21
|
/** Names and dates for one owner. Never values. */
|
|
22
22
|
list(owner: string): Promise<SecretSummary[]>;
|
|
23
|
-
/**
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Stores a value, replacing whatever was under that name.
|
|
25
|
+
*
|
|
26
|
+
* `metadata` is kept in the clear and comes back from `list`, so it must
|
|
27
|
+
* hold nothing secret — a credential's kind, or the username it belongs to,
|
|
28
|
+
* not the password.
|
|
29
|
+
*/
|
|
30
|
+
put(owner: string, name: string, value: string, metadata?: Record<string, string>): Promise<SecretSummary>;
|
|
25
31
|
/** True when the owner has a secret under that name. */
|
|
26
32
|
has(owner: string, name: string): Promise<boolean>;
|
|
27
33
|
/** Removes a secret, returning false if it wasn't there. */
|
package/dist/vault.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAExD,2DAA2D;AAC3D,eAAO,MAAM,cAAc,YAAY,CAAA;AAIvC,MAAM,MAAM,YAAY,GAAG;IACvB,yEAAyE;IACzE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,KAAK,EAAE,UAAU,CAAA;IACjB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;;GAIG;AACH,qBAAa,KAAK;IACd,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;gBAEX,EAAE,GAAG,EAAE,KAAK,EAAE,MAAuB,EAAE,EAAE,YAAY;IAMjE,mDAAmD;IAC7C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAOnD
|
|
1
|
+
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAExD,2DAA2D;AAC3D,eAAO,MAAM,cAAc,YAAY,CAAA;AAIvC,MAAM,MAAM,YAAY,GAAG;IACvB,yEAAyE;IACzE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,KAAK,EAAE,UAAU,CAAA;IACjB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;;GAIG;AACH,qBAAa,KAAK;IACd,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;gBAEX,EAAE,GAAG,EAAE,KAAK,EAAE,MAAuB,EAAE,EAAE,YAAY;IAMjE,mDAAmD;IAC7C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAOnD;;;;;;OAMG;IACG,GAAG,CACL,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACtC,OAAO,CAAC,aAAa,CAAC;IAczB,wDAAwD;IAClD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIxD,4DAA4D;IAC5D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrD;;;OAGG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAMxD;;;;;;OAMG;IACG,OAAO,CACT,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAalC,OAAO,CAAC,SAAS;CASpB"}
|
package/package.json
CHANGED