@mastra/libsql 1.9.1 → 1.10.0-alpha.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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @mastra/libsql
2
2
 
3
+ ## 1.10.0-alpha.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added the `schedules` storage domain so LibSQL-backed Mastra apps can use scheduled workflows. Creates `mastra_schedules` and `mastra_schedule_triggers` tables on init. ([#15830](https://github.com/mastra-ai/mastra/pull/15830))
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`c05c9a1`](https://github.com/mastra-ai/mastra/commit/c05c9a13230988cef6d438a62f37760f31927bc7), [`e24aacb`](https://github.com/mastra-ai/mastra/commit/e24aacba07bd66f5d95b636dc24016fca26b52cf), [`c721164`](https://github.com/mastra-ai/mastra/commit/c7211643f7ac861f83b19a3757cc921487fc9d75), [`1b55954`](https://github.com/mastra-ai/mastra/commit/1b559541c1e08a10e49d01ffc51a634dfc37a286), [`5adc55e`](https://github.com/mastra-ai/mastra/commit/5adc55e63407be8ee977914957d68bcc2a075ceb), [`70017d7`](https://github.com/mastra-ai/mastra/commit/70017d72ab741b5d7040e2a15c251a317782e39e), [`e4942bc`](https://github.com/mastra-ai/mastra/commit/e4942bc7fdc903572f7d84f26d5e15f9d39c763d)]:
12
+ - @mastra/core@1.32.0-alpha.1
13
+
3
14
  ## 1.9.1
4
15
 
5
16
  ### Patch Changes
@@ -3,7 +3,7 @@ name: mastra-libsql
3
3
  description: Documentation for @mastra/libsql. Use when working with @mastra/libsql APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/libsql"
6
- version: "1.9.1"
6
+ version: "1.10.0-alpha.0"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.9.1",
2
+ "version": "1.10.0-alpha.0",
3
3
  "package": "@mastra/libsql",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -8896,6 +8896,233 @@ var PromptBlocksLibSQL = class extends storage.PromptBlocksStorage {
8896
8896
  };
8897
8897
  }
8898
8898
  };
