riverbankcms 0.1.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.
Files changed (30) hide show
  1. package/README.md +21 -0
  2. package/dist/acceptance/matrix.mjs +784 -0
  3. package/dist/cli/index.mjs +110989 -0
  4. package/dist/cli/init-docs/content/agents-section.md +67 -0
  5. package/dist/cli/init-docs/content/cli-reference.md +1238 -0
  6. package/dist/cli/init-docs/content/content-management.md +792 -0
  7. package/dist/cli/init-docs/content/context-brand.md +125 -0
  8. package/dist/cli/init-docs/content/context-brief.md +77 -0
  9. package/dist/cli/init-docs/content/context-knowledge.md +111 -0
  10. package/dist/cli/init-docs/content/getting-started.md +171 -0
  11. package/dist/cli/init-docs/content/site-workflows-readme.md +96 -0
  12. package/dist/cli/init-docs/content/workflow-add-block.md +299 -0
  13. package/dist/cli/init-docs/content/workflow-agent-safe-sync.md +83 -0
  14. package/dist/cli/init-docs/content/workflow-block-extensions.md +370 -0
  15. package/dist/cli/init-docs/content/workflow-cmsify-page.md +357 -0
  16. package/dist/cli/init-docs/content/workflow-content-types.md +330 -0
  17. package/dist/cli/init-docs/content/workflow-create-page.md +212 -0
  18. package/dist/cli/init-docs/content/workflow-custom-block.md +470 -0
  19. package/dist/cli/init-docs/content/workflow-editor-workflows.md +130 -0
  20. package/dist/cli/init-docs/content/workflow-isr-revalidation.md +158 -0
  21. package/dist/cli/init-docs/content/workflow-preview-mode.md +252 -0
  22. package/dist/cli/init-docs/content/workflow-publish.md +285 -0
  23. package/dist/cli/init-docs/content/workflow-remote-setup.md +51 -0
  24. package/dist/cli/init-docs/content/workflow-templates.md +381 -0
  25. package/dist/load-config-CRB4AHKq.mjs +5 -0
  26. package/dist/load-config-r1s4htWu.mjs +87 -0
  27. package/dist/sdk-peer-DrblJmno.mjs +217 -0
  28. package/dist/style-Chv9Gcwq.mjs +49167 -0
  29. package/dist/testing.mjs +5 -0
  30. package/package.json +76 -0
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import "./sdk-peer-DrblJmno.mjs";
3
+ import { t as loadConfigFile } from "./load-config-r1s4htWu.mjs";
4
+
5
+ export { loadConfigFile };
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ import { n as assertCompatibleSdkPeer } from "./sdk-peer-DrblJmno.mjs";
3
+ import { dirname, resolve } from "path";
4
+ import { createJiti } from "jiti";
5
+ import { existsSync } from "fs";
6
+ import { fileURLToPath } from "url";
7
+
8
+ //#region src/load-config.ts
9
+ /**
10
+ * Config file loader for riverbank.config.ts
11
+ *
12
+ * Uses jiti to load TypeScript config files at runtime without
13
+ * requiring a build step.
14
+ */
15
+ const DEFAULT_CONFIG_FILENAME = "riverbank.config.ts";
16
+ const currentDir = dirname(fileURLToPath(import.meta.url));
17
+ /**
18
+ * Load builder config from a TypeScript file.
19
+ *
20
+ * @param configPath - Path to config file, or directory containing riverbank.config.ts
21
+ * @returns The loaded config object
22
+ * @throws Error if config file not found or invalid
23
+ */
24
+ async function loadConfigFile(configPath) {
25
+ const resolvedPath = resolveConfigPath(configPath);
26
+ if (!existsSync(resolvedPath)) {
27
+ throw new Error(`Config file not found: ${resolvedPath}\n` + `Create a riverbank.config.ts file or specify a path with --config`);
28
+ }
29
+ assertCompatibleSdkPeer(resolvedPath);
30
+ process.stderr.write(`Loading config from ${resolvedPath}...\n`);
31
+ const alias = {};
32
+ const sourceConfigPath = resolve(currentDir, "..", "config", "index.ts");
33
+ const sourceIndexPath = resolve(currentDir, "..", "index.ts");
34
+ if (existsSync(sourceConfigPath)) {
35
+ alias["@riverbankcms/sdk/config"] = sourceConfigPath;
36
+ }
37
+ if (existsSync(sourceIndexPath)) {
38
+ alias["@riverbankcms/sdk"] = sourceIndexPath;
39
+ }
40
+ const blocksDir = resolve(currentDir, "../../../blocks/src");
41
+ if (existsSync(blocksDir)) {
42
+ alias["@riverbankcms/blocks"] = blocksDir;
43
+ }
44
+ const mediaCorePath = resolve(currentDir, "../../../media-core/src/index.ts");
45
+ if (existsSync(mediaCorePath)) {
46
+ alias["@riverbankcms/media-core"] = mediaCorePath;
47
+ }
48
+ const jiti = createJiti(import.meta.url, {
49
+ fsCache: false,
50
+ moduleCache: false,
51
+ alias: Object.keys(alias).length > 0 ? alias : undefined,
52
+ jsx: Object.keys(alias).length > 0
53
+ });
54
+ try {
55
+ const configModule = await jiti.import(resolvedPath);
56
+ const config = configModule.default ?? configModule.config ?? configModule;
57
+ if (!config || typeof config !== "object") {
58
+ throw new Error("Config file must export a configuration object");
59
+ }
60
+ return config;
61
+ } catch (error) {
62
+ if (error instanceof Error) {
63
+ throw new Error(`Failed to load config: ${error.message}`);
64
+ }
65
+ throw error;
66
+ }
67
+ }
68
+ /**
69
+ * Resolve config path from user input.
70
+ *
71
+ * If no path provided, looks for riverbank.config.ts in cwd.
72
+ * If path is a directory, looks for riverbank.config.ts in that directory.
73
+ * If path is a file, uses it directly.
74
+ */
75
+ function resolveConfigPath(configPath) {
76
+ if (!configPath) {
77
+ return resolve(process.cwd(), DEFAULT_CONFIG_FILENAME);
78
+ }
79
+ const resolved = resolve(configPath);
80
+ if (existsSync(resolved) && !resolved.endsWith(".ts") && !resolved.endsWith(".js")) {
81
+ return resolve(resolved, DEFAULT_CONFIG_FILENAME);
82
+ }
83
+ return resolved;
84
+ }
85
+
86
+ //#endregion
87
+ export { loadConfigFile as t };
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { dirname, join, parse } from "node:path";
4
+
5
+ //#region package.json
6
+ var version = "0.1.0";
7
+ var peerDependencies = { "@riverbankcms/sdk": ">=0.129.1 <1.0.0" };
8
+ var package_default = {
9
+ name: "riverbankcms",
10
+ version,
11
+ description: "Riverbank CMS command-line tools for SDK site developers",
12
+ bin: { "riverbankcms": "dist/cli/index.mjs" },
13
+ exports: {
14
+ "./testing": "./dist/testing.mjs",
15
+ "./acceptance/matrix": "./dist/acceptance/matrix.mjs",
16
+ "./package.json": "./package.json"
17
+ },
18
+ files: ["dist", "README.md"],
19
+ engines: { "node": ">=18" },
20
+ scripts: {
21
+ "clean:dist": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
22
+ "build": "node scripts/build.mjs",
23
+ "dev": "node scripts/build.mjs --watch",
24
+ "typecheck": "tsgo --noEmit",
25
+ "lint": "node ../../scripts/run-package-lint.mjs src",
26
+ "test": "node scripts/run-tests.mjs",
27
+ "test:bun": "node scripts/run-bun-tests.mjs",
28
+ "test:bun:check": "node scripts/run-bun-tests.mjs --check",
29
+ "test:bun:list": "node scripts/run-bun-tests.mjs --list",
30
+ "check:packed-exports": "node scripts/check-packed-exports.mjs",
31
+ "check:consumer-contract": "node scripts/check-packed-consumer-contract.mjs",
32
+ "cli": "pnpm --filter @riverbankcms/sdk build && pnpm build && node dist/cli/index.mjs"
33
+ },
34
+ dependencies: {
35
+ "commander": "^12.1.0",
36
+ "dotenv": "^16.4.5",
37
+ "fast-deep-equal": "^3.1.3",
38
+ "jiti": "^2.7.0",
39
+ "prompts": "^2.4.2",
40
+ "simple-git": "^3.36.0",
41
+ "zod": "^4.3.6"
42
+ },
43
+ peerDependencies,
44
+ devDependencies: {
45
+ "@riverbankcms/api": "workspace:*",
46
+ "@riverbankcms/blocks": "workspace:*",
47
+ "@riverbankcms/content-model": "workspace:*",
48
+ "@riverbankcms/core": "workspace:*",
49
+ "@riverbankcms/management-client": "workspace:*",
50
+ "@riverbankcms/media-core": "workspace:*",
51
+ "@riverbankcms/sdk": "workspace:*",
52
+ "@riverbankcms/site-commands": "workspace:*",
53
+ "@riverbankcms/test-support": "workspace:*",
54
+ "@riverbankcms/theme-core": "workspace:*",
55
+ "@types/node": "^22.18.5",
56
+ "@types/prompts": "^2.4.9",
57
+ "tsdown": "^0.16.5",
58
+ "tsx": "^4.20.6",
59
+ "typescript": "^6.0.3"
60
+ },
61
+ repository: {
62
+ "type": "git",
63
+ "url": "git+https://github.com/riverbankcms/riverbankcms.git",
64
+ "directory": "packages/cli"
65
+ },
66
+ keywords: [
67
+ "headless-cms",
68
+ "riverbankcms",
69
+ "cms",
70
+ "cli"
71
+ ],
72
+ license: "MIT",
73
+ "private": false
74
+ };
75
+
76
+ //#endregion
77
+ //#region src/version.ts
78
+ /** The package manifest is the source-run fallback; builds inject this value. */
79
+ const CLI_VERSION = typeof "0.1.0" === "string" ? "0.1.0" : version;
80
+ /**
81
+ * The CLI's SDK peer range is bundled from the CLI manifest alongside its
82
+ * version. Runtime config loading uses this value as the single compatibility
83
+ * contract for the SDK installed by the site.
84
+ */
85
+ const CLI_SDK_PEER_RANGE = peerDependencies["@riverbankcms/sdk"];
86
+
87
+ //#endregion
88
+ //#region src/sdk-peer.ts
89
+ const SDK_PACKAGE_NAME = "@riverbankcms/sdk";
90
+ const SDK_INSTALL_COMMAND = (range) => `pnpm add ${SDK_PACKAGE_NAME}@'${range}'`;
91
+ /**
92
+ * A typed config-load failure raised before jiti imports the site config. This
93
+ * keeps missing/incompatible SDK failures actionable and prevents Node's raw
94
+ * module-resolution stack from reaching CLI users.
95
+ */
96
+ var CliSdkPeerError = class extends Error {
97
+ constructor(options) {
98
+ const { status, requiredRange, installedVersion } = options;
99
+ const detail = status === "missing" ? `No ${SDK_PACKAGE_NAME} package was found in this site.` : `This site has ${SDK_PACKAGE_NAME}@${installedVersion ?? "an invalid version"}.`;
100
+ const installCommand = SDK_INSTALL_COMMAND(requiredRange);
101
+ super(`${detail} The Riverbank CLI requires ${SDK_PACKAGE_NAME}@${requiredRange}. ` + `Install a compatible SDK with: ${installCommand}`);
102
+ this.code = "sdk:incompatible-sdk";
103
+ this.name = "CliSdkPeerError";
104
+ this.status = status;
105
+ this.requiredRange = requiredRange;
106
+ this.installedVersion = installedVersion;
107
+ this.installCommand = installCommand;
108
+ }
109
+ };
110
+ function parseStableVersion(value) {
111
+ const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(value.trim());
112
+ if (!match) return undefined;
113
+ const major = Number(match[1]);
114
+ const minor = Number(match[2]);
115
+ const patch = Number(match[3]);
116
+ if (![
117
+ major,
118
+ minor,
119
+ patch
120
+ ].every(Number.isSafeInteger)) return undefined;
121
+ return [
122
+ major,
123
+ minor,
124
+ patch
125
+ ];
126
+ }
127
+ function compareVersions(left, right) {
128
+ for (let index = 0; index < left.length; index += 1) {
129
+ const leftPart = left[index];
130
+ const rightPart = right[index];
131
+ if (leftPart === undefined || rightPart === undefined) continue;
132
+ if (leftPart < rightPart) return -1;
133
+ if (leftPart > rightPart) return 1;
134
+ }
135
+ return 0;
136
+ }
137
+ function parsePeerRange(value) {
138
+ const match = /^\s*>=\s*(\d+\.\d+\.\d+)\s+<\s*(\d+\.\d+\.\d+)\s*$/.exec(value);
139
+ if (!match) return undefined;
140
+ const floor = parseStableVersion(match[1] ?? "");
141
+ const ceiling = parseStableVersion(match[2] ?? "");
142
+ if (!floor || !ceiling || compareVersions(floor, ceiling) >= 0) return undefined;
143
+ return {
144
+ floor,
145
+ ceiling
146
+ };
147
+ }
148
+ const parsedCliSdkPeerRange = parsePeerRange(CLI_SDK_PEER_RANGE);
149
+ if (!parsedCliSdkPeerRange) {
150
+ throw new Error(`CLI package contains an unsupported SDK peer range: ${CLI_SDK_PEER_RANGE}`);
151
+ }
152
+ function isVersionInPeerRange(version$1, range) {
153
+ const parsedVersion = parseStableVersion(version$1);
154
+ if (!parsedVersion) return false;
155
+ return compareVersions(parsedVersion, range.floor) >= 0 && compareVersions(parsedVersion, range.ceiling) < 0;
156
+ }
157
+ function resolveSdkMetadataPath(fromPath) {
158
+ let directory = dirname(fromPath);
159
+ const root = parse(directory).root;
160
+ while (true) {
161
+ const manifestPath = join(directory, "node_modules", SDK_PACKAGE_NAME, "package.json");
162
+ if (existsSync(manifestPath)) return manifestPath;
163
+ if (directory === root) break;
164
+ directory = dirname(directory);
165
+ }
166
+ throw new Error(`Unable to locate ${SDK_PACKAGE_NAME} package metadata.`);
167
+ }
168
+ function readSdkMetadata(metadataPath) {
169
+ const manifest = JSON.parse(readFileSync(metadataPath, "utf8"));
170
+ if (manifest.name !== SDK_PACKAGE_NAME || typeof manifest.version !== "string") {
171
+ throw new Error(`Invalid ${SDK_PACKAGE_NAME} package metadata.`);
172
+ }
173
+ return {
174
+ name: SDK_PACKAGE_NAME,
175
+ version: manifest.version
176
+ };
177
+ }
178
+ /**
179
+ * Resolve and validate the one SDK package that the site config can import.
180
+ * Only package metadata is read here; the config import later resolves the
181
+ * same package through jiti, so this check cannot introduce another SDK copy.
182
+ */
183
+ function assertCompatibleSdkPeer(fromPath, options = {}) {
184
+ const requiredRange = options.requiredRange ?? CLI_SDK_PEER_RANGE;
185
+ const parsedRequiredRange = requiredRange === CLI_SDK_PEER_RANGE ? parsedCliSdkPeerRange : parsePeerRange(requiredRange);
186
+ const resolveMetadataPath = options.resolveMetadataPath ?? resolveSdkMetadataPath;
187
+ const readMetadata = options.readMetadata ?? readSdkMetadata;
188
+ let metadataPath;
189
+ try {
190
+ metadataPath = resolveMetadataPath(fromPath);
191
+ } catch {
192
+ throw new CliSdkPeerError({
193
+ status: "missing",
194
+ requiredRange
195
+ });
196
+ }
197
+ let metadata;
198
+ try {
199
+ metadata = readMetadata(metadataPath);
200
+ } catch {
201
+ throw new CliSdkPeerError({
202
+ status: "missing",
203
+ requiredRange
204
+ });
205
+ }
206
+ if (!parsedRequiredRange || !isVersionInPeerRange(metadata.version, parsedRequiredRange)) {
207
+ throw new CliSdkPeerError({
208
+ status: "incompatible",
209
+ requiredRange,
210
+ installedVersion: metadata.version
211
+ });
212
+ }
213
+ return metadata;
214
+ }
215
+
216
+ //#endregion
217
+ export { assertCompatibleSdkPeer as n, CLI_VERSION as r, CliSdkPeerError as t };