mneme-sdk 0.1.0 → 0.4.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/dist/index.cjs +96 -3
- package/dist/index.d.cts +115 -0
- package/dist/index.d.ts +115 -0
- package/dist/index.js +96 -3
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -112,7 +112,13 @@ var Mneme = class {
|
|
|
112
112
|
events;
|
|
113
113
|
kvs;
|
|
114
114
|
constructor(opts) {
|
|
115
|
-
|
|
115
|
+
if ("apiKey" in opts && opts.apiKey) {
|
|
116
|
+
this.auth = { apiKey: opts.apiKey };
|
|
117
|
+
} else if ("accessToken" in opts && opts.accessToken) {
|
|
118
|
+
this.auth = { accessToken: opts.accessToken };
|
|
119
|
+
} else {
|
|
120
|
+
this.auth = { account: opts.account };
|
|
121
|
+
}
|
|
116
122
|
this.gatewayUrl = opts.gatewayUrl.replace(/\/$/, "");
|
|
117
123
|
this.chainId = opts.chainId ?? 8453;
|
|
118
124
|
this.domainName = opts.domainName ?? "Mneme";
|
|
@@ -140,6 +146,50 @@ var Mneme = class {
|
|
|
140
146
|
from(table) {
|
|
141
147
|
return new Collection(this, table);
|
|
142
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Natural-language → SQL via the gateway's LLM proxy.
|
|
151
|
+
* Use the returned SQL with `m.sql(...)` to execute it.
|
|
152
|
+
*/
|
|
153
|
+
llm = {
|
|
154
|
+
sql: (args) => this.request(
|
|
155
|
+
"POST",
|
|
156
|
+
"/v1/llm/sql",
|
|
157
|
+
args
|
|
158
|
+
)
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Service-account API keys — for B2B2C integrators (e.g. Gitlawb) that
|
|
162
|
+
* distribute scoped keys to end-users who don't have wallets.
|
|
163
|
+
*
|
|
164
|
+
* Only callable by wallet-authed clients (keys cannot mint more keys).
|
|
165
|
+
*/
|
|
166
|
+
serviceKeys = {
|
|
167
|
+
/** Mint a new scoped key. Returns the raw key value ONCE. */
|
|
168
|
+
create: (args) => this.request("POST", "/v1/service/keys", args),
|
|
169
|
+
/** List all keys you've created (no raw values — only metadata). */
|
|
170
|
+
list: () => this.request("GET", "/v1/service/keys"),
|
|
171
|
+
/** Revoke a key by id. */
|
|
172
|
+
revoke: (id) => this.request("DELETE", `/v1/service/keys/${id}`)
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* Run raw SQL against your project's Postgres schema.
|
|
176
|
+
*
|
|
177
|
+
* Safety guards (server-side):
|
|
178
|
+
* - 5-second statement timeout
|
|
179
|
+
* - search_path pinned to your schema (unqualified table refs resolve to YOUR schema)
|
|
180
|
+
* - cross-tenant schema references are blocked
|
|
181
|
+
* - 1000-row result cap
|
|
182
|
+
* - single statement only
|
|
183
|
+
*
|
|
184
|
+
* Returns rows, column metadata, and elapsed time.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* await m.sql("SELECT count(*) FROM memories");
|
|
188
|
+
* await m.sql("CREATE INDEX ON books (rating)");
|
|
189
|
+
*/
|
|
190
|
+
sql(query) {
|
|
191
|
+
return this.request("POST", "/v1/sql", { query });
|
|
192
|
+
}
|
|
143
193
|
// ─── Storage (Cloudflare R2 backend, $MNEME burn quota) ──────────────────
|
|
144
194
|
storage = {
|
|
145
195
|
upload: async (args) => {
|
|
@@ -187,7 +237,9 @@ var Mneme = class {
|
|
|
187
237
|
async request(method, path, body) {
|
|
188
238
|
const bodyText = body === void 0 ? "" : JSON.stringify(body);
|
|
189
239
|
const headers = { "Content-Type": "application/json" };
|
|
190
|
-
if ("
|
|
240
|
+
if ("apiKey" in this.auth && this.auth.apiKey) {
|
|
241
|
+
headers["Authorization"] = `ApiKey ${this.auth.apiKey}`;
|
|
242
|
+
} else if ("accessToken" in this.auth && this.auth.accessToken) {
|
|
191
243
|
headers["Authorization"] = `Bearer ${this.auth.accessToken}`;
|
|
192
244
|
} else if ("account" in this.auth && this.auth.account) {
|
|
193
245
|
const signed = await signRequest({
|
|
@@ -201,7 +253,7 @@ var Mneme = class {
|
|
|
201
253
|
});
|
|
202
254
|
Object.assign(headers, signed);
|
|
203
255
|
} else {
|
|
204
|
-
throw new Error("Mneme:
|
|
256
|
+
throw new Error("Mneme: one of { account }, { accessToken }, or { apiKey } is required");
|
|
205
257
|
}
|
|
206
258
|
const res = await fetch(`${this.gatewayUrl}${path}`, {
|
|
207
259
|
method,
|
|
@@ -220,6 +272,7 @@ var Collection = class {
|
|
|
220
272
|
}
|
|
221
273
|
mneme;
|
|
222
274
|
table;
|
|
275
|
+
/** Insert one row or an array of rows. Returns the inserted rows. */
|
|
223
276
|
insert(rows) {
|
|
224
277
|
return this.mneme.request(
|
|
225
278
|
"POST",
|
|
@@ -227,14 +280,54 @@ var Collection = class {
|
|
|
227
280
|
rows
|
|
228
281
|
);
|
|
229
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* List rows. Supports filtering with `where` (PostgREST-style col.op.value),
|
|
285
|
+
* ordering with `order` (e.g. "created_at.desc"), and pagination.
|
|
286
|
+
*
|
|
287
|
+
* Ops: eq, neq, gt, gte, lt, lte, like, ilike, in, is.
|
|
288
|
+
* Example: `m.from("todos").list({ where: ["done.eq.false"], order: "created_at.desc" })`
|
|
289
|
+
*/
|
|
230
290
|
list(opts) {
|
|
231
291
|
const q = new URLSearchParams();
|
|
232
292
|
if (opts?.limit != null) q.set("limit", String(opts.limit));
|
|
233
293
|
if (opts?.offset != null) q.set("offset", String(opts.offset));
|
|
234
294
|
if (opts?.order) q.set("order", opts.order);
|
|
295
|
+
if (opts?.where) {
|
|
296
|
+
const ws = Array.isArray(opts.where) ? opts.where : [opts.where];
|
|
297
|
+
for (const w of ws) q.append("where", w);
|
|
298
|
+
}
|
|
235
299
|
const qs = q.toString() ? `?${q}` : "";
|
|
236
300
|
return this.mneme.request("GET", `/v1/rows/${this.table}${qs}`);
|
|
237
301
|
}
|
|
302
|
+
/** Update one row by id. Returns the updated row. */
|
|
303
|
+
update(id, updates) {
|
|
304
|
+
return this.mneme.request(
|
|
305
|
+
"PATCH",
|
|
306
|
+
`/v1/rows/${this.table}/${id}`,
|
|
307
|
+
updates
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
/** Delete one row by id. */
|
|
311
|
+
delete(id) {
|
|
312
|
+
return this.mneme.request(
|
|
313
|
+
"DELETE",
|
|
314
|
+
`/v1/rows/${this.table}/${id}`
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Bulk delete by filter. Refuses to delete the whole table — at least one
|
|
319
|
+
* where clause is required. Returns the count of deleted rows.
|
|
320
|
+
*/
|
|
321
|
+
deleteWhere(where) {
|
|
322
|
+
const ws = Array.isArray(where) ? where : [where];
|
|
323
|
+
if (ws.length === 0) throw new Error("deleteWhere requires at least one filter");
|
|
324
|
+
const q = new URLSearchParams();
|
|
325
|
+
for (const w of ws) q.append("where", w);
|
|
326
|
+
return this.mneme.request(
|
|
327
|
+
"DELETE",
|
|
328
|
+
`/v1/rows/${this.table}?${q}`
|
|
329
|
+
);
|
|
330
|
+
}
|
|
238
331
|
};
|
|
239
332
|
|
|
240
333
|
// src/types.ts
|
package/dist/index.d.cts
CHANGED
|
@@ -64,9 +64,15 @@ interface KvRow {
|
|
|
64
64
|
type MnemeAuth = {
|
|
65
65
|
account: Account;
|
|
66
66
|
accessToken?: never;
|
|
67
|
+
apiKey?: never;
|
|
67
68
|
} | {
|
|
68
69
|
accessToken: string;
|
|
69
70
|
account?: never;
|
|
71
|
+
apiKey?: never;
|
|
72
|
+
} | {
|
|
73
|
+
apiKey: string;
|
|
74
|
+
account?: never;
|
|
75
|
+
accessToken?: never;
|
|
70
76
|
};
|
|
71
77
|
type MnemeOptions = MnemeAuth & {
|
|
72
78
|
gatewayUrl: string;
|
|
@@ -112,6 +118,86 @@ declare class Mneme {
|
|
|
112
118
|
}>;
|
|
113
119
|
stats(): Promise<StatsResponse>;
|
|
114
120
|
from<T = unknown>(table: string): Collection<T>;
|
|
121
|
+
/**
|
|
122
|
+
* Natural-language → SQL via the gateway's LLM proxy.
|
|
123
|
+
* Use the returned SQL with `m.sql(...)` to execute it.
|
|
124
|
+
*/
|
|
125
|
+
llm: {
|
|
126
|
+
sql: (args: {
|
|
127
|
+
prompt: string;
|
|
128
|
+
schema?: string;
|
|
129
|
+
}) => Promise<{
|
|
130
|
+
sql: string;
|
|
131
|
+
model: string;
|
|
132
|
+
elapsed_ms: number;
|
|
133
|
+
}>;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Service-account API keys — for B2B2C integrators (e.g. Gitlawb) that
|
|
137
|
+
* distribute scoped keys to end-users who don't have wallets.
|
|
138
|
+
*
|
|
139
|
+
* Only callable by wallet-authed clients (keys cannot mint more keys).
|
|
140
|
+
*/
|
|
141
|
+
readonly serviceKeys: {
|
|
142
|
+
/** Mint a new scoped key. Returns the raw key value ONCE. */
|
|
143
|
+
create: (args: {
|
|
144
|
+
scope: string;
|
|
145
|
+
label?: string;
|
|
146
|
+
rpm_limit?: number;
|
|
147
|
+
}) => Promise<{
|
|
148
|
+
ok: true;
|
|
149
|
+
id: number;
|
|
150
|
+
key: string;
|
|
151
|
+
key_prefix: string;
|
|
152
|
+
scope: string;
|
|
153
|
+
label: string | null;
|
|
154
|
+
rpm_limit: number;
|
|
155
|
+
created_at: string;
|
|
156
|
+
warning: string;
|
|
157
|
+
}>;
|
|
158
|
+
/** List all keys you've created (no raw values — only metadata). */
|
|
159
|
+
list: () => Promise<{
|
|
160
|
+
keys: Array<{
|
|
161
|
+
id: number;
|
|
162
|
+
key_prefix: string;
|
|
163
|
+
scope: string;
|
|
164
|
+
label: string | null;
|
|
165
|
+
rpm_limit: number;
|
|
166
|
+
revoked: boolean;
|
|
167
|
+
revoked_at: string | null;
|
|
168
|
+
last_used_at: string | null;
|
|
169
|
+
created_at: string;
|
|
170
|
+
}>;
|
|
171
|
+
}>;
|
|
172
|
+
/** Revoke a key by id. */
|
|
173
|
+
revoke: (id: number) => Promise<{
|
|
174
|
+
ok: true;
|
|
175
|
+
id: number;
|
|
176
|
+
}>;
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Run raw SQL against your project's Postgres schema.
|
|
180
|
+
*
|
|
181
|
+
* Safety guards (server-side):
|
|
182
|
+
* - 5-second statement timeout
|
|
183
|
+
* - search_path pinned to your schema (unqualified table refs resolve to YOUR schema)
|
|
184
|
+
* - cross-tenant schema references are blocked
|
|
185
|
+
* - 1000-row result cap
|
|
186
|
+
* - single statement only
|
|
187
|
+
*
|
|
188
|
+
* Returns rows, column metadata, and elapsed time.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* await m.sql("SELECT count(*) FROM memories");
|
|
192
|
+
* await m.sql("CREATE INDEX ON books (rating)");
|
|
193
|
+
*/
|
|
194
|
+
sql<T = Record<string, unknown>>(query: string): Promise<{
|
|
195
|
+
rows: T[];
|
|
196
|
+
row_count: number;
|
|
197
|
+
columns: string[];
|
|
198
|
+
truncated: boolean;
|
|
199
|
+
elapsed_ms: number;
|
|
200
|
+
}>;
|
|
115
201
|
readonly storage: {
|
|
116
202
|
upload: (args: {
|
|
117
203
|
key: string;
|
|
@@ -183,20 +269,49 @@ declare class Mneme {
|
|
|
183
269
|
};
|
|
184
270
|
request<T = unknown>(method: string, path: string, body?: unknown): Promise<T>;
|
|
185
271
|
}
|
|
272
|
+
/** PostgREST-ish where clause. e.g. `["status.eq.done", "score.gt.10"]`. */
|
|
273
|
+
type WhereClause = string;
|
|
186
274
|
declare class Collection<T = unknown> {
|
|
187
275
|
private mneme;
|
|
188
276
|
readonly table: string;
|
|
189
277
|
constructor(mneme: Mneme, table: string);
|
|
278
|
+
/** Insert one row or an array of rows. Returns the inserted rows. */
|
|
190
279
|
insert(rows: T | T[]): Promise<{
|
|
191
280
|
inserted: number;
|
|
192
281
|
rows: T[];
|
|
193
282
|
}>;
|
|
283
|
+
/**
|
|
284
|
+
* List rows. Supports filtering with `where` (PostgREST-style col.op.value),
|
|
285
|
+
* ordering with `order` (e.g. "created_at.desc"), and pagination.
|
|
286
|
+
*
|
|
287
|
+
* Ops: eq, neq, gt, gte, lt, lte, like, ilike, in, is.
|
|
288
|
+
* Example: `m.from("todos").list({ where: ["done.eq.false"], order: "created_at.desc" })`
|
|
289
|
+
*/
|
|
194
290
|
list(opts?: {
|
|
195
291
|
limit?: number;
|
|
196
292
|
offset?: number;
|
|
197
293
|
order?: string;
|
|
294
|
+
where?: WhereClause | WhereClause[];
|
|
198
295
|
}): Promise<{
|
|
199
296
|
rows: T[];
|
|
297
|
+
count: number;
|
|
298
|
+
}>;
|
|
299
|
+
/** Update one row by id. Returns the updated row. */
|
|
300
|
+
update(id: string | number, updates: Partial<T>): Promise<{
|
|
301
|
+
updated: 1;
|
|
302
|
+
row: T;
|
|
303
|
+
}>;
|
|
304
|
+
/** Delete one row by id. */
|
|
305
|
+
delete(id: string | number): Promise<{
|
|
306
|
+
deleted: 1;
|
|
307
|
+
id: number | string;
|
|
308
|
+
}>;
|
|
309
|
+
/**
|
|
310
|
+
* Bulk delete by filter. Refuses to delete the whole table — at least one
|
|
311
|
+
* where clause is required. Returns the count of deleted rows.
|
|
312
|
+
*/
|
|
313
|
+
deleteWhere(where: WhereClause | WhereClause[]): Promise<{
|
|
314
|
+
deleted: number;
|
|
200
315
|
}>;
|
|
201
316
|
}
|
|
202
317
|
|
package/dist/index.d.ts
CHANGED
|
@@ -64,9 +64,15 @@ interface KvRow {
|
|
|
64
64
|
type MnemeAuth = {
|
|
65
65
|
account: Account;
|
|
66
66
|
accessToken?: never;
|
|
67
|
+
apiKey?: never;
|
|
67
68
|
} | {
|
|
68
69
|
accessToken: string;
|
|
69
70
|
account?: never;
|
|
71
|
+
apiKey?: never;
|
|
72
|
+
} | {
|
|
73
|
+
apiKey: string;
|
|
74
|
+
account?: never;
|
|
75
|
+
accessToken?: never;
|
|
70
76
|
};
|
|
71
77
|
type MnemeOptions = MnemeAuth & {
|
|
72
78
|
gatewayUrl: string;
|
|
@@ -112,6 +118,86 @@ declare class Mneme {
|
|
|
112
118
|
}>;
|
|
113
119
|
stats(): Promise<StatsResponse>;
|
|
114
120
|
from<T = unknown>(table: string): Collection<T>;
|
|
121
|
+
/**
|
|
122
|
+
* Natural-language → SQL via the gateway's LLM proxy.
|
|
123
|
+
* Use the returned SQL with `m.sql(...)` to execute it.
|
|
124
|
+
*/
|
|
125
|
+
llm: {
|
|
126
|
+
sql: (args: {
|
|
127
|
+
prompt: string;
|
|
128
|
+
schema?: string;
|
|
129
|
+
}) => Promise<{
|
|
130
|
+
sql: string;
|
|
131
|
+
model: string;
|
|
132
|
+
elapsed_ms: number;
|
|
133
|
+
}>;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Service-account API keys — for B2B2C integrators (e.g. Gitlawb) that
|
|
137
|
+
* distribute scoped keys to end-users who don't have wallets.
|
|
138
|
+
*
|
|
139
|
+
* Only callable by wallet-authed clients (keys cannot mint more keys).
|
|
140
|
+
*/
|
|
141
|
+
readonly serviceKeys: {
|
|
142
|
+
/** Mint a new scoped key. Returns the raw key value ONCE. */
|
|
143
|
+
create: (args: {
|
|
144
|
+
scope: string;
|
|
145
|
+
label?: string;
|
|
146
|
+
rpm_limit?: number;
|
|
147
|
+
}) => Promise<{
|
|
148
|
+
ok: true;
|
|
149
|
+
id: number;
|
|
150
|
+
key: string;
|
|
151
|
+
key_prefix: string;
|
|
152
|
+
scope: string;
|
|
153
|
+
label: string | null;
|
|
154
|
+
rpm_limit: number;
|
|
155
|
+
created_at: string;
|
|
156
|
+
warning: string;
|
|
157
|
+
}>;
|
|
158
|
+
/** List all keys you've created (no raw values — only metadata). */
|
|
159
|
+
list: () => Promise<{
|
|
160
|
+
keys: Array<{
|
|
161
|
+
id: number;
|
|
162
|
+
key_prefix: string;
|
|
163
|
+
scope: string;
|
|
164
|
+
label: string | null;
|
|
165
|
+
rpm_limit: number;
|
|
166
|
+
revoked: boolean;
|
|
167
|
+
revoked_at: string | null;
|
|
168
|
+
last_used_at: string | null;
|
|
169
|
+
created_at: string;
|
|
170
|
+
}>;
|
|
171
|
+
}>;
|
|
172
|
+
/** Revoke a key by id. */
|
|
173
|
+
revoke: (id: number) => Promise<{
|
|
174
|
+
ok: true;
|
|
175
|
+
id: number;
|
|
176
|
+
}>;
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Run raw SQL against your project's Postgres schema.
|
|
180
|
+
*
|
|
181
|
+
* Safety guards (server-side):
|
|
182
|
+
* - 5-second statement timeout
|
|
183
|
+
* - search_path pinned to your schema (unqualified table refs resolve to YOUR schema)
|
|
184
|
+
* - cross-tenant schema references are blocked
|
|
185
|
+
* - 1000-row result cap
|
|
186
|
+
* - single statement only
|
|
187
|
+
*
|
|
188
|
+
* Returns rows, column metadata, and elapsed time.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* await m.sql("SELECT count(*) FROM memories");
|
|
192
|
+
* await m.sql("CREATE INDEX ON books (rating)");
|
|
193
|
+
*/
|
|
194
|
+
sql<T = Record<string, unknown>>(query: string): Promise<{
|
|
195
|
+
rows: T[];
|
|
196
|
+
row_count: number;
|
|
197
|
+
columns: string[];
|
|
198
|
+
truncated: boolean;
|
|
199
|
+
elapsed_ms: number;
|
|
200
|
+
}>;
|
|
115
201
|
readonly storage: {
|
|
116
202
|
upload: (args: {
|
|
117
203
|
key: string;
|
|
@@ -183,20 +269,49 @@ declare class Mneme {
|
|
|
183
269
|
};
|
|
184
270
|
request<T = unknown>(method: string, path: string, body?: unknown): Promise<T>;
|
|
185
271
|
}
|
|
272
|
+
/** PostgREST-ish where clause. e.g. `["status.eq.done", "score.gt.10"]`. */
|
|
273
|
+
type WhereClause = string;
|
|
186
274
|
declare class Collection<T = unknown> {
|
|
187
275
|
private mneme;
|
|
188
276
|
readonly table: string;
|
|
189
277
|
constructor(mneme: Mneme, table: string);
|
|
278
|
+
/** Insert one row or an array of rows. Returns the inserted rows. */
|
|
190
279
|
insert(rows: T | T[]): Promise<{
|
|
191
280
|
inserted: number;
|
|
192
281
|
rows: T[];
|
|
193
282
|
}>;
|
|
283
|
+
/**
|
|
284
|
+
* List rows. Supports filtering with `where` (PostgREST-style col.op.value),
|
|
285
|
+
* ordering with `order` (e.g. "created_at.desc"), and pagination.
|
|
286
|
+
*
|
|
287
|
+
* Ops: eq, neq, gt, gte, lt, lte, like, ilike, in, is.
|
|
288
|
+
* Example: `m.from("todos").list({ where: ["done.eq.false"], order: "created_at.desc" })`
|
|
289
|
+
*/
|
|
194
290
|
list(opts?: {
|
|
195
291
|
limit?: number;
|
|
196
292
|
offset?: number;
|
|
197
293
|
order?: string;
|
|
294
|
+
where?: WhereClause | WhereClause[];
|
|
198
295
|
}): Promise<{
|
|
199
296
|
rows: T[];
|
|
297
|
+
count: number;
|
|
298
|
+
}>;
|
|
299
|
+
/** Update one row by id. Returns the updated row. */
|
|
300
|
+
update(id: string | number, updates: Partial<T>): Promise<{
|
|
301
|
+
updated: 1;
|
|
302
|
+
row: T;
|
|
303
|
+
}>;
|
|
304
|
+
/** Delete one row by id. */
|
|
305
|
+
delete(id: string | number): Promise<{
|
|
306
|
+
deleted: 1;
|
|
307
|
+
id: number | string;
|
|
308
|
+
}>;
|
|
309
|
+
/**
|
|
310
|
+
* Bulk delete by filter. Refuses to delete the whole table — at least one
|
|
311
|
+
* where clause is required. Returns the count of deleted rows.
|
|
312
|
+
*/
|
|
313
|
+
deleteWhere(where: WhereClause | WhereClause[]): Promise<{
|
|
314
|
+
deleted: number;
|
|
200
315
|
}>;
|
|
201
316
|
}
|
|
202
317
|
|
package/dist/index.js
CHANGED
|
@@ -80,7 +80,13 @@ var Mneme = class {
|
|
|
80
80
|
events;
|
|
81
81
|
kvs;
|
|
82
82
|
constructor(opts) {
|
|
83
|
-
|
|
83
|
+
if ("apiKey" in opts && opts.apiKey) {
|
|
84
|
+
this.auth = { apiKey: opts.apiKey };
|
|
85
|
+
} else if ("accessToken" in opts && opts.accessToken) {
|
|
86
|
+
this.auth = { accessToken: opts.accessToken };
|
|
87
|
+
} else {
|
|
88
|
+
this.auth = { account: opts.account };
|
|
89
|
+
}
|
|
84
90
|
this.gatewayUrl = opts.gatewayUrl.replace(/\/$/, "");
|
|
85
91
|
this.chainId = opts.chainId ?? 8453;
|
|
86
92
|
this.domainName = opts.domainName ?? "Mneme";
|
|
@@ -108,6 +114,50 @@ var Mneme = class {
|
|
|
108
114
|
from(table) {
|
|
109
115
|
return new Collection(this, table);
|
|
110
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Natural-language → SQL via the gateway's LLM proxy.
|
|
119
|
+
* Use the returned SQL with `m.sql(...)` to execute it.
|
|
120
|
+
*/
|
|
121
|
+
llm = {
|
|
122
|
+
sql: (args) => this.request(
|
|
123
|
+
"POST",
|
|
124
|
+
"/v1/llm/sql",
|
|
125
|
+
args
|
|
126
|
+
)
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Service-account API keys — for B2B2C integrators (e.g. Gitlawb) that
|
|
130
|
+
* distribute scoped keys to end-users who don't have wallets.
|
|
131
|
+
*
|
|
132
|
+
* Only callable by wallet-authed clients (keys cannot mint more keys).
|
|
133
|
+
*/
|
|
134
|
+
serviceKeys = {
|
|
135
|
+
/** Mint a new scoped key. Returns the raw key value ONCE. */
|
|
136
|
+
create: (args) => this.request("POST", "/v1/service/keys", args),
|
|
137
|
+
/** List all keys you've created (no raw values — only metadata). */
|
|
138
|
+
list: () => this.request("GET", "/v1/service/keys"),
|
|
139
|
+
/** Revoke a key by id. */
|
|
140
|
+
revoke: (id) => this.request("DELETE", `/v1/service/keys/${id}`)
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Run raw SQL against your project's Postgres schema.
|
|
144
|
+
*
|
|
145
|
+
* Safety guards (server-side):
|
|
146
|
+
* - 5-second statement timeout
|
|
147
|
+
* - search_path pinned to your schema (unqualified table refs resolve to YOUR schema)
|
|
148
|
+
* - cross-tenant schema references are blocked
|
|
149
|
+
* - 1000-row result cap
|
|
150
|
+
* - single statement only
|
|
151
|
+
*
|
|
152
|
+
* Returns rows, column metadata, and elapsed time.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* await m.sql("SELECT count(*) FROM memories");
|
|
156
|
+
* await m.sql("CREATE INDEX ON books (rating)");
|
|
157
|
+
*/
|
|
158
|
+
sql(query) {
|
|
159
|
+
return this.request("POST", "/v1/sql", { query });
|
|
160
|
+
}
|
|
111
161
|
// ─── Storage (Cloudflare R2 backend, $MNEME burn quota) ──────────────────
|
|
112
162
|
storage = {
|
|
113
163
|
upload: async (args) => {
|
|
@@ -155,7 +205,9 @@ var Mneme = class {
|
|
|
155
205
|
async request(method, path, body) {
|
|
156
206
|
const bodyText = body === void 0 ? "" : JSON.stringify(body);
|
|
157
207
|
const headers = { "Content-Type": "application/json" };
|
|
158
|
-
if ("
|
|
208
|
+
if ("apiKey" in this.auth && this.auth.apiKey) {
|
|
209
|
+
headers["Authorization"] = `ApiKey ${this.auth.apiKey}`;
|
|
210
|
+
} else if ("accessToken" in this.auth && this.auth.accessToken) {
|
|
159
211
|
headers["Authorization"] = `Bearer ${this.auth.accessToken}`;
|
|
160
212
|
} else if ("account" in this.auth && this.auth.account) {
|
|
161
213
|
const signed = await signRequest({
|
|
@@ -169,7 +221,7 @@ var Mneme = class {
|
|
|
169
221
|
});
|
|
170
222
|
Object.assign(headers, signed);
|
|
171
223
|
} else {
|
|
172
|
-
throw new Error("Mneme:
|
|
224
|
+
throw new Error("Mneme: one of { account }, { accessToken }, or { apiKey } is required");
|
|
173
225
|
}
|
|
174
226
|
const res = await fetch(`${this.gatewayUrl}${path}`, {
|
|
175
227
|
method,
|
|
@@ -188,6 +240,7 @@ var Collection = class {
|
|
|
188
240
|
}
|
|
189
241
|
mneme;
|
|
190
242
|
table;
|
|
243
|
+
/** Insert one row or an array of rows. Returns the inserted rows. */
|
|
191
244
|
insert(rows) {
|
|
192
245
|
return this.mneme.request(
|
|
193
246
|
"POST",
|
|
@@ -195,14 +248,54 @@ var Collection = class {
|
|
|
195
248
|
rows
|
|
196
249
|
);
|
|
197
250
|
}
|
|
251
|
+
/**
|
|
252
|
+
* List rows. Supports filtering with `where` (PostgREST-style col.op.value),
|
|
253
|
+
* ordering with `order` (e.g. "created_at.desc"), and pagination.
|
|
254
|
+
*
|
|
255
|
+
* Ops: eq, neq, gt, gte, lt, lte, like, ilike, in, is.
|
|
256
|
+
* Example: `m.from("todos").list({ where: ["done.eq.false"], order: "created_at.desc" })`
|
|
257
|
+
*/
|
|
198
258
|
list(opts) {
|
|
199
259
|
const q = new URLSearchParams();
|
|
200
260
|
if (opts?.limit != null) q.set("limit", String(opts.limit));
|
|
201
261
|
if (opts?.offset != null) q.set("offset", String(opts.offset));
|
|
202
262
|
if (opts?.order) q.set("order", opts.order);
|
|
263
|
+
if (opts?.where) {
|
|
264
|
+
const ws = Array.isArray(opts.where) ? opts.where : [opts.where];
|
|
265
|
+
for (const w of ws) q.append("where", w);
|
|
266
|
+
}
|
|
203
267
|
const qs = q.toString() ? `?${q}` : "";
|
|
204
268
|
return this.mneme.request("GET", `/v1/rows/${this.table}${qs}`);
|
|
205
269
|
}
|
|
270
|
+
/** Update one row by id. Returns the updated row. */
|
|
271
|
+
update(id, updates) {
|
|
272
|
+
return this.mneme.request(
|
|
273
|
+
"PATCH",
|
|
274
|
+
`/v1/rows/${this.table}/${id}`,
|
|
275
|
+
updates
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
/** Delete one row by id. */
|
|
279
|
+
delete(id) {
|
|
280
|
+
return this.mneme.request(
|
|
281
|
+
"DELETE",
|
|
282
|
+
`/v1/rows/${this.table}/${id}`
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Bulk delete by filter. Refuses to delete the whole table — at least one
|
|
287
|
+
* where clause is required. Returns the count of deleted rows.
|
|
288
|
+
*/
|
|
289
|
+
deleteWhere(where) {
|
|
290
|
+
const ws = Array.isArray(where) ? where : [where];
|
|
291
|
+
if (ws.length === 0) throw new Error("deleteWhere requires at least one filter");
|
|
292
|
+
const q = new URLSearchParams();
|
|
293
|
+
for (const w of ws) q.append("where", w);
|
|
294
|
+
return this.mneme.request(
|
|
295
|
+
"DELETE",
|
|
296
|
+
`/v1/rows/${this.table}?${q}`
|
|
297
|
+
);
|
|
298
|
+
}
|
|
206
299
|
};
|
|
207
300
|
|
|
208
301
|
// src/types.ts
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mneme-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "TypeScript SDK for Mneme — agent-native Postgres + R2 storage on Base. Wallet-auth, runtime DDL, pgvector, wallet-bound files with $MNEME burn quota.",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "TypeScript SDK for Mneme — agent-native Postgres + R2 storage on Base. Wallet-auth, runtime DDL, full CRUD with WHERE filters, raw SQL, pgvector, service-account API keys for B2B2C integrations, wallet-bound files with $MNEME burn quota.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|