8899
+ function parseJson2(val) {
8900
+ if (val == null) return void 0;
8901
+ if (typeof val === "string") {
8902
+ try {
8903
+ return JSON.parse(val);
8904
+ } catch {
8905
+ return val;
8906
+ }
8907
+ }
8908
+ return val;
8909
+ }
8910
+ function toNumber(val) {
8911
+ if (typeof val === "bigint") return Number(val);
8912
+ return Number(val);
8913
+ }
8914
+ function rowToSchedule(row) {
8915
+ const target = parseJson2(row.target);
8916
+ if (!target) {
8917
+ throw new Error(`Schedule row ${row.id} has invalid target`);
8918
+ }
8919
+ const schedule = {
8920
+ id: String(row.id),
8921
+ target,
8922
+ cron: String(row.cron),
8923
+ status: String(row.status),
8924
+ nextFireAt: toNumber(row.next_fire_at),
8925
+ createdAt: toNumber(row.created_at),
8926
+ updatedAt: toNumber(row.updated_at)
8927
+ };
8928
+ if (row.timezone != null) schedule.timezone = String(row.timezone);
8929
+ if (row.last_fire_at != null) schedule.lastFireAt = toNumber(row.last_fire_at);
8930
+ if (row.last_run_id != null) schedule.lastRunId = String(row.last_run_id);
8931
+ const metadata = parseJson2(row.metadata);
8932
+ if (metadata !== void 0) schedule.metadata = metadata;
8933
+ return schedule;
8934
+ }
8935
+ function rowToTrigger(row) {
8936
+ const trigger = {
8937
+ scheduleId: String(row.schedule_id),
8938
+ runId: String(row.run_id),
8939
+ scheduledFireAt: toNumber(row.scheduled_fire_at),
8940
+ actualFireAt: toNumber(row.actual_fire_at),
8941
+ status: String(row.status)
8942
+ };
8943
+ if (row.error != null) trigger.error = String(row.error);
8944
+ return trigger;
8945
+ }
8946
+ var SchedulesLibSQL = class extends storage.SchedulesStorage {
8947
+ #db;
8948
+ #client;
8949
+ constructor(config) {
8950
+ super();
8951
+ const client = resolveClient(config);
8952
+ this.#client = client;
8953
+ this.#db = new LibSQLDB({ client, maxRetries: config.maxRetries, initialBackoffMs: config.initialBackoffMs });
8954
+ }
8955
+ async init() {
8956
+ await this.#db.createTable({
8957
+ tableName: storage.TABLE_SCHEDULES,
8958
+ schema: storage.TABLE_SCHEMAS[storage.TABLE_SCHEDULES]
8959
+ });
8960
+ await this.#db.createTable({
8961
+ tableName: storage.TABLE_SCHEDULE_TRIGGERS,
8962
+ schema: storage.TABLE_SCHEMAS[storage.TABLE_SCHEDULE_TRIGGERS]
8963
+ });
8964
+ }
8965
+ async dangerouslyClearAll() {
8966
+ await this.#db.deleteData({ tableName: storage.TABLE_SCHEDULE_TRIGGERS });
8967
+ await this.#db.deleteData({ tableName: storage.TABLE_SCHEDULES });
8968
+ }
8969
+ async createSchedule(schedule) {
8970
+ const existing = await this.getSchedule(schedule.id);
8971
+ if (existing) {
8972
+ throw new Error(`Schedule with id "${schedule.id}" already exists`);
8973
+ }
8974
+ await this.#db.insert({
8975
+ tableName: storage.TABLE_SCHEDULES,
8976
+ record: {
8977
+ id: schedule.id,
8978
+ target: schedule.target,
8979
+ cron: schedule.cron,
8980
+ timezone: schedule.timezone ?? null,
8981
+ status: schedule.status,
8982
+ next_fire_at: schedule.nextFireAt,
8983
+ last_fire_at: schedule.lastFireAt ?? null,
8984
+ last_run_id: schedule.lastRunId ?? null,
8985
+ created_at: schedule.createdAt,
8986
+ updated_at: schedule.updatedAt,
8987
+ metadata: schedule.metadata ?? null
8988
+ }
8989
+ });
8990
+ return schedule;
8991
+ }
8992
+ async getSchedule(id) {
8993
+ const result = await this.#client.execute({
8994
+ sql: `SELECT ${buildSelectColumns(storage.TABLE_SCHEDULES)} FROM ${storage.TABLE_SCHEDULES} WHERE id = ?`,
8995
+ args: [id]
8996
+ });
8997
+ const row = result.rows[0];
8998
+ return row ? rowToSchedule(row) : null;
8999
+ }
9000
+ async listSchedules(filter) {
9001
+ const conditions = [];
9002
+ const params = [];
9003
+ if (filter?.status) {
9004
+ conditions.push("status = ?");
9005
+ params.push(filter.status);
9006
+ }
9007
+ if (filter?.workflowId) {
9008
+ conditions.push("json_extract(target, '$.workflowId') = ?");
9009
+ params.push(filter.workflowId);
9010
+ }
9011
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
9012
+ const result = await this.#client.execute({
9013
+ sql: `SELECT ${buildSelectColumns(storage.TABLE_SCHEDULES)} FROM ${storage.TABLE_SCHEDULES} ${where} ORDER BY created_at ASC`,
9014
+ args: params
9015
+ });
9016
+ return result.rows.map((r) => rowToSchedule(r));
9017
+ }
9018
+ async listDueSchedules(now, limit) {
9019
+ const cap = limit ?? 100;
9020
+ const result = await this.#client.execute({
9021
+ sql: `SELECT ${buildSelectColumns(storage.TABLE_SCHEDULES)} FROM ${storage.TABLE_SCHEDULES}
9022
+ WHERE status = ? AND next_fire_at <= ?
9023
+ ORDER BY next_fire_at ASC
9024
+ LIMIT ?`,
9025
+ args: ["active", now, cap]
9026
+ });
9027
+ return result.rows.map((r) => rowToSchedule(r));
9028
+ }
9029
+ async updateSchedule(id, patch) {
9030
+ const setClauses = [];
9031
+ const params = [];
9032
+ if ("cron" in patch && patch.cron !== void 0) {
9033
+ setClauses.push("cron = ?");
9034
+ params.push(patch.cron);
9035
+ }
9036
+ if ("timezone" in patch) {
9037
+ setClauses.push("timezone = ?");
9038
+ params.push(patch.timezone ?? null);
9039
+ }
9040
+ if ("status" in patch && patch.status !== void 0) {
9041
+ setClauses.push("status = ?");
9042
+ params.push(patch.status);
9043
+ }
9044
+ if ("nextFireAt" in patch && patch.nextFireAt !== void 0) {
9045
+ setClauses.push("next_fire_at = ?");
9046
+ params.push(patch.nextFireAt);
9047
+ }
9048
+ if ("target" in patch && patch.target !== void 0) {
9049
+ setClauses.push("target = jsonb(?)");
9050
+ params.push(JSON.stringify(patch.target));
9051
+ }
9052
+ if ("metadata" in patch) {
9053
+ setClauses.push("metadata = jsonb(?)");
9054
+ params.push(patch.metadata != null ? JSON.stringify(patch.metadata) : null);
9055
+ }
9056
+ setClauses.push("updated_at = ?");
9057
+ params.push(Date.now());
9058
+ params.push(id);
9059
+ if (setClauses.length === 1) {
9060
+ const existing = await this.getSchedule(id);
9061
+ if (!existing) throw new Error(`Schedule ${id} not found`);
9062
+ return existing;
9063
+ }
9064
+ await this.#client.execute({
9065
+ sql: `UPDATE ${storage.TABLE_SCHEDULES} SET ${setClauses.join(", ")} WHERE id = ?`,
9066
+ args: params
9067
+ });
9068
+ const updated = await this.getSchedule(id);
9069
+ if (!updated) throw new Error(`Schedule ${id} not found`);
9070
+ return updated;
9071
+ }
9072
+ async updateScheduleNextFire(id, expectedNextFireAt, newNextFireAt, lastFireAt, lastRunId) {
9073
+ const result = await this.#client.execute({
9074
+ sql: `UPDATE ${storage.TABLE_SCHEDULES}
9075
+ SET next_fire_at = ?, last_fire_at = ?, last_run_id = ?, updated_at = ?
9076
+ WHERE id = ? AND next_fire_at = ? AND status = ?`,
9077
+ args: [newNextFireAt, lastFireAt, lastRunId, Date.now(), id, expectedNextFireAt, "active"]
9078
+ });
9079
+ return (result.rowsAffected ?? 0) > 0;
9080
+ }
9081
+ async deleteSchedule(id) {
9082
+ await this.#client.execute({
9083
+ sql: `DELETE FROM ${storage.TABLE_SCHEDULE_TRIGGERS} WHERE schedule_id = ?`,
9084
+ args: [id]
9085
+ });
9086
+ await this.#client.execute({
9087
+ sql: `DELETE FROM ${storage.TABLE_SCHEDULES} WHERE id = ?`,
9088
+ args: [id]
9089
+ });
9090
+ }
9091
+ async recordTrigger(trigger) {
9092
+ await this.#db.insert({
9093
+ tableName: storage.TABLE_SCHEDULE_TRIGGERS,
9094
+ record: {
9095
+ schedule_id: trigger.scheduleId,
9096
+ run_id: trigger.runId,
9097
+ scheduled_fire_at: trigger.scheduledFireAt,
9098
+ actual_fire_at: trigger.actualFireAt,
9099
+ status: trigger.status,
9100
+ error: trigger.error ?? null
9101
+ }
9102
+ });
9103
+ }
9104
+ async listTriggers(scheduleId, opts) {
9105
+ const conditions = ["schedule_id = ?"];
9106
+ const params = [scheduleId];
9107
+ if (opts?.fromActualFireAt != null) {
9108
+ conditions.push("actual_fire_at >= ?");
9109
+ params.push(opts.fromActualFireAt);
9110
+ }
9111
+ if (opts?.toActualFireAt != null) {
9112
+ conditions.push("actual_fire_at < ?");
9113
+ params.push(opts.toActualFireAt);
9114
+ }
9115
+ const limitClause = opts?.limit != null ? `LIMIT ${Math.floor(opts.limit)}` : "";
9116
+ const result = await this.#client.execute({
9117
+ sql: `SELECT ${buildSelectColumns(storage.TABLE_SCHEDULE_TRIGGERS)} FROM ${storage.TABLE_SCHEDULE_TRIGGERS}
9118
+ WHERE ${conditions.join(" AND ")}
9119
+ ORDER BY actual_fire_at DESC
9120
+ ${limitClause}`,
9121
+ args: params
9122
+ });
9123
+ return result.rows.map((r) => rowToTrigger(r));
9124
+ }
9125
+ };
8899
9126
  var ScorerDefinitionsLibSQL = class extends storage.ScorerDefinitionsStorage {
8900
9127
  #db;
8901
9128
  #client;
@@ -11127,6 +11354,7 @@ var LibSQLStore = class extends storage.MastraCompositeStore {
11127
11354
  const skills = new SkillsLibSQL(domainConfig);
11128
11355
  const blobs = new BlobsLibSQL(domainConfig);
11129
11356
  const backgroundTasks = new BackgroundTasksLibSQL(domainConfig);
11357
+ const schedules = new SchedulesLibSQL(domainConfig);
11130
11358
  this.stores = {
11131
11359
  scores,
11132
11360
  workflows,
@@ -11143,7 +11371,8 @@ var LibSQLStore = class extends storage.MastraCompositeStore {
11143
11371
  workspaces,
11144
11372
  skills,
11145
11373
  blobs,
11146
- backgroundTasks
11374
+ backgroundTasks,
11375
+ schedules
11147
11376
  };
11148
11377
  }
11149
11378
  };
@@ -11262,6 +11491,7 @@ exports.MCPServersLibSQL = MCPServersLibSQL;
11262
11491
  exports.MemoryLibSQL = MemoryLibSQL;
11263
11492
  exports.ObservabilityLibSQL = ObservabilityLibSQL;
11264
11493
  exports.PromptBlocksLibSQL = PromptBlocksLibSQL;
11494
+ exports.SchedulesLibSQL = SchedulesLibSQL;
11265
11495
  exports.ScorerDefinitionsLibSQL = ScorerDefinitionsLibSQL;
11266
11496
  exports.ScoresLibSQL = ScoresLibSQL;
11267
11497
  exports.SkillsLibSQL = SkillsLibSQL;