@maker-or/opencms 0.1.2 → 0.1.4
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/README.md +4 -0
- package/dist/index.js +144 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,4 +19,8 @@ npx @maker-or/opencms deploy
|
|
|
19
19
|
|
|
20
20
|
`opencms create` authenticates you, creates an OpenCMS project, pulls the Next.js template, writes the project configuration, and installs dependencies.
|
|
21
21
|
|
|
22
|
+
The generated `cms/schema.json` file defines the project's content types and allowed blocks. The CLI syncs it to the development environment when `dev` or `deploy` runs.
|
|
23
|
+
|
|
22
24
|
The CLI stores its local login configuration in `~/.config/opencms/config.json` (or `$XDG_CONFIG_HOME/opencms/config.json` when configured).
|
|
25
|
+
|
|
26
|
+
The CLI defaults to the hosted OpenCMS dashboard and API. Use `OPENCMS_DASHBOARD_URL` and `OPENCMS_API_URL` to target a local or self-hosted instance.
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,51 @@ import { spawn } from "node:child_process";
|
|
|
10
10
|
import { createInterface } from "node:readline/promises";
|
|
11
11
|
import process from "node:process";
|
|
12
12
|
|
|
13
|
+
// ../../packages/sdk/src/schema.ts
|
|
14
|
+
var emptyPageContent = { version: 1, blocks: [] };
|
|
15
|
+
var defaultSchema = {
|
|
16
|
+
version: 1,
|
|
17
|
+
blocks: {
|
|
18
|
+
heading: {
|
|
19
|
+
label: "Heading",
|
|
20
|
+
fields: {
|
|
21
|
+
text: { type: "text", label: "Text", required: true },
|
|
22
|
+
level: { type: "number", label: "Level", required: true }
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
text: {
|
|
26
|
+
label: "Text",
|
|
27
|
+
fields: {
|
|
28
|
+
text: { type: "text", label: "Text", required: true }
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
quote: {
|
|
32
|
+
label: "Quote",
|
|
33
|
+
fields: {
|
|
34
|
+
text: { type: "text", label: "Quote", required: true },
|
|
35
|
+
author: { type: "text", label: "Author" }
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"feature-list": {
|
|
39
|
+
label: "Feature list",
|
|
40
|
+
fields: {
|
|
41
|
+
title: { type: "text", label: "Title", required: true },
|
|
42
|
+
items: { type: "text", label: "Items", required: true }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
contentTypes: {
|
|
47
|
+
page: {
|
|
48
|
+
label: "Page",
|
|
49
|
+
fields: {
|
|
50
|
+
title: { type: "text", label: "Title", required: true },
|
|
51
|
+
slug: { type: "slug", label: "Slug", required: true, unique: true }
|
|
52
|
+
},
|
|
53
|
+
blocks: ["heading", "text", "quote", "feature-list"]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
13
58
|
// ../../packages/sdk/src/index.ts
|
|
14
59
|
class OpenCmsApiError extends Error {
|
|
15
60
|
status;
|
|
@@ -20,7 +65,12 @@ class OpenCmsApiError extends Error {
|
|
|
20
65
|
}
|
|
21
66
|
}
|
|
22
67
|
function createSdk(options = {}) {
|
|
23
|
-
const
|
|
68
|
+
const defaultBaseUrl = typeof window === "undefined" ? undefined : window.location.origin;
|
|
69
|
+
const configuredBaseUrl = options.baseUrl ?? defaultBaseUrl;
|
|
70
|
+
if (!configuredBaseUrl) {
|
|
71
|
+
throw new Error("baseUrl is required when using the OpenCMS SDK outside a browser.");
|
|
72
|
+
}
|
|
73
|
+
const baseUrl = configuredBaseUrl.replace(/\/$/, "");
|
|
24
74
|
const fetcher = options.fetch ?? globalThis.fetch;
|
|
25
75
|
const projectId = options.projectId;
|
|
26
76
|
const environment = options.environment ?? "development";
|
|
@@ -55,6 +105,22 @@ function createSdk(options = {}) {
|
|
|
55
105
|
body: JSON.stringify(input)
|
|
56
106
|
})
|
|
57
107
|
},
|
|
108
|
+
schema: {
|
|
109
|
+
get: () => {
|
|
110
|
+
if (!projectId)
|
|
111
|
+
throw new Error("projectId is required to get the schema");
|
|
112
|
+
return request(`/api/projects/${projectId}/schema`);
|
|
113
|
+
},
|
|
114
|
+
update: (schema) => {
|
|
115
|
+
if (!projectId)
|
|
116
|
+
throw new Error("projectId is required to update the schema");
|
|
117
|
+
return request(`/api/projects/${projectId}/schema`, {
|
|
118
|
+
method: "PUT",
|
|
119
|
+
headers: { "Content-Type": "application/json" },
|
|
120
|
+
body: JSON.stringify(schema)
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
},
|
|
58
124
|
pages: {
|
|
59
125
|
list: () => {
|
|
60
126
|
if (!projectId)
|
|
@@ -67,8 +133,29 @@ function createSdk(options = {}) {
|
|
|
67
133
|
return request(`/api/projects/${projectId}/pages`, {
|
|
68
134
|
method: "POST",
|
|
69
135
|
headers: { "Content-Type": "application/json" },
|
|
136
|
+
body: JSON.stringify({ ...input, environment, content: input.content ?? emptyPageContent })
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
get: (documentId) => {
|
|
140
|
+
if (!projectId)
|
|
141
|
+
throw new Error("projectId is required to get pages");
|
|
142
|
+
return request(`/api/projects/${projectId}/pages/${documentId}?environment=${environment}`);
|
|
143
|
+
},
|
|
144
|
+
update: (documentId, input) => {
|
|
145
|
+
if (!projectId)
|
|
146
|
+
throw new Error("projectId is required to update pages");
|
|
147
|
+
return request(`/api/projects/${projectId}/pages/${documentId}`, {
|
|
148
|
+
method: "PATCH",
|
|
149
|
+
headers: { "Content-Type": "application/json" },
|
|
70
150
|
body: JSON.stringify({ ...input, environment })
|
|
71
151
|
});
|
|
152
|
+
},
|
|
153
|
+
delete: (documentId) => {
|
|
154
|
+
if (!projectId)
|
|
155
|
+
throw new Error("projectId is required to delete pages");
|
|
156
|
+
return request(`/api/projects/${projectId}/pages/${documentId}?environment=${environment}`, {
|
|
157
|
+
method: "DELETE"
|
|
158
|
+
});
|
|
72
159
|
}
|
|
73
160
|
},
|
|
74
161
|
deploy: (targetProjectId = projectId) => {
|
|
@@ -84,18 +171,44 @@ function createSdk(options = {}) {
|
|
|
84
171
|
throw new Error("projectId is required to list documents");
|
|
85
172
|
return request(`/api/projects/${projectId}/pages?environment=${environment}`);
|
|
86
173
|
},
|
|
87
|
-
create: (input) =>
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
174
|
+
create: (input) => {
|
|
175
|
+
if (!projectId)
|
|
176
|
+
throw new Error("projectId is required to create documents");
|
|
177
|
+
return request(`/api/projects/${projectId}/pages`, {
|
|
178
|
+
method: "POST",
|
|
179
|
+
headers: { "Content-Type": "application/json" },
|
|
180
|
+
body: JSON.stringify({ ...input, environment, content: input.content ?? emptyPageContent })
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
get: (documentId) => {
|
|
184
|
+
if (!projectId)
|
|
185
|
+
throw new Error("projectId is required to get documents");
|
|
186
|
+
return request(`/api/projects/${projectId}/pages/${documentId}?environment=${environment}`);
|
|
187
|
+
},
|
|
188
|
+
update: (documentId, input) => {
|
|
189
|
+
if (!projectId)
|
|
190
|
+
throw new Error("projectId is required to update documents");
|
|
191
|
+
return request(`/api/projects/${projectId}/pages/${documentId}`, {
|
|
192
|
+
method: "PATCH",
|
|
193
|
+
headers: { "Content-Type": "application/json" },
|
|
194
|
+
body: JSON.stringify({ ...input, environment })
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
delete: (documentId) => {
|
|
198
|
+
if (!projectId)
|
|
199
|
+
throw new Error("projectId is required to delete documents");
|
|
200
|
+
return request(`/api/projects/${projectId}/pages/${documentId}?environment=${environment}`, {
|
|
201
|
+
method: "DELETE"
|
|
202
|
+
});
|
|
203
|
+
}
|
|
92
204
|
}
|
|
93
205
|
};
|
|
94
206
|
}
|
|
95
207
|
|
|
96
208
|
// src/index.ts
|
|
97
|
-
var
|
|
98
|
-
var
|
|
209
|
+
var hostedUrl = "https://web-eta-ten-16.vercel.app";
|
|
210
|
+
var dashboardUrl = process.env.OPENCMS_DASHBOARD_URL ?? hostedUrl;
|
|
211
|
+
var apiUrl = process.env.OPENCMS_API_URL ?? hostedUrl;
|
|
99
212
|
var configRoot = process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
|
|
100
213
|
var configPath = join(configRoot, "opencms", "config.json");
|
|
101
214
|
async function readConfig() {
|
|
@@ -260,6 +373,11 @@ async function ensureCmsDirectory(destination, project, baseUrl) {
|
|
|
260
373
|
apiUrl: process.env.OPENCMS_API_URL ?? "${baseUrl}",
|
|
261
374
|
environment: process.env.OPENCMS_ENVIRONMENT ?? "development",
|
|
262
375
|
} as const;
|
|
376
|
+
`, "utf8");
|
|
377
|
+
}
|
|
378
|
+
const schemaFile = join(cmsDirectory, "schema.json");
|
|
379
|
+
if (!await fileExists(schemaFile)) {
|
|
380
|
+
await writeFile(schemaFile, `${JSON.stringify(defaultSchema, null, 2)}
|
|
263
381
|
`, "utf8");
|
|
264
382
|
}
|
|
265
383
|
}
|
|
@@ -283,7 +401,7 @@ async function installDependencies(destination) {
|
|
|
283
401
|
}
|
|
284
402
|
}
|
|
285
403
|
async function pullTemplate(destination) {
|
|
286
|
-
const repository = process.env.OPENCMS_TEMPLATE_REPO ?? "https://github.com/
|
|
404
|
+
const repository = process.env.OPENCMS_TEMPLATE_REPO ?? "https://github.com/maker-or/nextjs-template.git";
|
|
287
405
|
if (await fileExists(destination))
|
|
288
406
|
throw new Error(`Destination already exists: ${destination}`);
|
|
289
407
|
console.log("Pulling the OpenCMS Next.js template…");
|
|
@@ -331,10 +449,26 @@ Next steps:
|
|
|
331
449
|
async function runDev() {
|
|
332
450
|
const config = await readConfig();
|
|
333
451
|
await ensureToken(config);
|
|
452
|
+
await syncLocalSchema(await projectIdFromEnv(), await readConfig());
|
|
334
453
|
const manager = await packageManager(process.cwd());
|
|
335
454
|
const command = manager[0] === "npm" ? ["npm", "run", "dev"] : manager[0] === "pnpm" ? ["pnpm", "dev"] : manager[0] === "yarn" ? ["yarn", "dev"] : ["bun", "run", "dev"];
|
|
336
455
|
process.exit(await runCommand(command[0], command.slice(1), { cwd: process.cwd(), env: { ...process.env, OPENCMS_ENVIRONMENT: "development" }, inherit: true }));
|
|
337
456
|
}
|
|
457
|
+
async function syncLocalSchema(projectId, config) {
|
|
458
|
+
if (!projectId)
|
|
459
|
+
return;
|
|
460
|
+
const schemaPath = join(process.cwd(), "cms", "schema.json");
|
|
461
|
+
if (!await fileExists(schemaPath))
|
|
462
|
+
return;
|
|
463
|
+
let schema;
|
|
464
|
+
try {
|
|
465
|
+
schema = JSON.parse(await readFile(schemaPath, "utf8"));
|
|
466
|
+
} catch {
|
|
467
|
+
throw new Error("cms/schema.json is not valid JSON.");
|
|
468
|
+
}
|
|
469
|
+
console.log("Syncing the OpenCMS schema to development…");
|
|
470
|
+
await sdk(config, projectId).schema.update(schema);
|
|
471
|
+
}
|
|
338
472
|
function projectIdFromEnv() {
|
|
339
473
|
const envPath = join(process.cwd(), ".env.local");
|
|
340
474
|
return fileExists(envPath).then(async (exists) => {
|
|
@@ -350,6 +484,7 @@ async function deploy() {
|
|
|
350
484
|
const projectId = await projectIdFromEnv() ?? config.projectId;
|
|
351
485
|
if (!projectId)
|
|
352
486
|
throw new Error("No OpenCMS project is configured in this directory.");
|
|
487
|
+
await syncLocalSchema(projectId, await readConfig());
|
|
353
488
|
const deployment = await sdk(await readConfig()).deploy(projectId);
|
|
354
489
|
console.log(`Deployed ${deployment.sourceEnvironment} content to ${deployment.targetEnvironment}.`);
|
|
355
490
|
if (process.env.VERCEL_TOKEN) {
|