@mindstudio-ai/agent 0.1.17 → 0.1.19
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/cli.js +203 -71
- package/dist/index.d.ts +83 -15
- package/dist/index.js +167 -64
- package/dist/index.js.map +1 -1
- package/dist/postinstall.js +203 -71
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2201,10 +2201,11 @@ var init_query = __esm({
|
|
|
2201
2201
|
limit: this._limit,
|
|
2202
2202
|
offset: this._offset
|
|
2203
2203
|
});
|
|
2204
|
-
return { query, fallbackQuery: null, config: this._config };
|
|
2204
|
+
return { type: "query", query, fallbackQuery: null, config: this._config };
|
|
2205
2205
|
}
|
|
2206
2206
|
const fallbackQuery = buildSelect(this._config.tableName);
|
|
2207
2207
|
return {
|
|
2208
|
+
type: "query",
|
|
2208
2209
|
query: null,
|
|
2209
2210
|
fallbackQuery,
|
|
2210
2211
|
config: this._config,
|
|
@@ -2329,12 +2330,96 @@ var init_query = __esm({
|
|
|
2329
2330
|
}
|
|
2330
2331
|
});
|
|
2331
2332
|
|
|
2333
|
+
// src/db/mutation.ts
|
|
2334
|
+
var Mutation;
|
|
2335
|
+
var init_mutation = __esm({
|
|
2336
|
+
"src/db/mutation.ts"() {
|
|
2337
|
+
"use strict";
|
|
2338
|
+
Mutation = class _Mutation {
|
|
2339
|
+
/** @internal */
|
|
2340
|
+
_config;
|
|
2341
|
+
/** @internal */
|
|
2342
|
+
_queries;
|
|
2343
|
+
/** @internal */
|
|
2344
|
+
_processResult;
|
|
2345
|
+
/** @internal Non-batchable executor for complex mutations (e.g. removeAll JS fallback). */
|
|
2346
|
+
_executor;
|
|
2347
|
+
constructor(config, queries, processResult) {
|
|
2348
|
+
this._config = config;
|
|
2349
|
+
this._queries = queries;
|
|
2350
|
+
this._processResult = processResult;
|
|
2351
|
+
this._executor = void 0;
|
|
2352
|
+
}
|
|
2353
|
+
/**
|
|
2354
|
+
* Create a non-batchable mutation that wraps an async executor.
|
|
2355
|
+
* Used for operations that require multi-step execution (e.g. removeAll
|
|
2356
|
+
* with a JS-fallback predicate: fetch all rows → filter → delete).
|
|
2357
|
+
*
|
|
2358
|
+
* Works fine when awaited standalone. Throws if passed to db.batch().
|
|
2359
|
+
*
|
|
2360
|
+
* @internal
|
|
2361
|
+
*/
|
|
2362
|
+
static fromExecutor(config, executor) {
|
|
2363
|
+
const m = new _Mutation(config, [], () => void 0);
|
|
2364
|
+
Object.defineProperty(m, "_executor", { value: executor });
|
|
2365
|
+
return m;
|
|
2366
|
+
}
|
|
2367
|
+
// -------------------------------------------------------------------------
|
|
2368
|
+
// PromiseLike — executes on await
|
|
2369
|
+
// -------------------------------------------------------------------------
|
|
2370
|
+
then(onfulfilled, onrejected) {
|
|
2371
|
+
return this._execute().then(onfulfilled, onrejected);
|
|
2372
|
+
}
|
|
2373
|
+
// -------------------------------------------------------------------------
|
|
2374
|
+
// Batch compilation — used by db.batch()
|
|
2375
|
+
// -------------------------------------------------------------------------
|
|
2376
|
+
/**
|
|
2377
|
+
* @internal Compile this mutation into SQL for batch execution.
|
|
2378
|
+
* Returns the queries and a result processor.
|
|
2379
|
+
*
|
|
2380
|
+
* Throws if this is a non-batchable mutation (created via fromExecutor).
|
|
2381
|
+
*/
|
|
2382
|
+
_compile() {
|
|
2383
|
+
if (this._executor) {
|
|
2384
|
+
throw new Error(
|
|
2385
|
+
"This operation cannot be batched (e.g. removeAll with a predicate that cannot compile to SQL). Await it separately."
|
|
2386
|
+
);
|
|
2387
|
+
}
|
|
2388
|
+
return {
|
|
2389
|
+
type: "mutation",
|
|
2390
|
+
queries: this._queries,
|
|
2391
|
+
config: this._config,
|
|
2392
|
+
processResult: this._processResult
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
/**
|
|
2396
|
+
* @internal Process raw SQL results into the typed result.
|
|
2397
|
+
* Used by db.batch() after executing the compiled queries.
|
|
2398
|
+
*/
|
|
2399
|
+
static _processResults(results, compiled) {
|
|
2400
|
+
return compiled.processResult(results);
|
|
2401
|
+
}
|
|
2402
|
+
// -------------------------------------------------------------------------
|
|
2403
|
+
// Execution
|
|
2404
|
+
// -------------------------------------------------------------------------
|
|
2405
|
+
async _execute() {
|
|
2406
|
+
if (this._executor) {
|
|
2407
|
+
return this._executor();
|
|
2408
|
+
}
|
|
2409
|
+
const results = await this._config.executeBatch(this._queries);
|
|
2410
|
+
return this._processResult(results);
|
|
2411
|
+
}
|
|
2412
|
+
};
|
|
2413
|
+
}
|
|
2414
|
+
});
|
|
2415
|
+
|
|
2332
2416
|
// src/db/table.ts
|
|
2333
2417
|
var Table;
|
|
2334
2418
|
var init_table = __esm({
|
|
2335
2419
|
"src/db/table.ts"() {
|
|
2336
2420
|
"use strict";
|
|
2337
2421
|
init_query();
|
|
2422
|
+
init_mutation();
|
|
2338
2423
|
init_predicate();
|
|
2339
2424
|
init_sql();
|
|
2340
2425
|
Table = class {
|
|
@@ -2399,7 +2484,7 @@ var init_table = __esm({
|
|
|
2399
2484
|
sortBy(accessor) {
|
|
2400
2485
|
return new Query(this._config).sortBy(accessor);
|
|
2401
2486
|
}
|
|
2402
|
-
|
|
2487
|
+
push(data) {
|
|
2403
2488
|
const isArray = Array.isArray(data);
|
|
2404
2489
|
const items = isArray ? data : [data];
|
|
2405
2490
|
const queries = items.map(
|
|
@@ -2409,71 +2494,76 @@ var init_table = __esm({
|
|
|
2409
2494
|
this._config.columns
|
|
2410
2495
|
)
|
|
2411
2496
|
);
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2497
|
+
return new Mutation(this._config, queries, (results) => {
|
|
2498
|
+
const rows = results.map((r) => {
|
|
2499
|
+
if (r.rows.length > 0) {
|
|
2500
|
+
return deserializeRow(
|
|
2501
|
+
r.rows[0],
|
|
2502
|
+
this._config.columns
|
|
2503
|
+
);
|
|
2504
|
+
}
|
|
2505
|
+
return void 0;
|
|
2506
|
+
});
|
|
2507
|
+
return isArray ? rows : rows[0];
|
|
2421
2508
|
});
|
|
2422
|
-
return isArray ? rows : rows[0];
|
|
2423
2509
|
}
|
|
2424
2510
|
/**
|
|
2425
2511
|
* Update a row by ID. Only the provided fields are changed.
|
|
2426
2512
|
* Returns the updated row via `UPDATE ... RETURNING *`.
|
|
2427
2513
|
*/
|
|
2428
|
-
|
|
2514
|
+
update(id, data) {
|
|
2429
2515
|
const query = buildUpdate(
|
|
2430
2516
|
this._config.tableName,
|
|
2431
2517
|
id,
|
|
2432
2518
|
data,
|
|
2433
2519
|
this._config.columns
|
|
2434
2520
|
);
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2521
|
+
return new Mutation(
|
|
2522
|
+
this._config,
|
|
2523
|
+
[query],
|
|
2524
|
+
(results) => deserializeRow(
|
|
2525
|
+
results[0].rows[0],
|
|
2526
|
+
this._config.columns
|
|
2527
|
+
)
|
|
2439
2528
|
);
|
|
2440
2529
|
}
|
|
2441
|
-
|
|
2530
|
+
remove(id) {
|
|
2442
2531
|
const query = buildDelete(this._config.tableName, `id = ?`, [id]);
|
|
2443
|
-
|
|
2532
|
+
return new Mutation(this._config, [query], () => void 0);
|
|
2444
2533
|
}
|
|
2445
2534
|
/**
|
|
2446
2535
|
* Remove all rows matching a predicate. Returns the count removed.
|
|
2447
2536
|
*/
|
|
2448
|
-
|
|
2537
|
+
removeAll(predicate) {
|
|
2449
2538
|
const compiled = compilePredicate(predicate);
|
|
2450
2539
|
if (compiled.type === "sql") {
|
|
2451
2540
|
const query = buildDelete(this._config.tableName, compiled.where);
|
|
2452
|
-
|
|
2453
|
-
return results[0].changes;
|
|
2454
|
-
}
|
|
2455
|
-
console.warn(
|
|
2456
|
-
`[mindstudio] removeAll predicate on ${this._config.tableName} could not be compiled to SQL \u2014 fetching all rows first`
|
|
2457
|
-
);
|
|
2458
|
-
const allQuery = buildSelect(this._config.tableName);
|
|
2459
|
-
const allResults = await this._config.executeBatch([allQuery]);
|
|
2460
|
-
const allRows = allResults[0].rows.map(
|
|
2461
|
-
(r) => deserializeRow(
|
|
2462
|
-
r,
|
|
2463
|
-
this._config.columns
|
|
2464
|
-
)
|
|
2465
|
-
);
|
|
2466
|
-
const matching = allRows.filter((row) => predicate(row));
|
|
2467
|
-
if (matching.length === 0) return 0;
|
|
2468
|
-
const deleteQueries = matching.filter((row) => row.id).map((row) => buildDelete(this._config.tableName, `id = ?`, [row.id]));
|
|
2469
|
-
if (deleteQueries.length > 0) {
|
|
2470
|
-
await this._config.executeBatch(deleteQueries);
|
|
2541
|
+
return new Mutation(this._config, [query], (results) => results[0].changes);
|
|
2471
2542
|
}
|
|
2472
|
-
return
|
|
2543
|
+
return Mutation.fromExecutor(this._config, async () => {
|
|
2544
|
+
console.warn(
|
|
2545
|
+
`[mindstudio] removeAll predicate on ${this._config.tableName} could not be compiled to SQL \u2014 fetching all rows first`
|
|
2546
|
+
);
|
|
2547
|
+
const allQuery = buildSelect(this._config.tableName);
|
|
2548
|
+
const allResults = await this._config.executeBatch([allQuery]);
|
|
2549
|
+
const allRows = allResults[0].rows.map(
|
|
2550
|
+
(r) => deserializeRow(
|
|
2551
|
+
r,
|
|
2552
|
+
this._config.columns
|
|
2553
|
+
)
|
|
2554
|
+
);
|
|
2555
|
+
const matching = allRows.filter((row) => predicate(row));
|
|
2556
|
+
if (matching.length === 0) return 0;
|
|
2557
|
+
const deleteQueries = matching.filter((row) => row.id).map((row) => buildDelete(this._config.tableName, `id = ?`, [row.id]));
|
|
2558
|
+
if (deleteQueries.length > 0) {
|
|
2559
|
+
await this._config.executeBatch(deleteQueries);
|
|
2560
|
+
}
|
|
2561
|
+
return matching.length;
|
|
2562
|
+
});
|
|
2473
2563
|
}
|
|
2474
|
-
|
|
2564
|
+
clear() {
|
|
2475
2565
|
const query = buildDelete(this._config.tableName);
|
|
2476
|
-
|
|
2566
|
+
return new Mutation(this._config, [query], () => void 0);
|
|
2477
2567
|
}
|
|
2478
2568
|
};
|
|
2479
2569
|
}
|
|
@@ -2501,44 +2591,64 @@ function createDb(databases, executeBatch) {
|
|
|
2501
2591
|
ago: (ms) => Date.now() - ms,
|
|
2502
2592
|
fromNow: (ms) => Date.now() + ms,
|
|
2503
2593
|
// --- Batch execution ---
|
|
2504
|
-
batch: ((...
|
|
2594
|
+
batch: ((...operations) => {
|
|
2505
2595
|
return (async () => {
|
|
2506
|
-
const compiled =
|
|
2507
|
-
if (
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
);
|
|
2596
|
+
const compiled = operations.map((op) => {
|
|
2597
|
+
if (op instanceof Query) {
|
|
2598
|
+
return op._compile();
|
|
2599
|
+
}
|
|
2600
|
+
if (op instanceof Mutation) {
|
|
2601
|
+
return op._compile();
|
|
2513
2602
|
}
|
|
2514
|
-
|
|
2603
|
+
throw new MindStudioError(
|
|
2604
|
+
"db.batch() only accepts Query and Mutation objects (from .filter(), .update(), .push(), etc.)",
|
|
2605
|
+
"invalid_batch_operation",
|
|
2606
|
+
400
|
|
2607
|
+
);
|
|
2515
2608
|
});
|
|
2516
2609
|
const groups = /* @__PURE__ */ new Map();
|
|
2517
2610
|
for (let i = 0; i < compiled.length; i++) {
|
|
2518
2611
|
const c = compiled[i];
|
|
2519
2612
|
const dbId = c.config.databaseId;
|
|
2520
|
-
const sqlQuery = c.query ?? c.fallbackQuery;
|
|
2521
2613
|
if (!groups.has(dbId)) groups.set(dbId, []);
|
|
2522
|
-
|
|
2614
|
+
if (c.type === "query") {
|
|
2615
|
+
const sqlQuery = c.query ?? c.fallbackQuery;
|
|
2616
|
+
groups.get(dbId).push({ opIndex: i, sqlQueries: [sqlQuery] });
|
|
2617
|
+
} else {
|
|
2618
|
+
groups.get(dbId).push({ opIndex: i, sqlQueries: c.queries });
|
|
2619
|
+
}
|
|
2523
2620
|
}
|
|
2524
|
-
const
|
|
2621
|
+
const opResults = /* @__PURE__ */ new Map();
|
|
2525
2622
|
await Promise.all(
|
|
2526
2623
|
Array.from(groups.entries()).map(async ([dbId, entries]) => {
|
|
2527
|
-
const
|
|
2528
|
-
const
|
|
2529
|
-
for (
|
|
2530
|
-
|
|
2624
|
+
const flatQueries = [];
|
|
2625
|
+
const slices = [];
|
|
2626
|
+
for (const entry of entries) {
|
|
2627
|
+
slices.push({
|
|
2628
|
+
opIndex: entry.opIndex,
|
|
2629
|
+
start: flatQueries.length,
|
|
2630
|
+
count: entry.sqlQueries.length
|
|
2631
|
+
});
|
|
2632
|
+
flatQueries.push(...entry.sqlQueries);
|
|
2633
|
+
}
|
|
2634
|
+
const results = await executeBatch(dbId, flatQueries);
|
|
2635
|
+
for (const { opIndex, start, count } of slices) {
|
|
2636
|
+
opResults.set(opIndex, results.slice(start, start + count));
|
|
2531
2637
|
}
|
|
2532
2638
|
})
|
|
2533
2639
|
);
|
|
2534
2640
|
return compiled.map((c, i) => {
|
|
2535
|
-
const
|
|
2536
|
-
if (
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2641
|
+
const results = opResults.get(i);
|
|
2642
|
+
if (c.type === "query") {
|
|
2643
|
+
if (!c.query && c.predicates?.length) {
|
|
2644
|
+
console.warn(
|
|
2645
|
+
`[mindstudio] db.batch(): filter on ${c.config.tableName} could not be compiled to SQL \u2014 processing in JS`
|
|
2646
|
+
);
|
|
2647
|
+
}
|
|
2648
|
+
return Query._processResults(results[0], c);
|
|
2649
|
+
} else {
|
|
2650
|
+
return Mutation._processResults(results, c);
|
|
2540
2651
|
}
|
|
2541
|
-
return Query._processResults(result, c);
|
|
2542
2652
|
});
|
|
2543
2653
|
})();
|
|
2544
2654
|
})
|
|
@@ -2597,6 +2707,7 @@ var init_db = __esm({
|
|
|
2597
2707
|
init_errors();
|
|
2598
2708
|
init_table();
|
|
2599
2709
|
init_query();
|
|
2710
|
+
init_mutation();
|
|
2600
2711
|
init_table();
|
|
2601
2712
|
}
|
|
2602
2713
|
});
|
|
@@ -4282,15 +4393,24 @@ function summarizeInput(input) {
|
|
|
4282
4393
|
}
|
|
4283
4394
|
async function cmdAsk(question, options) {
|
|
4284
4395
|
try {
|
|
4396
|
+
let lineBuffer = "";
|
|
4285
4397
|
const response = await runAsk(question, options, (event) => {
|
|
4286
4398
|
switch (event.type) {
|
|
4287
4399
|
case "text":
|
|
4288
|
-
|
|
4400
|
+
lineBuffer += event.text;
|
|
4401
|
+
while (lineBuffer.includes("\n")) {
|
|
4402
|
+
const idx = lineBuffer.indexOf("\n");
|
|
4403
|
+
process.stderr.write(lineBuffer.slice(0, idx + 1));
|
|
4404
|
+
lineBuffer = lineBuffer.slice(idx + 1);
|
|
4405
|
+
}
|
|
4289
4406
|
break;
|
|
4290
4407
|
case "tool_start":
|
|
4408
|
+
if (lineBuffer) {
|
|
4409
|
+
process.stderr.write(lineBuffer + "\n");
|
|
4410
|
+
lineBuffer = "";
|
|
4411
|
+
}
|
|
4291
4412
|
process.stderr.write(
|
|
4292
|
-
`
|
|
4293
|
-
${ansi.cyan("\u27E1")} ${ansi.bold(event.name)} ${ansi.dim(summarizeInput(event.input))}
|
|
4413
|
+
` ${ansi.cyan("\u27E1")} ${ansi.bold(event.name)} ${ansi.dim(summarizeInput(event.input))}
|
|
4294
4414
|
`
|
|
4295
4415
|
);
|
|
4296
4416
|
break;
|
|
@@ -4298,6 +4418,9 @@ async function cmdAsk(question, options) {
|
|
|
4298
4418
|
break;
|
|
4299
4419
|
}
|
|
4300
4420
|
});
|
|
4421
|
+
if (lineBuffer) {
|
|
4422
|
+
process.stderr.write(lineBuffer);
|
|
4423
|
+
}
|
|
4301
4424
|
if (process.stdout.isTTY) {
|
|
4302
4425
|
process.stderr.write("\n");
|
|
4303
4426
|
} else {
|
|
@@ -4389,7 +4512,7 @@ async function startMcpServer(options) {
|
|
|
4389
4512
|
capabilities: { tools: {} },
|
|
4390
4513
|
serverInfo: {
|
|
4391
4514
|
name: "mindstudio-agent",
|
|
4392
|
-
version: "0.1.
|
|
4515
|
+
version: "0.1.19"
|
|
4393
4516
|
},
|
|
4394
4517
|
instructions: 'Welcome to MindStudio \u2014 a platform with 200+ AI models, 850+ third-party integrations, and pre-built agents.\n\nGetting started:\n1. Call `ask` with any question about the SDK \u2014 it knows every action, model, and connector and returns working code with real model IDs and config options. Examples: ask("generate an image with FLUX"), ask("what models support vision?"), ask("how do I send a Slack message?").\n2. Call `changeName` to set your display name \u2014 use your name or whatever your user calls you. This is how you\'ll appear in MindStudio request logs.\n3. If you have a profile picture or icon, call `uploadFile` to upload it, then `changeProfilePicture` with the returned URL.\n4. For manual browsing, call `listActions` to discover all available actions.\n\nThen use the tools to generate text, images, video, audio, search the web, work with data sources, run agents, and more.\n\nImportant:\n- AI-powered actions (text generation, image generation, video, audio, etc.) cost money. Before running these, call `estimateActionCost` and confirm with the user before proceeding \u2014 unless they\'ve explicitly told you to go ahead.\n- Not all agents from `listAgents` are configured for API use. Do not try to run an agent just because it appears in the list \u2014 it will likely fail. Only run agents the user specifically asks you to run.'
|
|
4395
4518
|
});
|
|
@@ -5323,7 +5446,7 @@ function isNewerVersion(current, latest) {
|
|
|
5323
5446
|
return false;
|
|
5324
5447
|
}
|
|
5325
5448
|
async function checkForUpdate() {
|
|
5326
|
-
const currentVersion = "0.1.
|
|
5449
|
+
const currentVersion = "0.1.19";
|
|
5327
5450
|
if (!currentVersion) return null;
|
|
5328
5451
|
try {
|
|
5329
5452
|
const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
@@ -5352,7 +5475,7 @@ async function checkForUpdate() {
|
|
|
5352
5475
|
}
|
|
5353
5476
|
}
|
|
5354
5477
|
function printUpdateNotice(latestVersion) {
|
|
5355
|
-
const currentVersion = "0.1.
|
|
5478
|
+
const currentVersion = "0.1.19";
|
|
5356
5479
|
process.stderr.write(
|
|
5357
5480
|
`
|
|
5358
5481
|
${ansi2.cyanBright("Update available")} ${ansi2.gray(currentVersion + " \u2192")} ${ansi2.cyanBold(latestVersion)}
|
|
@@ -5427,7 +5550,7 @@ async function cmdLogin(options) {
|
|
|
5427
5550
|
process.stderr.write("\n");
|
|
5428
5551
|
printLogo();
|
|
5429
5552
|
process.stderr.write("\n");
|
|
5430
|
-
const ver = "0.1.
|
|
5553
|
+
const ver = "0.1.19";
|
|
5431
5554
|
process.stderr.write(
|
|
5432
5555
|
` ${ansi2.bold("MindStudio Agent")} ${ver ? " " + ansi2.gray("v" + ver) : ""}
|
|
5433
5556
|
`
|
|
@@ -5513,6 +5636,9 @@ async function cmdLogin(options) {
|
|
|
5513
5636
|
${ansi2.bold("Using with Claude Code?")} Run once to enable the MCP server:
|
|
5514
5637
|
${ansi2.cyan("claude mcp add mindstudio -- mindstudio mcp")}
|
|
5515
5638
|
|
|
5639
|
+
${ansi2.bold("Need help?")} Ask the SDK anything:
|
|
5640
|
+
${ansi2.cyan('mindstudio ask "how do I generate an image?"')}
|
|
5641
|
+
|
|
5516
5642
|
`
|
|
5517
5643
|
);
|
|
5518
5644
|
return;
|
|
@@ -5735,6 +5861,12 @@ async function main() {
|
|
|
5735
5861
|
const command = positionals[0];
|
|
5736
5862
|
const updatePromise = command !== "mcp" && command !== "login" ? checkForUpdate() : Promise.resolve(null);
|
|
5737
5863
|
try {
|
|
5864
|
+
if (command === "version" || command === "-v") {
|
|
5865
|
+
process.stdout.write(
|
|
5866
|
+
"0.1.19\n"
|
|
5867
|
+
);
|
|
5868
|
+
return;
|
|
5869
|
+
}
|
|
5738
5870
|
if (command === "login") {
|
|
5739
5871
|
await cmdLogin({
|
|
5740
5872
|
baseUrl: values["base-url"]
|
package/dist/index.d.ts
CHANGED
|
@@ -726,6 +726,7 @@ declare class Query<T> implements PromiseLike<T[]> {
|
|
|
726
726
|
* (fast path) or a fallback SELECT * with JS processing metadata.
|
|
727
727
|
*/
|
|
728
728
|
interface CompiledQuery<T> {
|
|
729
|
+
type: 'query';
|
|
729
730
|
/** Compiled SQL query, or null if JS fallback needed. */
|
|
730
731
|
query: SqlQuery | null;
|
|
731
732
|
/** SELECT * fallback query, or null if SQL compiled. */
|
|
@@ -744,12 +745,76 @@ interface CompiledQuery<T> {
|
|
|
744
745
|
offset?: number;
|
|
745
746
|
}
|
|
746
747
|
|
|
748
|
+
/**
|
|
749
|
+
* Mutation<T> — a lazy write operation backed by SQLite.
|
|
750
|
+
*
|
|
751
|
+
* Created by Table write methods (push, update, remove, removeAll, clear).
|
|
752
|
+
* Like Query, implements PromiseLike so `await` triggers execution. Unlike
|
|
753
|
+
* Query, there's no chaining — a Mutation is a fixed set of SQL statements
|
|
754
|
+
* with a result processor.
|
|
755
|
+
*
|
|
756
|
+
* ## Batch support
|
|
757
|
+
*
|
|
758
|
+
* `db.batch()` calls `_compile()` to extract the SQL without executing,
|
|
759
|
+
* then bundles it with other operations into a single round trip. After
|
|
760
|
+
* execution, `_processResults()` deserializes the raw SQL results.
|
|
761
|
+
*
|
|
762
|
+
* ## Non-batchable mutations
|
|
763
|
+
*
|
|
764
|
+
* Some mutations (e.g. `removeAll` with a JS-fallback predicate) require
|
|
765
|
+
* multi-step execution that can't be expressed as a fixed SQL batch.
|
|
766
|
+
* These are created via `Mutation.fromExecutor()` and work fine when
|
|
767
|
+
* awaited standalone, but throw if passed to `db.batch()`.
|
|
768
|
+
*/
|
|
769
|
+
|
|
770
|
+
interface CompiledMutation<TResult> {
|
|
771
|
+
type: 'mutation';
|
|
772
|
+
queries: SqlQuery[];
|
|
773
|
+
config: TableConfig;
|
|
774
|
+
processResult: (results: SqlResult[]) => TResult;
|
|
775
|
+
}
|
|
776
|
+
declare class Mutation<TResult> implements PromiseLike<TResult> {
|
|
777
|
+
/** @internal */
|
|
778
|
+
private readonly _config;
|
|
779
|
+
/** @internal */
|
|
780
|
+
private readonly _queries;
|
|
781
|
+
/** @internal */
|
|
782
|
+
private readonly _processResult;
|
|
783
|
+
/** @internal Non-batchable executor for complex mutations (e.g. removeAll JS fallback). */
|
|
784
|
+
private readonly _executor;
|
|
785
|
+
constructor(config: TableConfig, queries: SqlQuery[], processResult: (results: SqlResult[]) => TResult);
|
|
786
|
+
/**
|
|
787
|
+
* Create a non-batchable mutation that wraps an async executor.
|
|
788
|
+
* Used for operations that require multi-step execution (e.g. removeAll
|
|
789
|
+
* with a JS-fallback predicate: fetch all rows → filter → delete).
|
|
790
|
+
*
|
|
791
|
+
* Works fine when awaited standalone. Throws if passed to db.batch().
|
|
792
|
+
*
|
|
793
|
+
* @internal
|
|
794
|
+
*/
|
|
795
|
+
static fromExecutor<T>(config: TableConfig, executor: () => Promise<T>): Mutation<T>;
|
|
796
|
+
then<T1 = TResult, T2 = never>(onfulfilled?: ((value: TResult) => T1 | PromiseLike<T1>) | null, onrejected?: ((reason: unknown) => T2 | PromiseLike<T2>) | null): Promise<T1 | T2>;
|
|
797
|
+
/**
|
|
798
|
+
* @internal Compile this mutation into SQL for batch execution.
|
|
799
|
+
* Returns the queries and a result processor.
|
|
800
|
+
*
|
|
801
|
+
* Throws if this is a non-batchable mutation (created via fromExecutor).
|
|
802
|
+
*/
|
|
803
|
+
_compile(): CompiledMutation<TResult>;
|
|
804
|
+
/**
|
|
805
|
+
* @internal Process raw SQL results into the typed result.
|
|
806
|
+
* Used by db.batch() after executing the compiled queries.
|
|
807
|
+
*/
|
|
808
|
+
static _processResults<T>(results: SqlResult[], compiled: CompiledMutation<T>): T;
|
|
809
|
+
private _execute;
|
|
810
|
+
}
|
|
811
|
+
|
|
747
812
|
/**
|
|
748
813
|
* Table<T> — a typed persistent collection backed by SQLite.
|
|
749
814
|
*
|
|
750
815
|
* Created via `db.defineTable<T>(name)`. Every method either returns a
|
|
751
|
-
* chainable Query<T> (for lazy reads)
|
|
752
|
-
*
|
|
816
|
+
* chainable Query<T> (for lazy reads), a Mutation<T> (for lazy writes),
|
|
817
|
+
* or a Promise (for terminal reads).
|
|
753
818
|
*
|
|
754
819
|
* ## Write operations use RETURNING
|
|
755
820
|
*
|
|
@@ -781,19 +846,19 @@ declare class Table<T> {
|
|
|
781
846
|
* Uses `INSERT ... RETURNING *` so the created row comes back in a
|
|
782
847
|
* single round trip — no separate SELECT needed.
|
|
783
848
|
*/
|
|
784
|
-
push(data: PushInput<T>):
|
|
785
|
-
push(data: PushInput<T>[]):
|
|
849
|
+
push(data: PushInput<T>): Mutation<T>;
|
|
850
|
+
push(data: PushInput<T>[]): Mutation<T[]>;
|
|
786
851
|
/**
|
|
787
852
|
* Update a row by ID. Only the provided fields are changed.
|
|
788
853
|
* Returns the updated row via `UPDATE ... RETURNING *`.
|
|
789
854
|
*/
|
|
790
|
-
update(id: string, data: UpdateInput<T>):
|
|
791
|
-
remove(id: string):
|
|
855
|
+
update(id: string, data: UpdateInput<T>): Mutation<T>;
|
|
856
|
+
remove(id: string): Mutation<void>;
|
|
792
857
|
/**
|
|
793
858
|
* Remove all rows matching a predicate. Returns the count removed.
|
|
794
859
|
*/
|
|
795
|
-
removeAll(predicate: Predicate<T>):
|
|
796
|
-
clear():
|
|
860
|
+
removeAll(predicate: Predicate<T>): Mutation<number>;
|
|
861
|
+
clear(): Mutation<void>;
|
|
797
862
|
}
|
|
798
863
|
|
|
799
864
|
/**
|
|
@@ -904,18 +969,21 @@ interface Db {
|
|
|
904
969
|
/** Returns a unix timestamp for (now + duration). Use with days/hours/minutes. */
|
|
905
970
|
fromNow(ms: number): number;
|
|
906
971
|
/**
|
|
907
|
-
* Execute multiple
|
|
908
|
-
* the same database connection, eliminating
|
|
972
|
+
* Execute multiple reads and writes in a single round trip. All
|
|
973
|
+
* operations run on the same database connection, eliminating
|
|
974
|
+
* per-operation HTTP overhead. Writes execute in argument order.
|
|
909
975
|
*
|
|
910
|
-
* Accepts Query objects (
|
|
976
|
+
* Accepts Query objects (reads) and Mutation objects (writes from
|
|
977
|
+
* push, update, remove, removeAll, clear). Compiles them to SQL,
|
|
911
978
|
* sends all in one batch request, and returns typed results.
|
|
912
979
|
*
|
|
913
980
|
* @example
|
|
914
981
|
* ```ts
|
|
915
|
-
*
|
|
916
|
-
*
|
|
917
|
-
*
|
|
918
|
-
*
|
|
982
|
+
* // Mixed reads and writes in one round trip
|
|
983
|
+
* const [, newCard, cards] = await db.batch(
|
|
984
|
+
* Cards.update(card1.id, { position: 1 }),
|
|
985
|
+
* Cards.push({ title: 'New', columnId, position: 0 }),
|
|
986
|
+
* Cards.filter(c => c.columnId === columnId),
|
|
919
987
|
* );
|
|
920
988
|
* ```
|
|
921
989
|
*/
|