@stacksjs/actions 0.70.113 → 0.70.114
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/auth/setup.js +4 -1
- package/dist/blog.js +23 -25
- package/dist/make.d.ts +1 -1
- package/dist/make.js +19 -13
- package/dist/upgrade/framework-utils.d.ts +13 -0
- package/dist/upgrade/framework-utils.js +28 -0
- package/dist/upgrade/framework.js +136 -1
- package/package.json +19 -19
package/dist/auth/setup.js
CHANGED
|
@@ -177,7 +177,10 @@ try {
|
|
|
177
177
|
)
|
|
178
178
|
`);
|
|
179
179
|
try {
|
|
180
|
-
|
|
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 `<
|
|
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
|
-
</
|
|
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
|
-
<
|
|
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
|
-
|
|
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(),
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
<
|
|
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
|
-
|
|
284
|
-
|
|
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-
|
|
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-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
292
|
+
const optionName = options.name;
|
|
287
293
|
if (!optionName[0])
|
|
288
294
|
throw Error("options.name is required and cannot be empty");
|
|
289
|
-
const
|
|
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(`
|
|
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.
|
|
5
|
+
"version": "0.70.114",
|
|
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": "
|
|
68
|
+
"@stacksjs/ts-cloud": "catalog:",
|
|
69
69
|
"@stacksjs/ts-md": "^0.1.1"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@stacksjs/api": "0.70.
|
|
73
|
-
"@stacksjs/cli": "0.70.
|
|
74
|
-
"@stacksjs/config": "0.70.
|
|
75
|
-
"@stacksjs/database": "0.70.
|
|
72
|
+
"@stacksjs/api": "0.70.114",
|
|
73
|
+
"@stacksjs/cli": "0.70.114",
|
|
74
|
+
"@stacksjs/config": "0.70.114",
|
|
75
|
+
"@stacksjs/database": "0.70.114",
|
|
76
76
|
"@stacksjs/tlsx": "^0.13.2",
|
|
77
|
-
"better-dx": "
|
|
78
|
-
"@stacksjs/dns": "0.70.
|
|
79
|
-
"@stacksjs/enums": "0.70.
|
|
80
|
-
"@stacksjs/env": "0.70.
|
|
81
|
-
"@stacksjs/error-handling": "0.70.
|
|
82
|
-
"@stacksjs/logging": "0.70.
|
|
83
|
-
"@stacksjs/path": "0.70.
|
|
84
|
-
"@stacksjs/security": "0.70.
|
|
85
|
-
"@stacksjs/storage": "0.70.
|
|
86
|
-
"@stacksjs/strings": "0.70.
|
|
87
|
-
"@stacksjs/utils": "0.70.
|
|
88
|
-
"@stacksjs/validation": "0.70.
|
|
77
|
+
"better-dx": "catalog:",
|
|
78
|
+
"@stacksjs/dns": "0.70.114",
|
|
79
|
+
"@stacksjs/enums": "0.70.114",
|
|
80
|
+
"@stacksjs/env": "0.70.114",
|
|
81
|
+
"@stacksjs/error-handling": "0.70.114",
|
|
82
|
+
"@stacksjs/logging": "0.70.114",
|
|
83
|
+
"@stacksjs/path": "0.70.114",
|
|
84
|
+
"@stacksjs/security": "0.70.114",
|
|
85
|
+
"@stacksjs/storage": "0.70.114",
|
|
86
|
+
"@stacksjs/strings": "0.70.114",
|
|
87
|
+
"@stacksjs/utils": "0.70.114",
|
|
88
|
+
"@stacksjs/validation": "0.70.114"
|
|
89
89
|
},
|
|
90
90
|
"peerDependencies": {
|
|
91
|
-
"pickier": "
|
|
91
|
+
"pickier": "catalog:"
|
|
92
92
|
},
|
|
93
93
|
"peerDependenciesMeta": {
|
|
94
94
|
"pickier": {
|