@poppykit/client 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/API.md +4 -0
- package/CHANGELOG.md +15 -15
- package/CONTRIBUTING.md +30 -42
- package/DELIVERY.md +6 -25
- package/PROVIDER.md +25 -2
- package/README.md +26 -98
- package/RELEASING.md +91 -193
- package/SECURITY.md +3 -3
- package/STORAGE.md +65 -8
- package/dist/adapter-contract.d.ts +15 -0
- package/dist/adapter-contract.js +48 -0
- package/dist/postgres-runtime.d.ts +30 -0
- package/dist/postgres-runtime.js +172 -0
- package/dist/postgres.d.ts +39 -0
- package/dist/postgres.js +143 -0
- package/dist/provider-postgres.d.ts +15 -0
- package/dist/provider-postgres.js +96 -0
- package/dist/provider-sqlite.d.ts +2 -2
- package/dist/provider-sqlite.js +9 -6
- package/dist/provider-storage.d.ts +7 -0
- package/dist/provider-storage.js +61 -0
- package/dist/provider.d.ts +40 -10
- package/dist/provider.js +35 -20
- package/migrations/postgres/0001_poppy_client.sql +16 -0
- package/migrations/postgres/0001_poppy_provider.sql +14 -0
- package/package.json +26 -3
package/dist/provider.d.ts
CHANGED
|
@@ -11,10 +11,40 @@ export interface ProviderTransaction {
|
|
|
11
11
|
value: Row;
|
|
12
12
|
}[];
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
export type ProviderSelection = {
|
|
15
|
+
kind: 'enroll';
|
|
16
|
+
subjectHash: string;
|
|
17
|
+
requestHash: string;
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'identity';
|
|
20
|
+
enrollmentId: string;
|
|
21
|
+
issuer: string;
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'operation';
|
|
24
|
+
enrollmentId: string;
|
|
25
|
+
operationId: string;
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'begin';
|
|
28
|
+
enrollmentId: string;
|
|
29
|
+
operationId: string;
|
|
30
|
+
issuer: string;
|
|
31
|
+
stateHash?: string;
|
|
32
|
+
at: number;
|
|
33
|
+
} | {
|
|
34
|
+
kind: 'callback';
|
|
35
|
+
stateHash: string;
|
|
36
|
+
} | {
|
|
37
|
+
kind: 'revoke';
|
|
38
|
+
enrollmentId: string;
|
|
39
|
+
};
|
|
40
|
+
/** Atomic asynchronous I/O around a pure synchronous, selection-bounded callback. */
|
|
15
41
|
export interface ProviderStore {
|
|
16
|
-
transaction<T>(action: (tx: ProviderTransaction) => T): T
|
|
42
|
+
transaction<T>(selection: ProviderSelection, action: (tx: ProviderTransaction) => T): Promise<T>;
|
|
17
43
|
}
|
|
44
|
+
/** Explicit migration aid for existing local synchronous stores; unsuitable for remote I/O. */
|
|
45
|
+
export declare function adaptLegacyProviderStore(store: {
|
|
46
|
+
transaction<T>(action: (tx: ProviderTransaction) => T): T;
|
|
47
|
+
}): ProviderStore;
|
|
18
48
|
export interface ResultCipher {
|
|
19
49
|
seal(value: string): string;
|
|
20
50
|
open(value: string): string;
|
|
@@ -70,22 +100,22 @@ export declare function createProvider(options: ProviderOptions): {
|
|
|
70
100
|
assertion: string;
|
|
71
101
|
expiresAt: number;
|
|
72
102
|
}>;
|
|
73
|
-
callback(callbackUrl: string): {
|
|
103
|
+
callback(callbackUrl: string): Promise<{
|
|
74
104
|
status: string;
|
|
75
|
-
}
|
|
76
|
-
takeResult(credential: string, input: Row): {
|
|
105
|
+
}>;
|
|
106
|
+
takeResult(credential: string, input: Row): Promise<{
|
|
77
107
|
status: string;
|
|
78
108
|
callbackUrl?: undefined;
|
|
79
109
|
} | {
|
|
80
110
|
status: string;
|
|
81
111
|
callbackUrl: string;
|
|
82
|
-
}
|
|
83
|
-
cancel(credential: string, input: Row): {
|
|
112
|
+
}>;
|
|
113
|
+
cancel(credential: string, input: Row): Promise<{
|
|
84
114
|
status: string;
|
|
85
|
-
}
|
|
86
|
-
revokeEnrollment(credential: string, input: Row): {
|
|
115
|
+
}>;
|
|
116
|
+
revokeEnrollment(credential: string, input: Row): Promise<{
|
|
87
117
|
status: string;
|
|
88
|
-
}
|
|
118
|
+
}>;
|
|
89
119
|
handle(request: Request): Promise<Response>;
|
|
90
120
|
};
|
|
91
121
|
/** Bound trusted adapter: credentials/assertions/results never belong in harness output. */
|
package/dist/provider.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
/** Optional PoppyKit provider v1. Hosting, human authentication and key custody belong to the operator. */
|
|
2
2
|
import { createHash, randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';
|
|
3
3
|
import { secureUrl } from './network/transport.js';
|
|
4
|
+
/** Explicit migration aid for existing local synchronous stores; unsuitable for remote I/O. */
|
|
5
|
+
export function adaptLegacyProviderStore(store) {
|
|
6
|
+
return { async transaction(_selection, action) {
|
|
7
|
+
return store.transaction(tx => {
|
|
8
|
+
const result = action(tx);
|
|
9
|
+
if (result && typeof result.then === 'function')
|
|
10
|
+
throw new TypeError('provider transaction must be synchronous');
|
|
11
|
+
return structuredClone(result);
|
|
12
|
+
});
|
|
13
|
+
} };
|
|
14
|
+
}
|
|
4
15
|
export function createResultCipher(key) {
|
|
5
16
|
if (key.length !== 32)
|
|
6
17
|
throw new Error('provider encryption key must be 32 bytes');
|
|
@@ -85,10 +96,12 @@ export function createProvider(options) {
|
|
|
85
96
|
starts.push(now());
|
|
86
97
|
tx.put('enrollment', enrollment.enrollmentId, { ...enrollment, starts });
|
|
87
98
|
}
|
|
88
|
-
|
|
99
|
+
const enrollmentId = (credential) => credential.split('.')[0] ?? '';
|
|
100
|
+
const selectedOperation = (credential, input) => ({ kind: 'operation', enrollmentId: enrollmentId(credential), operationId: text(input.operationId) });
|
|
101
|
+
async function authorizeCompany(credential, input) {
|
|
89
102
|
const domain = text(input.domain);
|
|
90
103
|
text(input.issuer);
|
|
91
|
-
store.transaction(tx => { const enrollment = auth(tx, credential, text(input.installationId)); if (!enrollment.allowedCompanies.includes(domain))
|
|
104
|
+
await store.transaction({ kind: 'identity', enrollmentId: enrollmentId(credential), issuer: input.issuer }, tx => { const enrollment = auth(tx, credential, text(input.installationId)); if (!enrollment.allowedCompanies.includes(domain))
|
|
92
105
|
fail('unauthorized'); });
|
|
93
106
|
}
|
|
94
107
|
const api = {
|
|
@@ -98,12 +111,14 @@ export function createProvider(options) {
|
|
|
98
111
|
if (!human?.subject || !human.allowedCompanies.length)
|
|
99
112
|
fail('unauthorized');
|
|
100
113
|
const installationId = text(input.installationId), key = hash(JSON.stringify([human.subject, text(input.idempotencyKey)]));
|
|
101
|
-
return store.transaction(tx => {
|
|
114
|
+
return store.transaction({ kind: 'enroll', subjectHash: hash(human.subject), requestHash: key }, tx => {
|
|
102
115
|
if (tx.get('enrollmentRequest', key))
|
|
103
116
|
fail('consumed'); // Credential delivery cannot be replayed from a verifier.
|
|
104
117
|
const subjectKey = hash(human.subject), visitor = tx.get('visitor', subjectKey)?.id ?? id();
|
|
105
|
-
|
|
118
|
+
const count = tx.get('capacity', 'enrollments')?.count ?? 0;
|
|
119
|
+
if (count >= (options.maxEnrollments ?? 10000))
|
|
106
120
|
throw new ProviderError('rate_limited', now() + 60000);
|
|
121
|
+
tx.put('capacity', 'enrollments', { count: count + 1 });
|
|
107
122
|
tx.put('visitor', subjectKey, { id: visitor });
|
|
108
123
|
const enrollmentId = id(), secret = id();
|
|
109
124
|
tx.put('enrollment', enrollmentId, { installationId, visitor, verifier: hash(secret), allowedCompanies: [...new Set(human.allowedCompanies)], revoked: false, starts: [] });
|
|
@@ -113,9 +128,9 @@ export function createProvider(options) {
|
|
|
113
128
|
},
|
|
114
129
|
async identity(credential, input) {
|
|
115
130
|
exact(input, ['version', 'installationId', 'domain', 'issuer']);
|
|
116
|
-
authorizeCompany(credential, input);
|
|
131
|
+
await authorizeCompany(credential, input);
|
|
117
132
|
const metadata = await verified(text(input.domain), text(input.issuer));
|
|
118
|
-
return store.transaction(tx => {
|
|
133
|
+
return store.transaction({ kind: 'identity', enrollmentId: enrollmentId(credential), issuer: input.issuer }, tx => {
|
|
119
134
|
const enrollment = auth(tx, credential, text(input.installationId));
|
|
120
135
|
if (!enrollment.allowedCompanies.includes(metadata.document.organization.domain))
|
|
121
136
|
fail('unauthorized');
|
|
@@ -129,7 +144,7 @@ export function createProvider(options) {
|
|
|
129
144
|
text(input.operationId);
|
|
130
145
|
if (input.sessionId !== undefined)
|
|
131
146
|
text(input.sessionId);
|
|
132
|
-
authorizeCompany(credential, input);
|
|
147
|
+
await authorizeCompany(credential, input);
|
|
133
148
|
if (input.purpose === 'client-authentication' && (input.sessionId !== undefined || input.returnTo !== undefined))
|
|
134
149
|
fail('binding_conflict');
|
|
135
150
|
if (input.purpose !== 'browser' && input.returnTo !== undefined)
|
|
@@ -145,7 +160,7 @@ export function createProvider(options) {
|
|
|
145
160
|
const metadata = await verified(text(input.domain), text(input.issuer));
|
|
146
161
|
if (input.purpose === 'browser' && (!onDomain(input.returnTo, metadata.document.organization.domain) || !metadata.document.web?.browser_session_endpoint))
|
|
147
162
|
fail('binding_conflict');
|
|
148
|
-
const identity = store.transaction(tx => {
|
|
163
|
+
const identity = await store.transaction({ kind: 'identity', enrollmentId: enrollmentId(credential), issuer: input.issuer }, tx => {
|
|
149
164
|
const enrollment = auth(tx, credential, text(input.installationId));
|
|
150
165
|
if (!enrollment.allowedCompanies.includes(metadata.document.organization.domain))
|
|
151
166
|
fail('unauthorized');
|
|
@@ -154,7 +169,7 @@ export function createProvider(options) {
|
|
|
154
169
|
if (input.purpose === 'browser' && !await options.verifySession?.({ clientId: options.clientId, userId: identity.userId, issuer: input.issuer, sessionId: input.sessionId }))
|
|
155
170
|
fail('unauthorized');
|
|
156
171
|
const binding = { issuer: input.issuer, domain: metadata.document.organization.domain, purpose: input.purpose, sessionId: input.sessionId ?? null, returnTo: input.returnTo ?? null, stateHash: input.state ? hash(input.state) : null, userId: identity.userId, browserEndpoint: metadata.document.web?.browser_session_endpoint ?? null };
|
|
157
|
-
return store.transaction(tx => {
|
|
172
|
+
return store.transaction({ kind: 'begin', enrollmentId: enrollmentId(credential), operationId: input.operationId, issuer: input.issuer, ...(binding.stateHash ? { stateHash: binding.stateHash } : {}), at: now() }, tx => {
|
|
158
173
|
const enrollment = auth(tx, credential, text(input.installationId)), key = `${enrollment.enrollmentId}:${text(input.operationId)}`, existing = tx.get('operation', key);
|
|
159
174
|
if (existing) {
|
|
160
175
|
if (!same(existing.binding, binding))
|
|
@@ -186,7 +201,7 @@ export function createProvider(options) {
|
|
|
186
201
|
},
|
|
187
202
|
async assert(credential, input) {
|
|
188
203
|
exact(input, ['version', 'installationId', 'operationId', 'purpose']);
|
|
189
|
-
const snapshot = store.transaction(tx => {
|
|
204
|
+
const snapshot = await store.transaction(selectedOperation(credential, input), tx => {
|
|
190
205
|
const enrollment = auth(tx, credential, text(input.installationId)), op = operation(tx, enrollment, text(input.operationId));
|
|
191
206
|
if (op.binding.purpose !== input.purpose || !['client-authentication', 'session', 'browser'].includes(input.purpose))
|
|
192
207
|
fail('binding_conflict');
|
|
@@ -206,17 +221,17 @@ export function createProvider(options) {
|
|
|
206
221
|
if (signature.length !== 64)
|
|
207
222
|
fail('unavailable');
|
|
208
223
|
// A revoke/cancel racing external KMS signing wins before the assertion leaves the provider.
|
|
209
|
-
store.transaction(tx => { const enrollment = auth(tx, credential, input.installationId), op = operation(tx, enrollment, input.operationId); tx.put('operation', `${enrollment.enrollmentId}:${input.operationId}`, { ...op, status: 'signed' }); });
|
|
224
|
+
await store.transaction(selectedOperation(credential, input), tx => { const enrollment = auth(tx, credential, input.installationId), op = operation(tx, enrollment, input.operationId); tx.put('operation', `${enrollment.enrollmentId}:${input.operationId}`, { ...op, status: 'signed' }); });
|
|
210
225
|
return { assertion: `${unsigned}.${Buffer.from(signature).toString('base64url')}`, expiresAt: exp };
|
|
211
226
|
},
|
|
212
|
-
callback(callbackUrl) {
|
|
227
|
+
async callback(callbackUrl) {
|
|
213
228
|
const url = new URL(callbackUrl), base = new URL(options.callbackUrl);
|
|
214
229
|
if (url.origin !== base.origin || url.pathname !== base.pathname || url.username || url.password || url.hash || [...url.searchParams.keys()].some(key => !['state', 'iss', 'code', 'error'].includes(key)) || ['state', 'iss', 'code', 'error'].some(key => url.searchParams.getAll(key).length > 1))
|
|
215
230
|
fail('binding_conflict');
|
|
216
231
|
const state = text(url.searchParams.get('state')), issuer = text(url.searchParams.get('iss'));
|
|
217
232
|
if (!!url.searchParams.get('code') === !!url.searchParams.get('error') || callbackUrl.length > 8192)
|
|
218
233
|
fail('binding_conflict');
|
|
219
|
-
return store.transaction(tx => {
|
|
234
|
+
return store.transaction({ kind: 'callback', stateHash: hash(state) }, tx => {
|
|
220
235
|
const lookup = tx.get('state', hash(state));
|
|
221
236
|
if (!lookup)
|
|
222
237
|
fail('binding_conflict');
|
|
@@ -236,9 +251,9 @@ export function createProvider(options) {
|
|
|
236
251
|
return { status: 'ready' };
|
|
237
252
|
});
|
|
238
253
|
},
|
|
239
|
-
takeResult(credential, input) {
|
|
254
|
+
async takeResult(credential, input) {
|
|
240
255
|
exact(input, ['version', 'installationId', 'operationId', 'issuer', 'sessionId']);
|
|
241
|
-
return store.transaction(tx => {
|
|
256
|
+
return store.transaction(selectedOperation(credential, input), tx => {
|
|
242
257
|
const enrollment = auth(tx, credential, text(input.installationId)), op = operation(tx, enrollment, text(input.operationId));
|
|
243
258
|
if (op.binding.issuer !== input.issuer || op.binding.sessionId !== input.sessionId || op.binding.purpose !== 'direct')
|
|
244
259
|
fail('binding_conflict');
|
|
@@ -249,9 +264,9 @@ export function createProvider(options) {
|
|
|
249
264
|
return { status: 'completed', callbackUrl };
|
|
250
265
|
});
|
|
251
266
|
},
|
|
252
|
-
cancel(credential, input) {
|
|
267
|
+
async cancel(credential, input) {
|
|
253
268
|
exact(input, ['version', 'installationId', 'operationId']);
|
|
254
|
-
return store.transaction(tx => {
|
|
269
|
+
return store.transaction(selectedOperation(credential, input), tx => {
|
|
255
270
|
const enrollment = auth(tx, credential, text(input.installationId)), key = `${enrollment.enrollmentId}:${text(input.operationId)}`, op = tx.get('operation', key);
|
|
256
271
|
if (!op)
|
|
257
272
|
fail('binding_conflict');
|
|
@@ -259,9 +274,9 @@ export function createProvider(options) {
|
|
|
259
274
|
return { status: 'canceled' };
|
|
260
275
|
});
|
|
261
276
|
},
|
|
262
|
-
revokeEnrollment(credential, input) {
|
|
277
|
+
async revokeEnrollment(credential, input) {
|
|
263
278
|
exact(input, ['version', 'installationId']);
|
|
264
|
-
return store.transaction(tx => {
|
|
279
|
+
return store.transaction({ kind: 'revoke', enrollmentId: enrollmentId(credential) }, tx => {
|
|
265
280
|
const enrollment = auth(tx, credential, text(input.installationId));
|
|
266
281
|
tx.put('enrollment', enrollment.enrollmentId, { ...enrollment, revoked: true });
|
|
267
282
|
for (const row of tx.list('operation', `${enrollment.enrollmentId}:`, 1000))
|
|
@@ -278,7 +293,7 @@ export function createProvider(options) {
|
|
|
278
293
|
return Response.json({ keys: (options.publishedKeys ? await options.publishedKeys() : [{ ...await options.signer.publicJwk(), kid: options.signer.kid }]).map(publicKey) }, { headers });
|
|
279
294
|
const url = new URL(request.url);
|
|
280
295
|
if (url.origin === new URL(options.callbackUrl).origin && url.pathname === new URL(options.callbackUrl).pathname && request.method === 'GET') {
|
|
281
|
-
api.callback(request.url);
|
|
296
|
+
await api.callback(request.url);
|
|
282
297
|
return Response.json({ status: 'received' }, { headers });
|
|
283
298
|
}
|
|
284
299
|
if (request.method !== 'POST' || !request.headers.get('content-type')?.startsWith('application/json'))
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
CREATE SCHEMA poppy_client;
|
|
2
|
+
CREATE TABLE poppy_client.schema_version (version integer PRIMARY KEY CHECK(version > 0));
|
|
3
|
+
INSERT INTO poppy_client.schema_version VALUES (1);
|
|
4
|
+
CREATE TABLE poppy_client.records (ns text NOT NULL, kind text NOT NULL, id text NOT NULL, body text NOT NULL CHECK (body::jsonb IS NOT NULL), ordinal bigint GENERATED ALWAYS AS IDENTITY, PRIMARY KEY(ns,kind,id));
|
|
5
|
+
CREATE INDEX by_conversation ON poppy_client.records (ns,kind,(body::jsonb->>'conversationId'));
|
|
6
|
+
CREATE INDEX by_binding ON poppy_client.records (ns,kind,(body::jsonb->>'bindingId'));
|
|
7
|
+
CREATE INDEX by_client ON poppy_client.records (ns,kind,(body::jsonb->>'clientId'));
|
|
8
|
+
CREATE INDEX by_account ON poppy_client.records (ns,kind,(body::jsonb->>'accountId'));
|
|
9
|
+
CREATE INDEX by_grant ON poppy_client.records (ns,kind,(body::jsonb->>'grantId'));
|
|
10
|
+
CREATE INDEX by_phase ON poppy_client.records (ns,kind,(body::jsonb->>'phase'));
|
|
11
|
+
CREATE INDEX by_expiry ON poppy_client.records (ns,kind,((body::jsonb->>'expiresAt')::double precision));
|
|
12
|
+
CREATE INDEX by_connection ON poppy_client.records (ns,kind,(body::jsonb->>'connectionId'));
|
|
13
|
+
CREATE INDEX by_callback ON poppy_client.records (ns,kind,(body::jsonb#>>'{direct,stateHash}'));
|
|
14
|
+
CREATE TABLE poppy_client.outbound (ns text NOT NULL, connection text NOT NULL, issuer text NOT NULL, id text NOT NULL, body text NOT NULL, PRIMARY KEY(ns,connection,issuer,id));
|
|
15
|
+
CREATE TABLE poppy_client.checkpoints (ns text NOT NULL, connection text NOT NULL, issuer text NOT NULL, endpoint text NOT NULL, conversation text NOT NULL, name text NOT NULL, cursor text NOT NULL, PRIMARY KEY(ns,connection,issuer,endpoint,conversation,name));
|
|
16
|
+
CREATE UNIQUE INDEX auth_callback ON poppy_client.records(ns,((body::jsonb)#>>'{direct,stateHash}')) WHERE kind='operations';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
CREATE SCHEMA poppy_provider;
|
|
2
|
+
CREATE TABLE poppy_provider.schema_version (version integer PRIMARY KEY CHECK(version > 0));
|
|
3
|
+
INSERT INTO poppy_provider.schema_version VALUES (1);
|
|
4
|
+
CREATE TABLE poppy_provider.records (ns text NOT NULL, kind text NOT NULL, id text NOT NULL, body text NOT NULL CHECK (body::jsonb IS NOT NULL), ordinal bigint GENERATED ALWAYS AS IDENTITY, PRIMARY KEY(ns,kind,id));
|
|
5
|
+
CREATE INDEX operations_enrollment ON poppy_provider.records(ns,(split_part(id,':',1)),id) WHERE kind='operation';
|
|
6
|
+
CREATE INDEX by_conversation ON poppy_provider.records (ns,kind,(body::jsonb->>'conversationId'));
|
|
7
|
+
CREATE INDEX by_binding ON poppy_provider.records (ns,kind,(body::jsonb->>'bindingId'));
|
|
8
|
+
CREATE INDEX by_client ON poppy_provider.records (ns,kind,(body::jsonb->>'clientId'));
|
|
9
|
+
CREATE INDEX by_account ON poppy_provider.records (ns,kind,(body::jsonb->>'accountId'));
|
|
10
|
+
CREATE INDEX by_grant ON poppy_provider.records (ns,kind,(body::jsonb->>'grantId'));
|
|
11
|
+
CREATE INDEX by_phase ON poppy_provider.records (ns,kind,(body::jsonb->>'phase'));
|
|
12
|
+
CREATE INDEX by_expiry ON poppy_provider.records (ns,kind,((body::jsonb->>'expiresAt')::double precision));
|
|
13
|
+
CREATE INDEX by_connection ON poppy_provider.records (ns,kind,(body::jsonb->>'connectionId'));
|
|
14
|
+
CREATE INDEX by_callback ON poppy_provider.records (ns,kind,(body::jsonb#>>'{direct,stateHash}'));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poppykit/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Personal Agent Protocol client SDK",
|
|
6
6
|
"repository": {
|
|
@@ -24,7 +24,9 @@
|
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "24.10.0",
|
|
27
|
-
"typescript": "5.9.3"
|
|
27
|
+
"typescript": "5.9.3",
|
|
28
|
+
"pg": "8.23.1",
|
|
29
|
+
"@types/pg": "8.23.1"
|
|
28
30
|
},
|
|
29
31
|
"files": [
|
|
30
32
|
"dist",
|
|
@@ -40,7 +42,8 @@
|
|
|
40
42
|
"CHANGELOG.md",
|
|
41
43
|
"RELEASING.md",
|
|
42
44
|
"examples",
|
|
43
|
-
"LICENSE"
|
|
45
|
+
"LICENSE",
|
|
46
|
+
"migrations"
|
|
44
47
|
],
|
|
45
48
|
"exports": {
|
|
46
49
|
".": {
|
|
@@ -62,6 +65,18 @@
|
|
|
62
65
|
"./provider/sqlite": {
|
|
63
66
|
"import": "./dist/provider-sqlite.js",
|
|
64
67
|
"types": "./dist/provider-sqlite.d.ts"
|
|
68
|
+
},
|
|
69
|
+
"./postgres": {
|
|
70
|
+
"types": "./dist/postgres.d.ts",
|
|
71
|
+
"import": "./dist/postgres.js"
|
|
72
|
+
},
|
|
73
|
+
"./provider/postgres": {
|
|
74
|
+
"types": "./dist/provider-postgres.d.ts",
|
|
75
|
+
"import": "./dist/provider-postgres.js"
|
|
76
|
+
},
|
|
77
|
+
"./adapter-contract": {
|
|
78
|
+
"types": "./dist/adapter-contract.d.ts",
|
|
79
|
+
"import": "./dist/adapter-contract.js"
|
|
65
80
|
}
|
|
66
81
|
},
|
|
67
82
|
"dependencies": {
|
|
@@ -70,5 +85,13 @@
|
|
|
70
85
|
"license": "MIT",
|
|
71
86
|
"publishConfig": {
|
|
72
87
|
"access": "public"
|
|
88
|
+
},
|
|
89
|
+
"peerDependencies": {
|
|
90
|
+
"pg": "^8.23.1"
|
|
91
|
+
},
|
|
92
|
+
"peerDependenciesMeta": {
|
|
93
|
+
"pg": {
|
|
94
|
+
"optional": true
|
|
95
|
+
}
|
|
73
96
|
}
|
|
74
97
|
}
|