@stacksjs/buddy 0.70.255 → 0.70.257

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.
@@ -43,6 +43,74 @@ export declare function resolveDeployEnvValues(environment: 'production' | 'stag
43
43
  * the process env).
44
44
  */
45
45
  export declare function mergeSiteDeployEnv(sites: Record<string, any>, resolvedDeployEnv: Record<string, string>): Record<string, any>;
46
+ /**
47
+ * The SQLite file a site will open, relative to its release root — or `null`
48
+ * when the site is not on SQLite, or its database already lives outside the
49
+ * release tree (an absolute `DB_DATABASE_PATH` is the operator saying "I have
50
+ * placed this somewhere persistent myself").
51
+ *
52
+ * Mirrors config/database.ts' resolution order. `DB_DATABASE` is only a path
53
+ * when it looks like one — for every other driver it is a database NAME, and
54
+ * linking `stacks` as a file would be nonsense.
55
+ */
56
+ export declare function siteSqlitePath(siteEnv?: Record<string, any>): string | null;
57
+ /**
58
+ * Does the loaded ts-cloud actually keep persistent state the way
59
+ * {@link applyPersistentStatePaths} assumes?
60
+ *
61
+ * Declaring shared paths against a ts-cloud that lacks these is worse than not
62
+ * declaring them at all — it is the difference between "the database dies with
63
+ * its release" and "the deploy places an empty database over the live one and
64
+ * migrates into it". So this probes the two capabilities the declaration
65
+ * depends on and lets the caller refuse the deploy.
66
+ *
67
+ * Probed by generating a script and reading what it DOES, not by a version
68
+ * number or an exported symbol name: a version range goes stale the moment
69
+ * someone installs a fork, and an internal helper can be renamed without
70
+ * changing behaviour.
71
+ *
72
+ * @param buildSiteDeployScript ts-cloud's script builder, as loaded at runtime.
73
+ */
74
+ export declare function tsCloudPersistentStateSupport(buildSiteDeployScript: unknown): { ok: boolean, missing: string[] };
75
+ /**
76
+ * Where a project's app database lives on the box: one directory per project,
77
+ * outside every site's release tree.
78
+ *
79
+ * Deliberately derived from the project slug ALONE. ts-cloud installs each site
80
+ * under `/var/www/<slug>-<site>`, so anything derived from the site name gives
81
+ * each site a database of its own — which is exactly how `main` and `api` ended
82
+ * up on separate files, with only `main` ever migrated. Two sites of one project
83
+ * cannot disagree about a path that does not mention which site is asking.
84
+ */
85
+ export declare function projectDatabaseTarget(slug: string, relativePath: string): string;
86
+ /**
87
+ * Declare the paths a Stacks server-app WRITES at runtime as ts-cloud shared
88
+ * paths, so they are symlinked into each release instead of dying with it.
89
+ *
90
+ * Two separate failures are closed here.
91
+ *
92
+ * **A release owns the database.** `releases/<sha>/database/stacks.sqlite` was a
93
+ * real file inside the release the deploy had just unpacked: `migrate` (in
94
+ * preStart) built a brand new empty database, the release went live against it,
95
+ * and every production row written since the previous deploy was gone the moment
96
+ * the old release was pruned — silently, with nothing in the deploy output to
97
+ * say so. Verified on a live box: a sentinel row was gone after the next deploy.
98
+ *
99
+ * **A site owns the database.** Each site installs under its own base, so `main`
100
+ * and `api` both opened `database/stacks.sqlite` relative to their OWN release
101
+ * — two files, only one of them ever migrated. The database is therefore pointed
102
+ * at a project-level target ({@link projectDatabaseTarget}) that no site's name
103
+ * appears in, so siblings share one file by construction. Only the site that
104
+ * runs `migrate` may create or seed it; the rest link at it (`seed: false`), so
105
+ * deploy order cannot decide whose data wins.
106
+ *
107
+ * Logs stay site-scoped — `main` and `api` are different services and their logs
108
+ * should not interleave.
109
+ *
110
+ * Additive: a site's own `sharedPaths` in config/cloud.ts always survive, so an
111
+ * app can persist its own state (upload dirs, generated assets) the same way.
112
+ */
113
+ export declare function applyPersistentStatePaths(sites: Record<string, any>, slug: string): Record<string, any>;
46
114
  /**
47
115
  * Make the site model environment-aware. For a non-production environment that
48
116
  * declares a `domainPrefix` (staging → `staging`, development → `dev`), every
@@ -479,6 +479,74 @@ export function mergeSiteDeployEnv(sites, resolvedDeployEnv) {
479
479
  return [siteName, { ...site, env: { ...base, ...site.env || {} } }];
480
480
  }));
481
481
  }
482
+ function looksLikeSqliteFile(value) {
483
+ return typeof value === "string" && /\.(?:sqlite3?|db)$/i.test(value.trim());
484
+ }
485
+ export function siteSqlitePath(siteEnv = {}) {
486
+ if (String(siteEnv.DB_CONNECTION ?? "sqlite").trim().toLowerCase() !== "sqlite")
487
+ return null;
488
+ const configured = typeof siteEnv.DB_DATABASE_PATH === "string" && siteEnv.DB_DATABASE_PATH.trim() ? siteEnv.DB_DATABASE_PATH : looksLikeSqliteFile(siteEnv.DB_DATABASE) ? siteEnv.DB_DATABASE : "database/stacks.sqlite", path = String(configured).trim().replace(/^\.\//, "");
489
+ if (!path || path.startsWith("/") || path.startsWith("~") || path.split("/").includes(".."))
490
+ return null;
491
+ return path;
492
+ }
493
+ export function tsCloudPersistentStateSupport(buildSiteDeployScript) {
494
+ const missing = [];
495
+ if (typeof buildSiteDeployScript !== "function")
496
+ return { ok: !1, missing: ["buildSiteDeployScript"] };
497
+ const target = "/var/www/probe-shared/database/probe.sqlite";
498
+ let script = "";
499
+ try {
500
+ script = buildSiteDeployScript({
501
+ siteName: "probe",
502
+ slug: "probe",
503
+ appDir: "/var/www/probe-probe",
504
+ artifactFetch: [],
505
+ releaseId: "probe",
506
+ execStart: "/bin/true",
507
+ envEntries: {},
508
+ port: 3000,
509
+ sharedPaths: [{ path: "database/probe.sqlite", target, seed: !0 }]
510
+ }).join(`
511
+ `);
512
+ } catch {
513
+ return { ok: !1, missing: ["shared paths with an explicit target"] };
514
+ }
515
+ if (!(script.includes("cp -a") && script.includes("/current/")))
516
+ missing.push("adoption of existing state into shared/");
517
+ if (!script.includes(`ln -sfn ${target} `))
518
+ missing.push("shared paths with an explicit target");
519
+ return { ok: missing.length === 0, missing };
520
+ }
521
+ export function projectDatabaseTarget(slug, relativePath) {
522
+ return `/var/www/${slug}-shared/${relativePath}`;
523
+ }
524
+ function runsMigrations(site) {
525
+ return Array.isArray(site?.preStart) && site.preStart.some((cmd) => typeof cmd === "string" && /\bmigrate\b/.test(cmd));
526
+ }
527
+ export function applyPersistentStatePaths(sites, slug) {
528
+ const isServerApp = (site) => !!site && typeof site.start === "string", appSites = Object.entries(sites).filter(([, site]) => isServerApp(site)), owner = (appSites.find(([, site]) => runsMigrations(site)) ?? appSites[0])?.[0], out = {};
529
+ for (const [name, site] of Object.entries(sites)) {
530
+ if (!isServerApp(site)) {
531
+ out[name] = site;
532
+ continue;
533
+ }
534
+ const sqlite = siteSqlitePath(site.env || {}), framework = [
535
+ "storage/logs"
536
+ ];
537
+ if (sqlite)
538
+ framework.unshift({
539
+ path: sqlite,
540
+ target: projectDatabaseTarget(slug, sqlite),
541
+ seed: name === owner
542
+ });
543
+ const declared = Array.isArray(site.sharedPaths) ? site.sharedPaths.filter(Boolean) : [], byPath = new Map;
544
+ for (const entry of [...declared, ...framework])
545
+ byPath.set(typeof entry === "string" ? entry : entry.path, entry);
546
+ out[name] = { ...site, sharedPaths: [...byPath.values()] };
547
+ }
548
+ return out;
549
+ }
482
550
  function prefixHostForEnv(host, prefix) {
483
551
  if (host.startsWith(`${prefix}.`) || host.startsWith(`www.${prefix}.`))
484
552
  return host;
@@ -546,7 +614,13 @@ async function deployToHetzner(tsCloudConfig, deployEnv, options) {
546
614
  log.info("Generate one with: ssh-keygen -t ed25519");
547
615
  process.exit(ExitCode.FatalError);
548
616
  }
549
- const { createCloudDriver, deployAllComputeSites, ensureManagementDashboard, resolveSiteKind } = await loadTsCloudDeployApi();
617
+ const { createCloudDriver, deployAllComputeSites, ensureManagementDashboard, resolveSiteKind, buildSiteDeployScript } = await loadTsCloudDeployApi(), support = tsCloudPersistentStateSupport(buildSiteDeployScript);
618
+ if (!support.ok) {
619
+ log.error("This ts-cloud cannot keep your database across deploys, and deploying anyway would destroy it.");
620
+ log.error(`Missing: ${support.missing.join(", ")}.`);
621
+ log.error("Upgrade @stacksjs/ts-cloud (bun update @stacksjs/ts-cloud), or point TS_CLOUD_MODULE at a build that has it.");
622
+ process.exit(ExitCode.FatalError);
623
+ }
550
624
  try {
551
625
  await runHetznerDeploy({ tsCloudConfig, environment, verbose, docker: options.docker === !0, createCloudDriver, deployAllComputeSites, ensureManagementDashboard, resolveSiteKind, onlySite: options.site || void 0, persistedAttachBox });
552
626
  } catch (err) {
@@ -830,7 +904,10 @@ async function runHetznerDeploy(args) {
830
904
  ".env.local",
831
905
  ".env.keys",
832
906
  ".env.production.bak",
833
- ".env.production.plain"
907
+ ".env.production.plain",
908
+ "*.sqlite",
909
+ "*.sqlite-wal",
910
+ "*.sqlite-shm"
834
911
  ];
835
912
  if (onlySite && !sites[onlySite]) {
836
913
  log.error(`--site '${onlySite}' is not a configured site. Available: ${Object.keys(sites).join(", ")}`);
@@ -862,7 +939,7 @@ async function runHetznerDeploy(args) {
862
939
  }
863
940
  if (docker)
864
941
  await buildContainerImageWithPantry({ slug, sites, verbose });
865
- const resolvedDeployEnv = await resolveDeployEnvValues(environment, tsCloudConfig), sitesWithResolvedEnv = mergeSiteDeployEnv(sites, resolvedDeployEnv);
942
+ const resolvedDeployEnv = await resolveDeployEnvValues(environment, tsCloudConfig), sitesWithResolvedEnv = applyPersistentStatePaths(mergeSiteDeployEnv(sites, resolvedDeployEnv), slug);
866
943
  for (const [envKey, envValue] of Object.entries(resolvedDeployEnv))
867
944
  if (process.env[envKey] === void 0)
868
945
  process.env[envKey] = envValue;
@@ -60,6 +60,20 @@ export function generate(buddy) {
60
60
  log.warn(`[generate:db-types] ${e.file}: ${e.error}`);
61
61
  log.info(`[generate:db-types] resolved ${result.tables.length} table(s)`);
62
62
  });
63
+ buddy.command("generate:vschema", "Derive a Vitess VSchema from your models (writes database/vschema.json)").option("--dry-run", "Print the VSchema without writing it", { default: !1 }).option("--out [path]", "Where to write the VSchema", { default: "database/vschema.json" }).action(async (options) => {
64
+ const { generateVSchema } = await import("@stacksjs/actions"), result = await generateVSchema({ dryRun: options.dryRun, out: options.out });
65
+ if (!result.ok) {
66
+ console.error(`
67
+ \u274C ${result.error}
68
+ `);
69
+ process.exit(ExitCode.FatalError);
70
+ }
71
+ console.log(result.report);
72
+ if (options.dryRun)
73
+ console.log(JSON.stringify(result.vschema, null, 2));
74
+ else
75
+ log.success(`Wrote ${result.path} (${result.tableCount} tables)`);
76
+ });
63
77
  buddy.command("generate:entries", descriptions.entries).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
64
78
  log.debug("Running `buddy generate:entries` ...", options);
65
79
  await generateLibEntries(options);
@@ -6,7 +6,7 @@ import { hasTTY, isCI } from "@stacksjs/env";
6
6
  import { appPath, frameworkPath, frameworkRuntimePath, projectPath } from "@stacksjs/path";
7
7
  import { ExitCode } from "@stacksjs/types";
8
8
  import { preflightDatabase } from "../database-preflight";
9
- import { DIALECT_OVERRIDE_ENV, auditMigrationCorpus, formatMigrationDialectError, stripSqlNoise } from "@stacksjs/database";
9
+ import { DDL_CONSTRAINT_OVERRIDE_ENV, DIALECT_OVERRIDE_ENV, auditDdlConstraints, auditMigrationCorpus, dialectCapabilities, formatDdlConstraintError, formatMigrationDialectError, stripSqlNoise } from "@stacksjs/database";
10
10
  let _runAction;
11
11
  async function runAction(...args) {
12
12
  if (!_runAction)
@@ -85,15 +85,21 @@ function validateModelsExist() {
85
85
  return { valid: !0 };
86
86
  }
87
87
  function validateMigrationDialect() {
88
- if (process.env[DIALECT_OVERRIDE_ENV] === "1")
89
- return { valid: !0 };
90
- const driver = String(process.env.DB_CONNECTION || "sqlite").toLowerCase(), target = driver === "singlestore" ? "mysql" : driver;
91
- if (target !== "sqlite" && target !== "postgres" && target !== "mysql")
92
- return { valid: !0 };
93
- const dir = projectPath("database/migrations"), audit = auditMigrationCorpus({ dir, target });
94
- if (audit.empty || audit.incompatible.length === 0)
95
- return { valid: !0 };
96
- return { valid: !1, error: formatMigrationDialectError(audit, target, "database/migrations") };
88
+ const driver = String(process.env.DB_CONNECTION || "sqlite").toLowerCase(), dir = projectPath("database/migrations");
89
+ if (process.env[DIALECT_OVERRIDE_ENV] !== "1") {
90
+ const caps = dialectCapabilities(driver), target = caps.wire === "mysql" ? "mysql" : caps.wire === "postgres" ? "postgres" : "sqlite";
91
+ if (driver === "sqlite" || driver === "postgres" || caps.wire === "mysql") {
92
+ const audit = auditMigrationCorpus({ dir, target });
93
+ if (!audit.empty && audit.incompatible.length > 0)
94
+ return { valid: !1, error: formatMigrationDialectError(audit, target, "database/migrations") };
95
+ }
96
+ }
97
+ if (process.env[DDL_CONSTRAINT_OVERRIDE_ENV] !== "1") {
98
+ const constraints = auditDdlConstraints({ dir, dialect: driver });
99
+ if (!constraints.empty && constraints.violations.length > 0)
100
+ return { valid: !1, error: formatDdlConstraintError(constraints, driver, "database/migrations") };
101
+ }
102
+ return { valid: !0 };
97
103
  }
98
104
  async function reportMissingForeignKeys() {
99
105
  try {
@@ -289,14 +295,20 @@ export function migrate(buddy) {
289
295
  log.error("Model migrations failed \u2014 applying notification/RBAC table guarantees before exiting.");
290
296
  if (options.auth !== !1)
291
297
  try {
292
- const { migrateNotificationTables, migrateRbacTables } = await import("@stacksjs/database"), notifResult = await migrateNotificationTables({ verbose: options.verbose });
298
+ const { ensureUtcDatetimeColumns, migrateNotificationTables, migrateRbacTables, migrateTraitTables } = await import("@stacksjs/database"), notifResult = await migrateNotificationTables({ verbose: options.verbose });
293
299
  if (!notifResult.success)
294
300
  log.error(`Failed to migrate notification tables: ${notifResult.error}`);
295
301
  const rbacResult = await migrateRbacTables({ verbose: options.verbose });
296
302
  if (!rbacResult.success)
297
303
  log.error(`Failed to migrate RBAC tables: ${rbacResult.error}`);
304
+ const traitResult = await migrateTraitTables({ verbose: options.verbose });
305
+ if (!traitResult.success)
306
+ log.error(`Failed to migrate polymorphic trait tables: ${traitResult.error}`);
307
+ const datetimeResult = await ensureUtcDatetimeColumns({ verbose: options.verbose });
308
+ if (!datetimeResult.success)
309
+ log.error(`Failed to convert TIMESTAMP columns to DATETIME: ${datetimeResult.error}`);
298
310
  } catch (error) {
299
- log.error("Failed to migrate notification/RBAC tables:", error);
311
+ log.error("Failed to migrate notification/RBAC/trait tables:", error);
300
312
  }
301
313
  if (result.isErr) {
302
314
  await outro("While running the migrate command, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
@@ -371,7 +383,7 @@ export function migrate(buddy) {
371
383
  if (options.auth !== !1) {
372
384
  log.debug("Migrating auth tables...");
373
385
  try {
374
- const { migrateAuthTables, migrateNotificationTables, migrateRbacTables } = await import("@stacksjs/database"), authResult = await migrateAuthTables({ verbose: options.verbose });
386
+ const { migrateAuthTables, migrateNotificationTables, migrateRbacTables, migrateTraitTables } = await import("@stacksjs/database"), authResult = await migrateAuthTables({ verbose: options.verbose });
375
387
  if (!authResult.success)
376
388
  log.error(`Failed to migrate auth tables: ${authResult.error}`);
377
389
  const notifResult = await migrateNotificationTables({ verbose: options.verbose });
@@ -380,8 +392,11 @@ export function migrate(buddy) {
380
392
  const rbacResult = await migrateRbacTables({ verbose: options.verbose });
381
393
  if (!rbacResult.success)
382
394
  log.error(`Failed to migrate RBAC tables: ${rbacResult.error}`);
395
+ const traitResult = await migrateTraitTables({ verbose: options.verbose });
396
+ if (!traitResult.success)
397
+ log.error(`Failed to migrate polymorphic trait tables: ${traitResult.error}`);
383
398
  } catch (error) {
384
- log.error("Failed to migrate auth/notification/RBAC tables:", error);
399
+ log.error("Failed to migrate auth/notification/RBAC/trait tables:", error);
385
400
  }
386
401
  }
387
402
  try {
@@ -1,35 +1 @@
1
- /**
2
- * Resolve the project's includes directory.
3
- *
4
- * A configured `config/stx.ts#partialsDir` wins outright. The convention list
5
- * below is only a fallback for apps that never set one, and it cannot stand in
6
- * for the config: the candidates are probed for existence in order, so an app
7
- * that keeps its includes in `resources/components` but also has an unrelated
8
- * `resources/partials` directory silently resolved to the wrong one and every
9
- * `@include` failed with ENOENT at runtime.
10
- *
11
- * The configured value is relative to the stx root (`resources`), matching how
12
- * stx itself reads it, but an app-root-relative path is accepted too so either
13
- * spelling resolves.
14
- */
15
- export declare function resolveUserPartialsPath(cwd?: unknown, configuredDir?: string): string | undefined;
16
- /**
17
- * Read `partialsDir` off the app's stx config. Failure is non-fatal: without
18
- * it {@link resolveUserPartialsPath} falls back to the conventions.
19
- */
20
- export declare function loadStxPartialsDir(cwd?: unknown): Promise<string | undefined>;
21
- /**` proxy target, or `null` when it cannot be
22
- * known safely.
23
- *
24
- * `API_URL` and `PORT_API` are explicit operator intent and always win. The
25
- * framework-wide `ports.api` default is only trusted *outside* deployed
26
- * environments: locally one app owns the machine, so `127.0.0.1:3008` really is
27
- * its own API. On a deployed box that assumption does not hold — ts-cloud runs
28
- * many SSR sites side by side, each on its own port, and an unconfigured
29
- * default resolves to whichever tenant happens to own it.
30
- *
31
- * Returning `null` makes the caller answer 502. That is the safe failure: the
32
- * alternative is proxying authenticated requests into another app's process.
33
- */
34
- export declare function resolveApiBase(configuredPort?: number, env?: NodeJS.ProcessEnv): string | null;
35
- export declare function startProductionServer(options?: { port?: string | number, verbose?: boolean }): Promise<void>;
1
+ export {};
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/buddy",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.70.255",
5
+ "version": "0.70.257",
6
6
  "description": "Meet Buddy. The Stacks runtime.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -88,53 +88,53 @@
