@stacksjs/actions 0.70.113 → 0.70.115

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.
@@ -177,7 +177,10 @@ try {
177
177
  )
178
178
  `);
179
179
  try {
180
- await db.unsafe("ALTER TABLE password_resets ADD COLUMN expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP");
180
+ if (isPostgres)
181
+ await db.unsafe("ALTER TABLE password_resets ADD COLUMN IF NOT EXISTS expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP");
182
+ else
183
+ await db.unsafe("ALTER TABLE password_resets ADD COLUMN expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP");
181
184
  } catch {}
182
185
  await db.unsafe(`
183
186
  CREATE UNIQUE INDEX IF NOT EXISTS idx_password_resets_email_unique ON password_resets(email)
package/dist/blog.js CHANGED
@@ -193,11 +193,9 @@ async function blogChrome() {
193
193
  ${toggle}`;
194
194
  }
195
195
  async function blogFooter() {
196
- return `<div class="blog-landscape" aria-hidden="true">
197
- <span class="ridge"></span>
198
- <span class="river"></span>
196
+ return `<footer class="blog-foot">
199
197
  <p class="colophon">${(await site()).colophon}</p>
200
- </div>`;
198
+ </footer>`;
201
199
  }
202
200
  async function blogConfig(bp, fm) {
203
201
  const cfg = await site(), themeCss = existsSync(THEME_FILE) ? readFileSync(THEME_FILE, "utf-8") : "", baseCss = bp.defaultConfig.markdown?.css || "";
@@ -232,7 +230,7 @@ async function notFoundHtml(bp) {
232
230
  const body = `
233
231
  <a class="blog-back" href="/blog">\u2190 All posts</a>
234
232
  <div class="blog-404">
235
- <span class="blog-404-art" aria-hidden="true"></span>
233
+ <p class="blog-kicker">404</p>
236
234
  <h1>Nothing here</h1>
237
235
  <p>This post doesn't exist (or it moved). Head back to <a href="/blog">all posts</a>.</p>
238
236
  </div>`;
@@ -248,13 +246,12 @@ async function postHtml(bp, slug, origin) {
248
246
  const author = fm.author || cfg.author, initial = escapeHtml(author.charAt(0).toUpperCase()), header = `
249
247
  <a class="blog-back" href="/blog">\u2190 All posts</a>
250
248
  <div class="blog-post-head">
251
- <h1>${escapeHtml(fm.title || slug)}</h1>
252
249
  <p class="blog-post-meta">
253
- <span class="author">${escapeHtml(author)}</span>
254
- <span class="dot">\xB7</span>
255
250
  <time>${escapeHtml(formatDate(fm.date))}</time>
251
+ <span class="dot">\xB7</span>
252
+ <span class="author">${escapeHtml(author)}</span>
256
253
  </p>
257
- ${fm.poster ? `<figure class="blog-post-poster"><img src="${escapeHtml(fm.poster)}" alt="${escapeHtml(fm.title || "")}"></figure>` : ""}
254
+ <h1>${escapeHtml(fm.title || slug)}</h1>
258
255
  </div>`, authorCard = fm.authorBio ? `<aside class="blog-author-card">
259
256
  <div class="avatar">${initial}</div>
260
257
  <div><span class="name">${escapeHtml(author)}</span><p class="bio">${escapeHtml(fm.authorBio)}</p></div>
@@ -270,19 +267,20 @@ async function postHtml(bp, slug, origin) {
270
267
  return bp.wrapInLayout(await blogChrome() + header + html + authorCard + share + more + await blogFooter(), await blogConfig(bp, fm), `/blog/${slug}`, "page");
271
268
  }
272
269
  async function indexHtml(bp) {
273
- const cfg = await site(), cards = listPosts().map((p) => {
274
- const featured = p.fm.featured === "true", media = p.fm.poster ? `<div class="blog-card-media"><img src="${escapeHtml(p.fm.poster)}" alt="" loading="lazy"></div>` : "";
275
- return `<a class="blog-card${featured ? " is-featured" : ""}" href="/blog/${escapeHtml(p.slug)}">
276
- ${media}
277
- <div>
278
- ${featured ? '<span class="blog-card-flag">Featured</span>' : ""}
279
- <h2 class="blog-card-title">${escapeHtml(p.fm.title || p.slug)}</h2>
280
- <p class="blog-card-excerpt">${escapeHtml((p.fm.description || "").slice(0, 180))}</p>
281
- <div class="blog-card-meta">${escapeHtml(p.fm.author || cfg.author)} \xB7 ${escapeHtml(formatDate(p.fm.date))}</div>
270
+ const cfg = await site(), posts = listPosts(), [lead, ...rest] = posts, leadHtml = lead ? `<a class="blog-feature" href="/blog/${escapeHtml(lead.slug)}">
271
+ <p class="blog-feature-meta">${lead.fm.featured === "true" ? '<span class="chip">Featured</span>' : ""}<time>${escapeHtml(formatDate(lead.fm.date))}</time></p>
272
+ <h2>${escapeHtml(lead.fm.title || lead.slug)}</h2>
273
+ <p class="blog-feature-excerpt">${escapeHtml((lead.fm.description || "").slice(0, 200))}</p>
274
+ <span class="blog-read">Read the post <span class="arrow" aria-hidden="true">\u2192</span></span>
275
+ </a>` : "", rows = rest.map((p) => `<a class="blog-row" href="/blog/${escapeHtml(p.slug)}">
276
+ <time>${escapeHtml(formatDate(p.fm.date))}</time>
277
+ <div class="blog-row-main">
278
+ <h2>${escapeHtml(p.fm.title || p.slug)}</h2>
279
+ <p>${escapeHtml((p.fm.description || "").slice(0, 160))}</p>
282
280
  </div>
283
- </a>`;
284
- }).join(`
285
- `), emptyState = `
281
+ <span class="blog-row-arrow" aria-hidden="true">\u2192</span>
282
+ </a>`).join(`
283
+ `), cards = leadHtml + (rest.length ? `<div class="blog-index">${rows}</div>` : ""), emptyState = `
286
284
  <div class="blog-empty">
287
285
  <h2>${escapeHtml(cfg.emptyTitle)}</h2>
288
286
  <p>${escapeHtml(cfg.emptyText)}</p>
@@ -329,12 +327,12 @@ async function indexHtml(bp) {
329
327
  })
330
328
  })()
331
329
  </script>`, body = `
332
- <div class="blog-listing-head">
333
- <span class="sign" aria-hidden="true"></span>
330
+ <div class="blog-head">
334
331
  <h1>${escapeHtml(cfg.title)}</h1>
335
- <p>${escapeHtml(cfg.description)}</p>
332
+ <p class="blog-head-sub">${escapeHtml(cfg.description)}</p>
333
+ ${posts.length ? `<p class="blog-count">${posts.length} ${posts.length === 1 ? "post" : "posts"}</p>` : ""}
336
334
  </div>
337
- <div class="blog-cards">${cards || emptyState}</div>`;
335
+ <div class="blog-list">${cards || emptyState}</div>`;
338
336
  return bp.wrapInLayout(await blogChrome() + body + await blogFooter(), await blogConfig(bp, { title: cfg.title, description: cfg.description }), "/blog", "page");
339
337
  }
