@bettercms-ai/convert 0.23.0 → 0.24.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 +6 -0
- package/dist/cli.js +75 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +18 -2
- package/dist/index.js +84 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @bettercms-ai/convert
|
|
2
2
|
|
|
3
|
+
## 0.24.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 86c0c9f: Helper v12: on a server BetterCMS hosts, each content snapshot resolves at request time to its published counterpart in the file the platform rewrites on every publish (`BCMS_CONTENT_FILE`), so a server-rendered page shows a publish in seconds without a rebuild. Builds, dev servers, browsers and edge runtimes are unchanged. New export `helperUpgrades()` lists the current helper per path with the digests of every older one it may replace.
|
|
8
|
+
|
|
3
9
|
## 0.23.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/dist/cli.js
CHANGED
|
@@ -4190,7 +4190,7 @@ async function bindImages(ctx, targets) {
|
|
|
4190
4190
|
|
|
4191
4191
|
// src/helper.ts
|
|
4192
4192
|
import { createHash as createHash2 } from "crypto";
|
|
4193
|
-
var HELPER_VERSION =
|
|
4193
|
+
var HELPER_VERSION = 12;
|
|
4194
4194
|
var HEADER = "// @bettercms-ai/convert helper v";
|
|
4195
4195
|
var HELPER_PATH = Object.fromEntries(
|
|
4196
4196
|
Object.keys(DIALECT_RULES).map((d) => [d, DIALECT_RULES[d].helper])
|
|
@@ -4247,8 +4247,69 @@ function render(value: unknown): string | undefined {
|
|
|
4247
4247
|
return undefined;
|
|
4248
4248
|
}
|
|
4249
4249
|
|
|
4250
|
+
/**
|
|
4251
|
+
* The PUBLISHED copy, on a server BetterCMS hosts \u2014 read at request time, not at build time.
|
|
4252
|
+
*
|
|
4253
|
+
* BetterCMS keeps one file current for a running server app (\`BCMS_CONTENT_FILE\`, the same
|
|
4254
|
+
* bcms-content.json the build was given) and rewrites it on every publish, so a server-rendered
|
|
4255
|
+
* page shows a publish within seconds instead of after a rebuild. Each snapshot this module reads
|
|
4256
|
+
* resolves to its live counterpart: the shared layout by identity, a page by its \`slug\`.
|
|
4257
|
+
*
|
|
4258
|
+
* Nowhere else does anything change: with no variable (a build, \`astro dev\`, a browser, an edge
|
|
4259
|
+
* runtime) every snapshot is the one the bundle imported, exactly as before. A file that cannot be
|
|
4260
|
+
* read keeps the last good copy; it is checked at most once a second.
|
|
4261
|
+
*/
|
|
4262
|
+
type BcmsLiveContent = { stamp: number; bySlug: Map<string, unknown>; layout: unknown };
|
|
4263
|
+
let bcmsLive: BcmsLiveContent | null = null;
|
|
4264
|
+
let bcmsLiveCheckedAt = 0;
|
|
4265
|
+
|
|
4266
|
+
function liveContent(): BcmsLiveContent | null {
|
|
4267
|
+
const proc = (globalThis as {
|
|
4268
|
+
process?: { env?: Record<string, string | undefined>; getBuiltinModule?: (id: string) => unknown };
|
|
4269
|
+
}).process;
|
|
4270
|
+
const file = proc?.env?.BCMS_CONTENT_FILE;
|
|
4271
|
+
if (!file || typeof proc?.getBuiltinModule !== "function") return null;
|
|
4272
|
+
const now = Date.now();
|
|
4273
|
+
if (now - bcmsLiveCheckedAt < 1000) return bcmsLive;
|
|
4274
|
+
bcmsLiveCheckedAt = now;
|
|
4275
|
+
try {
|
|
4276
|
+
const fs = proc.getBuiltinModule("node:fs") as {
|
|
4277
|
+
statSync(path: string): { mtimeMs: number };
|
|
4278
|
+
readFileSync(path: string, encoding: "utf8"): string;
|
|
4279
|
+
};
|
|
4280
|
+
const stamp = fs.statSync(file).mtimeMs;
|
|
4281
|
+
if (bcmsLive && bcmsLive.stamp === stamp) return bcmsLive;
|
|
4282
|
+
const snapshot: unknown = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
4283
|
+
const bySlug = new Map<string, unknown>();
|
|
4284
|
+
const collections = isRecord(snapshot) && isRecord(snapshot.collections) ? snapshot.collections : {};
|
|
4285
|
+
for (const rows of Object.values(collections)) {
|
|
4286
|
+
if (!Array.isArray(rows)) continue;
|
|
4287
|
+
for (const row of rows) {
|
|
4288
|
+
if (isRecord(row) && typeof row.slug === "string" && !bySlug.has(row.slug)) bySlug.set(row.slug, row);
|
|
4289
|
+
}
|
|
4290
|
+
}
|
|
4291
|
+
const pages = isRecord(snapshot) && Array.isArray(snapshot.pages) ? snapshot.pages : [];
|
|
4292
|
+
const withLayout = pages.find((page: unknown) => isRecord(page) && isRecord(page.layout));
|
|
4293
|
+
const layout = isRecord(withLayout) ? withLayout.layout : isRecord(snapshot) ? snapshot.layout : undefined;
|
|
4294
|
+
bcmsLive = { stamp, bySlug, layout };
|
|
4295
|
+
} catch {
|
|
4296
|
+
// Unreadable, or caught mid-write: keep serving the last good copy.
|
|
4297
|
+
}
|
|
4298
|
+
return bcmsLive;
|
|
4299
|
+
}
|
|
4300
|
+
|
|
4301
|
+
/** The published counterpart of a snapshot this module was handed, or the snapshot itself. */
|
|
4302
|
+
function live(page: unknown): unknown {
|
|
4303
|
+
const content = liveContent();
|
|
4304
|
+
if (!content) return page;
|
|
4305
|
+
if (page === layoutSnapshot) return isRecord(content.layout) ? content.layout : page;
|
|
4306
|
+
if (isRecord(page) && typeof page.slug === "string") return content.bySlug.get(page.slug) ?? page;
|
|
4307
|
+
return page;
|
|
4308
|
+
}
|
|
4309
|
+
|
|
4250
4310
|
/** One field of one page. \`slug\` selects the entry on a dynamic route. */
|
|
4251
4311
|
export function bcms(page: unknown, path: string, fallback: string, slug?: string): string {
|
|
4312
|
+
page = live(page);
|
|
4252
4313
|
const entries = isRecord(page) ? page.entries : undefined;
|
|
4253
4314
|
const root = slug !== undefined && isRecord(entries) ? entries[slug] : page;
|
|
4254
4315
|
return render(readPath(root, path)) ?? fallback;
|
|
@@ -4256,7 +4317,7 @@ export function bcms(page: unknown, path: string, fallback: string, slug?: strin
|
|
|
4256
4317
|
|
|
4257
4318
|
/** One field of the shared layout \u2014 the header and footer every route renders. */
|
|
4258
4319
|
export function bcmsLayout(path: string, fallback: string): string {
|
|
4259
|
-
return render(readPath(layoutSnapshot, path)) ?? fallback;
|
|
4320
|
+
return render(readPath(live(layoutSnapshot), path)) ?? fallback;
|
|
4260
4321
|
}
|
|
4261
4322
|
|
|
4262
4323
|
/**
|
|
@@ -4264,6 +4325,7 @@ export function bcmsLayout(path: string, fallback: string): string {
|
|
|
4264
4325
|
* an empty snapshot still renders the same number of cards it always did.
|
|
4265
4326
|
*/
|
|
4266
4327
|
export function bcmsRows<T>(page: unknown, path: string, fallback: T[], slug?: string): T[] {
|
|
4328
|
+
page = live(page);
|
|
4267
4329
|
const entries = isRecord(page) ? page.entries : undefined;
|
|
4268
4330
|
const root = slug !== undefined && isRecord(entries) ? entries[slug] : page;
|
|
4269
4331
|
const value = readPath(root, path);
|
|
@@ -4309,6 +4371,7 @@ export function bcmsRowsAs<T>(
|
|
|
4309
4371
|
* this out loud rather than leaving an editor to discover it.
|
|
4310
4372
|
*/
|
|
4311
4373
|
export function bcmsList(page: unknown, paths: string[], fallback: string[], slug?: string): string[] {
|
|
4374
|
+
page = live(page);
|
|
4312
4375
|
const entries = isRecord(page) ? page.entries : undefined;
|
|
4313
4376
|
const root = slug !== undefined && isRecord(entries) ? entries[slug] : page;
|
|
4314
4377
|
return paths.map((path, index) => render(readPath(root, path)) ?? fallback[index] ?? "");
|
|
@@ -4333,6 +4396,7 @@ export function bcmsTuples(page: unknown, paths: string[][], fallback: string[][
|
|
|
4333
4396
|
* no such rule and takes the CMS url directly.
|
|
4334
4397
|
*/
|
|
4335
4398
|
export function bcmsImage<T>(page: unknown, path: string, fallback: T, slug?: string): T | string {
|
|
4399
|
+
page = live(page);
|
|
4336
4400
|
if (fallback !== null && typeof fallback === "object") return fallback;
|
|
4337
4401
|
const entries = isRecord(page) ? page.entries : undefined;
|
|
4338
4402
|
const root = slug !== undefined && isRecord(entries) ? entries[slug] : page;
|
|
@@ -4361,6 +4425,7 @@ export function bcmsSection(
|
|
|
4361
4425
|
overrides?: unknown,
|
|
4362
4426
|
bindPaths?: Record<string, string>,
|
|
4363
4427
|
): Record<string, unknown> {
|
|
4428
|
+
page = live(page);
|
|
4364
4429
|
const group = bind ? readPath(page, bind) : undefined;
|
|
4365
4430
|
const base: Record<string, unknown> = isRecord(group) ? { ...group } : {};
|
|
4366
4431
|
// A locale copy on its twin's component spells its fields its own way: each prop's copy is
|
|
@@ -4432,6 +4497,7 @@ export function bcmsSectionPaths(
|
|
|
4432
4497
|
map: BcmsPathMap,
|
|
4433
4498
|
bindPaths?: Record<string, string>,
|
|
4434
4499
|
): Record<string, unknown> {
|
|
4500
|
+
page = live(page);
|
|
4435
4501
|
const out: Record<string, unknown> = isRecord(page) ? { ...page } : {};
|
|
4436
4502
|
const own = isRecord(overrides) ? overrides : {};
|
|
4437
4503
|
const separator = prefix.slice(-1);
|
|
@@ -4665,7 +4731,8 @@ var HISTORICAL = {
|
|
|
4665
4731
|
7: "f22514ef48c50230985e605bea6cf9bf41756384a7dc80603e347baba9b65d93",
|
|
4666
4732
|
8: "484e72852d2b496e016a1f2a2b1a77bb993f8a163b290781522d6114b6519bb9",
|
|
4667
4733
|
9: "d6441db2ff4578c3c5d4b7d461f3374b89247ef6ba9e0d535791e840d803e4f3",
|
|
4668
|
-
10: "ffcb59862972b15a67c5951e9f3b94ce5b8b50345e6aac2bfa5789cfc3136910"
|
|
4734
|
+
10: "ffcb59862972b15a67c5951e9f3b94ce5b8b50345e6aac2bfa5789cfc3136910",
|
|
4735
|
+
11: "ceb2a932d4c2761a5045ff35032e0b45130a0b5034547ff37579c72c9ce3594e"
|
|
4669
4736
|
},
|
|
4670
4737
|
"src/lib/bcms-content.ts": {
|
|
4671
4738
|
1: "ae72ae14d706943d481c880d70da5789b4816ba1ba319a10fbc63ded4d0b42f2",
|
|
@@ -4677,7 +4744,8 @@ var HISTORICAL = {
|
|
|
4677
4744
|
7: "ed92fb88de953d9951abbe6a1edae1d048f4050eaf6fb607ac08167f94d8bcc7",
|
|
4678
4745
|
8: "1a6f669d76d42effe77f082436e9d21c0efa6fc499e919e3d116bc3a27a7f3d5",
|
|
4679
4746
|
9: "eee9fb1635ae7d6f8f33676a1f390600ca24a62ee992775252273c73a011c494",
|
|
4680
|
-
10: "35bb7c0e30f5c41fe68e52259ec4764de6de2734064fa0e1521f3338eef0a09e"
|
|
4747
|
+
10: "35bb7c0e30f5c41fe68e52259ec4764de6de2734064fa0e1521f3338eef0a09e",
|
|
4748
|
+
11: "818784f2088150d64d91b42eac944dc9503f104d32a0e7a18c753d2982a5adc0"
|
|
4681
4749
|
},
|
|
4682
4750
|
"composables/bcms-content.ts": {
|
|
4683
4751
|
1: "c272412532efed7db64b6cf313b2bed4291f9951430412289c8a588b7f565407",
|
|
@@ -4689,7 +4757,8 @@ var HISTORICAL = {
|
|
|
4689
4757
|
7: "f22514ef48c50230985e605bea6cf9bf41756384a7dc80603e347baba9b65d93",
|
|
4690
4758
|
8: "484e72852d2b496e016a1f2a2b1a77bb993f8a163b290781522d6114b6519bb9",
|
|
4691
4759
|
9: "d6441db2ff4578c3c5d4b7d461f3374b89247ef6ba9e0d535791e840d803e4f3",
|
|
4692
|
-
10: "ffcb59862972b15a67c5951e9f3b94ce5b8b50345e6aac2bfa5789cfc3136910"
|
|
4760
|
+
10: "ffcb59862972b15a67c5951e9f3b94ce5b8b50345e6aac2bfa5789cfc3136910",
|
|
4761
|
+
11: "ceb2a932d4c2761a5045ff35032e0b45130a0b5034547ff37579c72c9ce3594e"
|
|
4693
4762
|
}
|
|
4694
4763
|
};
|
|
4695
4764
|
var sha256 = (value) => createHash2("sha256").update(value, "utf8").digest("hex");
|
|
@@ -10705,7 +10774,7 @@ function styleEdits(before, after) {
|
|
|
10705
10774
|
// package.json
|
|
10706
10775
|
var package_default = {
|
|
10707
10776
|
name: "@bettercms-ai/convert",
|
|
10708
|
-
version: "0.
|
|
10777
|
+
version: "0.24.0",
|
|
10709
10778
|
type: "module",
|
|
10710
10779
|
description: "Deterministic codemod that turns an imported site's text-matched bindings into declared ones \u2014 parser offsets in, one magic-string pass out, plus a receipt of everything it could not do.",
|
|
10711
10780
|
bin: {
|