88
88
  "prepublishOnly": "bun run build"
89
89
  },
90
90
  "dependencies": {
91
- "@stacksjs/actions": "^0.70.255",
92
- "@stacksjs/ai": "^0.70.255",
93
- "@stacksjs/alias": "^0.70.255",
94
- "@stacksjs/arrays": "^0.70.255",
95
- "@stacksjs/auth": "^0.70.255",
96
- "@stacksjs/build": "^0.70.255",
97
- "@stacksjs/cache": "^0.70.255",
98
- "@stacksjs/cli": "^0.70.255",
91
+ "@stacksjs/actions": "^0.70.257",
92
+ "@stacksjs/ai": "^0.70.257",
93
+ "@stacksjs/alias": "^0.70.257",
94
+ "@stacksjs/arrays": "^0.70.257",
95
+ "@stacksjs/auth": "^0.70.257",
96
+ "@stacksjs/build": "^0.70.257",
97
+ "@stacksjs/cache": "^0.70.257",
98
+ "@stacksjs/cli": "^0.70.257",
99
99
  "@stacksjs/clapp": "^0.2.12",
100
- "@stacksjs/cloud": "^0.70.255",
101
- "@stacksjs/collections": "^0.70.255",
102
- "@stacksjs/config": "^0.70.255",
103
- "@stacksjs/database": "^0.70.255",
104
- "@stacksjs/desktop-build": "^0.70.255",
105
- "@stacksjs/dns": "^0.70.255",
106
- "@stacksjs/email": "^0.70.255",
107
- "@stacksjs/enums": "^0.70.255",
108
- "@stacksjs/error-handling": "^0.70.255",
109
- "@stacksjs/events": "^0.70.255",
110
- "@stacksjs/git": "^0.70.255",
100
+ "@stacksjs/cloud": "^0.70.257",
101
+ "@stacksjs/collections": "^0.70.257",
102
+ "@stacksjs/config": "^0.70.257",
103
+ "@stacksjs/database": "^0.70.257",
104
+ "@stacksjs/desktop-build": "^0.70.257",
105
+ "@stacksjs/dns": "^0.70.257",
106
+ "@stacksjs/email": "^0.70.257",
107
+ "@stacksjs/enums": "^0.70.257",
108
+ "@stacksjs/error-handling": "^0.70.257",
109
+ "@stacksjs/events": "^0.70.257",
110
+ "@stacksjs/git": "^0.70.257",
111
111
  "@stacksjs/gitit": "^0.2.5",
112
- "@stacksjs/health": "^0.70.255",
112
+ "@stacksjs/health": "^0.70.257",
113
113
  "@stacksjs/dnsx": "^0.2.3",
114
114
  "@stacksjs/httx": "^0.1.10",
115
- "@stacksjs/image": "^0.70.255",
116
- "@stacksjs/lint": "^0.70.255",
117
- "@stacksjs/logging": "^0.70.255",
118
- "@stacksjs/notifications": "^0.70.255",
119
- "@stacksjs/objects": "^0.70.255",
120
- "@stacksjs/orm": "^0.70.255",
121
- "@stacksjs/path": "^0.70.255",
122
- "@stacksjs/skills": "^0.70.255",
123
- "@stacksjs/payments": "^0.70.255",
124
- "@stacksjs/realtime": "^0.70.255",
125
- "@stacksjs/router": "^0.70.255",
115
+ "@stacksjs/image": "^0.70.257",
116
+ "@stacksjs/lint": "^0.70.257",
117
+ "@stacksjs/logging": "^0.70.257",
118
+ "@stacksjs/notifications": "^0.70.257",
119
+ "@stacksjs/objects": "^0.70.257",
120
+ "@stacksjs/orm": "^0.70.257",
121
+ "@stacksjs/path": "^0.70.257",
122
+ "@stacksjs/skills": "^0.70.257",
123
+ "@stacksjs/payments": "^0.70.257",
124
+ "@stacksjs/realtime": "^0.70.257",
125
+ "@stacksjs/router": "^0.70.257",
126
126
  "@stacksjs/rpx": "^0.11.42",
127
- "@stacksjs/search-engine": "^0.70.255",
128
- "@stacksjs/security": "^0.70.255",
129
- "@stacksjs/server": "^0.70.255",
130
- "@stacksjs/storage": "^0.70.255",
131
- "@stacksjs/strings": "^0.70.255",
132
- "@stacksjs/testing": "^0.70.255",
133
- "@stacksjs/tunnel": "^0.70.255",
134
- "@stacksjs/types": "^0.70.255",
135
- "@stacksjs/ui": "^0.70.255",
136
- "@stacksjs/utils": "^0.70.255",
137
- "@stacksjs/validation": "^0.70.255",
127
+ "@stacksjs/search-engine": "^0.70.257",
128
+ "@stacksjs/security": "^0.70.257",
129
+ "@stacksjs/server": "^0.70.257",
130
+ "@stacksjs/storage": "^0.70.257",
131
+ "@stacksjs/strings": "^0.70.257",
132
+ "@stacksjs/testing": "^0.70.257",
133
+ "@stacksjs/tunnel": "^0.70.257",
134
+ "@stacksjs/types": "^0.70.257",
135
+ "@stacksjs/ui": "^0.70.257",
136
+ "@stacksjs/utils": "^0.70.257",
137
+ "@stacksjs/validation": "^0.70.257",
138
138
  "@stacksjs/ts-cloud": "^0.7.92",
139
139
  "ajv": "^8.20.0",
140
140
  "ajv-formats": "^3.0.1",