340
338
  async function feedXml(baseUrl) {
package/dist/make.d.ts CHANGED
@@ -15,7 +15,7 @@ export declare function createAction(options: MakeOptions): Promise<void>;
15
15
  export declare function createComponent(options: MakeOptions): Promise<void>;
16
16
  export declare function makeDatabase(options: MakeOptions): void;
17
17
  export declare function createDatabase(options: MakeOptions): void;
18
- export declare function factory(options: MakeOptions): void;
18
+ export declare function factory(options: MakeOptions): Promise<void>;
19
19
  export declare function createFactory(options: MakeOptions): Promise<void>;
20
20
  export declare function makeNotification(options: MakeOptions): Promise<void>;
21
21
  /**
package/dist/make.js CHANGED
@@ -6,9 +6,9 @@ import { localUrl } from "@stacksjs/config";
6
6
  import { Action } from "@stacksjs/enums";
7
7
  import { handleError } from "@stacksjs/error-handling";
8
8
  import { log } from "@stacksjs/logging";
9
- import { frameworkPath, path as p, resolve } from "@stacksjs/path";
9
+ import { path as p, resolve } from "@stacksjs/path";
10
10
  import { createFolder, doesFolderExist, writeTextFile } from "@stacksjs/storage";
11
- import { kebabCase, pascalCase, template } from "@stacksjs/strings";
11
+ import { camelCase, kebabCase, pascalCase, template } from "@stacksjs/strings";
12
12
  import { runAction } from "./helpers";
13
13
  import { CODE_TEMPLATES } from "./templates";
14
14
  let isDryRun = !1;
@@ -91,24 +91,30 @@ export async function createComponent(options) {
91
91
  }
92
92
  export function makeDatabase(options) {
93
93
  try {
94
- const name = options.name;
95
- log.info(`Creating your ${italic(name)} database...`);
96
94
  createDatabase(options);
97
- log.success(`Created ${italic(name)} database`);
98
95
  } catch (error) {
99
96
  log.error("There was an error creating your database", error);
100
97
  process.exit(ExitCode.FatalError);
101
98
  }
102
99
  }
103
100
  export function createDatabase(options) {
104
- log.debug("createDatabase options", options);
101
+ const name = pascalCase(options.name || "MyModel");
102
+ console.log(`
103
+ Stacks manages the database through models and migrations, so there is no separate database to create.
104
+
105
+ To add a "${name}" table:
106
+ 1. buddy make:model ${name}
107
+ 2. buddy generate:migrations
108
+ 3. buddy migrate
109
+
110
+ To use a different database engine or file, edit the connections in \`config/database.ts\`.
111
+ `);
105
112
  }
106
- export function factory(options) {
113
+ export async function factory(options) {
107
114
  try {
108
115
  const name = options.name;
109
116
  log.info(`Creating your ${italic(name)} factory...`);
110
- createDatabase(options);
111
- log.success(`Created ${italic(name)} factory`);
117
+ await createFactory(options);
112
118
  } catch (error) {
113
119
  log.error("There was an error creating your factory", error);
114
120
  process.exit(ExitCode.FatalError);
@@ -220,7 +226,7 @@ export async function makeFunction(options) {
220
226
  }
221
227
  export async function createFunction(options) {
222
228
  const name = options.name;
223
- await createFileWithTemplate(p.userFunctionsPath(`${name}.ts`), "function", name);
229
+ await createFileWithTemplate(p.userFunctionsPath(`${name}.ts`), "function", camelCase(name));
224
230
  }
225
231
  export async function makeLanguage(options) {
226
232
  try {
@@ -283,13 +289,13 @@ export async function createNotification(options) {
283
289
  }
284
290
  }
285
291
  export async function createMigration(options) {
286
- const optionName = options.name, table = "dummy-name";
292
+ const optionName = options.name;
287
293
  if (!optionName[0])
288
294
  throw Error("options.name is required and cannot be empty");
289
- const name = optionName[0].toUpperCase() + optionName.slice(1), path = frameworkPath(`database/migrations/${name}.ts`);
295
+ const fileName = `${Date.now()}-${kebabCase(optionName)}.ts`, path = p.userMigrationsPath(fileName), snake = kebabCase(optionName).replace(/-/g, "_"), table = /^create_(.+)_table$/.exec(snake)?.[1] ?? "table_name";
290
296
  try {
291
297
  await createFileWithTemplate(path, "migration", table);
292
- log.success(`Successfully created your migration file at stacks/database/migrations/${name}.ts`);
298
+ log.success(`Migration created: ${italic(`database/migrations/${fileName}`)}`);
293
299
  } catch (error) {
294
300
  log.error(error);
295
301
  }
@@ -108,6 +108,14 @@ export declare function snapshotTree(root: string, skip?: string[]): Promise<Map
108
108
  * inputs already carry their content hash, so this is just bookkeeping.
109
109
  */
110
110
  export declare function diffSnapshots(before: Map<string, SnapshotEntry>, after: Map<string, SnapshotEntry>): ChangeSummary;
111
+ /**
112
+ * Like `diffSnapshots`, but also returns the sorted relative file lists behind
113
+ * the counts. Used by the `--dry-run` preview, which diffs the local target
114
+ * against the upgrade SOURCE (local checkout or temp-dir download) instead of
115
+ * against a post-sync tree, so it can show exactly which files a real sync
116
+ * would add or change without writing anything.
117
+ */
118
+ export declare function diffSnapshotsDetailed(before: Map<string, SnapshotEntry>, after: Map<string, SnapshotEntry>): DetailedChangeSummary;
111
119
  export declare const MANAGED_PATHS: ManagedPath[];
112
120
  export declare interface UpgradeContext {
113
121
  channel: 'stable' | 'canary'
@@ -157,3 +165,8 @@ export declare interface ChangeSummary {
157
165
  removed: number
158
166
  unchanged: number
159
167
  }
168
+ export declare interface DetailedChangeSummary extends ChangeSummary {
169
+ addedFiles: string[]
170
+ changedFiles: string[]
171
+ removedFiles: string[]
172
+ }
@@ -186,6 +186,34 @@ export function diffSnapshots(before, after) {
186
186
  removed++;
187
187
  return { added, changed, removed, unchanged };
188
188
  }
189
+ export function diffSnapshotsDetailed(before, after) {
190
+ const addedFiles = [], changedFiles = [], removedFiles = [];
191
+ let unchanged = 0;
192
+ for (const [rel, info] of after) {
193
+ const prev = before.get(rel);
194
+ if (!prev)
195
+ addedFiles.push(rel);
196
+ else if (prev.size !== info.size || prev.hash !== info.hash)
197
+ changedFiles.push(rel);
198
+ else
199
+ unchanged++;
200
+ }
201
+ for (const rel of before.keys())
202
+ if (!after.has(rel))
203
+ removedFiles.push(rel);
204
+ addedFiles.sort();
205
+ changedFiles.sort();
206
+ removedFiles.sort();
207
+ return {
208
+ added: addedFiles.length,
209
+ changed: changedFiles.length,
210
+ removed: removedFiles.length,
211
+ unchanged,
212
+ addedFiles,
213
+ changedFiles,
214
+ removedFiles
215
+ };
216
+ }
189
217
  async function hashFile(absPath) {
190
218
  try {
191
219
  const buf = await Bun.file(absPath).arrayBuffer();
@@ -1,4 +1,5 @@
1
- import { chmodSync, copyFileSync, cpSync, existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
1
+ import { chmodSync, copyFileSync, cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
2
3
  import { dirname, join } from "node:path";
3
4
  import process from "node:process";
4
5
  import { parseOptions } from "@stacksjs/cli";
@@ -9,6 +10,7 @@ import {
9
10
  buildTemplateString,
10
11
  detectLocalStacks,
11
12
  diffSnapshots,
13
+ diffSnapshotsDetailed,
12
14
  MANAGED_PATHS,
13
15
  readChannel,
14
16
  readSyncedVersion,
@@ -37,6 +39,10 @@ if (!existsSync(p.projectPath("storage/framework/core"))) {
37
39
  const channelFile = join(projectRoot, ".stacks-channel"), versionFile = join(projectRoot, ".stacks-version"), currentChannel = readChannel(channelFile), ctx = resolveUpgradeContext(options, currentChannel), corePkgPath = p.projectPath("storage/framework/core/buddy/package.json"), currentVersion = readVersion(corePkgPath), explicitLocal = options.from ? p.projectPath(options.from) : null, detectedLocal = explicitLocal ?? (shouldAutoDetectLocalStacks(options) ? detectLocalStacks(projectRoot) : null), usingLocal = !!detectedLocal;
38
40
  console.log(resolveUpgradeMessage(ctx, currentChannel, !!options.stable));
39
41
  console.log(usingLocal ? ` source: local checkout at ${detectedLocal}` : ` source: github:stacksjs/stacks#${ctx.ref}`);
42
+ if (options.dryRun) {
43
+ await runDryRunPreview();
44
+ process.exit(ExitCode.Success);
45
+ }
40
46
  if (!options.force) {
41
47
  const dirty = await detectDirtyManagedPaths(projectRoot);
42
48
  if (dirty.length > 0) {
@@ -119,6 +125,135 @@ if (runHooks)
119
125
  if (ctx.channel === "canary" && !ctx.targetVersion)
120
126
  console.warn("\u26A0 Canary builds may contain bugs or breaking changes. Not recommended for production.");
121
127
  process.exit(ExitCode.Success);
128
+ async function runDryRunPreview() {
129
+ console.log(`
130
+ DRY RUN - preview only. No files will be written, nothing will be installed, no migrations will run.
131
+ `);
132
+ const dirty = await detectDirtyManagedPaths(projectRoot);
133
+ if (dirty.length > 0) {
134
+ console.warn(" Note: these framework-managed paths have uncommitted changes (a real run would abort without --force):");
135
+ for (const path of dirty)
136
+ console.warn(` - ${path}`);
137
+ console.warn("");
138
+ }
139
+ let previewSha = null;
140
+ if (!options.force && !ctx.targetVersion) {
141
+ previewSha = await getRemoteSha(ctx, usingLocal, detectedLocal);
142
+ const synced = readSyncedVersion(versionFile);
143
+ if (shouldShortCircuit({ force: !!options.force, targetVersion: ctx.targetVersion, remoteSha: previewSha, synced, channel: ctx.channel })) {
144
+ console.log(`\u2714 Already on the latest ${ctx.channel} (${previewSha.slice(0, 7)}). A real run would change nothing.`);
145
+ return;
146
+ }
147
+ }
148
+ const aggregate = { added: 0, changed: 0, removed: 0, unchanged: 0 }, perPath = [];
149
+ let sawRemoved = 0, sourceVersion = null;
150
+ const tmpBase = mkdtempSync(join(tmpdir(), "stacks-upgrade-dry-run-"));
151
+ try {
152
+ let repoTmp = null;
153
+ for (const managed of MANAGED_PATHS) {
154
+ const localTarget = join(projectRoot, managed.localPath), before = managed.isFile ? await singleFileSnapshot(localTarget) : await snapshotTree(localTarget, managed.skip);
155
+ let after;
156
+ if (usingLocal && detectedLocal) {
157
+ const src = join(detectedLocal, managed.subPath);
158
+ if (!existsSync(src)) {
159
+ console.log(` ${managed.label.padEnd(10)} skip: source missing at ${src}`);
160
+ continue;
161
+ }
162
+ after = managed.isFile ? await singleFileSnapshot(src) : await snapshotTree(src, managed.skip);
163
+ } else
164
+ try {
165
+ if (managed.isFile) {
166
+ if (!repoTmp) {
167
+ repoTmp = join(tmpBase, "repo");
168
+ await downloadTemplate(`github:stacksjs/stacks#${ctx.ref}`, {
169
+ dir: repoTmp,
170
+ force: !0,
171
+ forceClean: !0,
172
+ preferOffline: !0,
173
+ silent: !0
174
+ });
175
+ }
176
+ after = await singleFileSnapshot(join(repoTmp, managed.subPath));
177
+ } else {
178
+ const dir = join(tmpBase, managed.label);
179
+ await downloadTemplate(buildTemplateString(ctx.ref, managed.subPath), {
180
+ dir,
181
+ force: !0,
182
+ forceClean: !0,
183
+ preferOffline: !options.force,
184
+ silent: !0
185
+ });
186
+ after = await snapshotTree(dir, managed.skip);
187
+ }
188
+ } catch (err) {
189
+ console.log(` ${managed.label.padEnd(10)} preview unavailable (${err?.message || err}); a real run would sync from github:stacksjs/stacks#${ctx.ref}`);
190
+ continue;
191
+ }
192
+ const summary = diffSnapshotsDetailed(before, after);
193
+ aggregate.added += summary.added;
194
+ aggregate.changed += summary.changed;
195
+ aggregate.removed += summary.removed;
196
+ aggregate.unchanged += summary.unchanged;
197
+ perPath.push({ managed, summary });
198
+ sawRemoved += summary.removed;
199
+ if (managed.isFile) {
200
+ const moved = summary.added + summary.changed > 0;
201
+ console.log(` ${managed.label.padEnd(10)} ${moved ? "would update" : "unchanged"}`);
202
+ } else if (summary.added + summary.changed + summary.removed === 0)
203
+ console.log(` ${managed.label.padEnd(10)} unchanged (${summary.unchanged} files)`);
204
+ else {
205
+ console.log(` ${managed.label.padEnd(10)} +${summary.added} ~${summary.changed} -${summary.removed} (${summary.unchanged} unchanged)`);
206
+ const samples = [
207
+ ...summary.addedFiles.map((f) => `+ ${f}`),
208
+ ...summary.changedFiles.map((f) => `~ ${f}`)
209
+ ];
210
+ for (const line of samples.slice(0, 8))
211
+ console.log(` ${line}`);
212
+ if (samples.length > 8)
213
+ console.log(` ... and ${samples.length - 8} more`);
214
+ }
215
+ }
216
+ const sourcePkgPath = usingLocal && detectedLocal ? join(detectedLocal, "storage/framework/core/buddy/package.json") : repoTmp ? join(repoTmp, "storage/framework/core/buddy/package.json") : join(tmpBase, "core", "buddy", "package.json");
217
+ sourceVersion = readVersion(sourcePkgPath);
218
+ } finally {
219
+ rmSync(tmpBase, { recursive: !0, force: !0 });
220
+ }
221
+ console.log("");
222
+ if (currentVersion || sourceVersion)
223
+ console.log(currentVersion === sourceVersion ? ` version: unchanged (v${currentVersion ?? "unknown"})` : ` version: v${currentVersion ?? "unknown"} -> v${sourceVersion ?? "unknown"}`);
224
+ console.log(`
225
+ A real run would:`);
226
+ console.log(" - sync the managed paths above into place");
227
+ if (!ctx.targetVersion) {
228
+ console.log(` - write channel "${ctx.channel}" to .stacks-channel`);
229
+ console.log(previewSha ? ` - record synced sha ${previewSha.slice(0, 7)} in .stacks-version` : " - record the resolved commit sha in .stacks-version (unavailable in this preview)");
230
+ }
231
+ if (!(!options.noPostinstall && options.postinstall !== !1))
232
+ console.log(" - skip post-sync hooks (--no-postinstall)");
233
+ else if (aggregate.added + aggregate.changed + aggregate.removed === 0)
234
+ console.log(" - skip post-sync hooks (nothing changed)");
235
+ else {
236
+ console.log(" - regenerate the auto-import manifest");
237
+ if (perPath.some((entry) => {
238
+ const { managed, summary } = entry;
239
+ if (managed.isFile)
240
+ return !1;
241
+ if (managed.label !== "core" && managed.label !== "defaults")
242
+ return !1;
243
+ if (summary.added + summary.changed === 0)
244
+ return !1;
245
+ return pkgJsonInTree(join(projectRoot, managed.localPath));
246
+ }))
247
+ console.log(" - run `bun install` to refresh dependencies");
248
+ if (existsSync(join(projectRoot, "database", "migrations")))
249
+ console.log(" - run pending migrations");
250
+ }
251
+ if (sawRemoved > 0)
252
+ console.log(`
253
+ (-N counts files no longer shipped upstream; the sync leaves them in place.)`);
254
+ console.log(`
255
+ \u2714 Dry run complete. No changes were made.`);
256
+ }
122
257
  async function detectDirtyManagedPaths(root) {
123
258
  const gitDir = join(root, ".git");
124
259
  if (!existsSync(gitDir))
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/actions",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.70.113",
5
+ "version": "0.70.115",
6
6
  "description": "The Stacks actions.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -65,30 +65,30 @@
65
65
  "@stacksjs/bumpx": "^0.2.6",
66
66
  "@stacksjs/bunpress": "^0.1.12",
67
67
  "@stacksjs/logsmith": "^0.2.3",
68
- "@stacksjs/ts-cloud": "^0.7.17",
68
+ "@stacksjs/ts-cloud": "catalog:",
69
69
  "@stacksjs/ts-md": "^0.1.1"
70
70
  },
71
71
  "devDependencies": {
72
- "@stacksjs/api": "0.70.113",
73
- "@stacksjs/cli": "0.70.113",
74
- "@stacksjs/config": "0.70.113",
75
- "@stacksjs/database": "0.70.113",
72
+ "@stacksjs/api": "0.70.115",
73
+ "@stacksjs/cli": "0.70.115",
74
+ "@stacksjs/config": "0.70.115",
75
+ "@stacksjs/database": "0.70.115",
76
76
  "@stacksjs/tlsx": "^0.13.2",
77
- "better-dx": "^0.2.16",
78
- "@stacksjs/dns": "0.70.113",
79
- "@stacksjs/enums": "0.70.113",
80
- "@stacksjs/env": "0.70.113",
81
- "@stacksjs/error-handling": "0.70.113",
82
- "@stacksjs/logging": "0.70.113",
83
- "@stacksjs/path": "0.70.113",
84
- "@stacksjs/security": "0.70.113",
85
- "@stacksjs/storage": "0.70.113",
86
- "@stacksjs/strings": "0.70.113",
87
- "@stacksjs/utils": "0.70.113",
88
- "@stacksjs/validation": "0.70.113"
77
+ "better-dx": "catalog:",
78
+ "@stacksjs/dns": "0.70.115",
79
+ "@stacksjs/enums": "0.70.115",
80
+ "@stacksjs/env": "0.70.115",
81
+ "@stacksjs/error-handling": "0.70.115",
82
+ "@stacksjs/logging": "0.70.115",
83
+ "@stacksjs/path": "0.70.115",
84
+ "@stacksjs/security": "0.70.115",
85
+ "@stacksjs/storage": "0.70.115",
86
+ "@stacksjs/strings": "0.70.115",
87
+ "@stacksjs/utils": "0.70.115",
88
+ "@stacksjs/validation": "0.70.115"
89
89
  },
90
90
  "peerDependencies": {
91
- "pickier": "^0.1.28"
91
+ "pickier": "catalog:"
92
92
  },
93
93
  "peerDependenciesMeta": {
94
94
  "pickier": {