@maker-or/opencms 0.1.2 → 0.1.3

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 (3) hide show
  1. package/README.md +2 -0
  2. package/dist/index.js +135 -6
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -19,4 +19,6 @@ 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).
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;
@@ -55,6 +100,22 @@ function createSdk(options = {}) {
55
100
  body: JSON.stringify(input)
56
101
  })
57
102
  },
103
+ schema: {
104
+ get: () => {
105
+ if (!projectId)
106
+ throw new Error("projectId is required to get the schema");
107
+ return request(`/api/projects/${projectId}/schema`);
108
+ },
109
+ update: (schema) => {
110
+ if (!projectId)
111
+ throw new Error("projectId is required to update the schema");
112
+ return request(`/api/projects/${projectId}/schema`, {
113
+ method: "PUT",
114
+ headers: { "Content-Type": "application/json" },
115
+ body: JSON.stringify(schema)
116
+ });
117
+ }
118
+ },
58
119
  pages: {
59
120
  list: () => {
60
121
  if (!projectId)
@@ -67,8 +128,29 @@ function createSdk(options = {}) {
67
128
  return request(`/api/projects/${projectId}/pages`, {
68
129
  method: "POST",
69
130
  headers: { "Content-Type": "application/json" },
131
+ body: JSON.stringify({ ...input, environment, content: input.content ?? emptyPageContent })
132
+ });
133
+ },
134
+ get: (documentId) => {
135
+ if (!projectId)
136
+ throw new Error("projectId is required to get pages");
137
+ return request(`/api/projects/${projectId}/pages/${documentId}?environment=${environment}`);
138
+ },
139
+ update: (documentId, input) => {
140
+ if (!projectId)
141
+ throw new Error("projectId is required to update pages");
142
+ return request(`/api/projects/${projectId}/pages/${documentId}`, {
143
+ method: "PATCH",
144
+ headers: { "Content-Type": "application/json" },
70
145
  body: JSON.stringify({ ...input, environment })
71
146
  });
147
+ },
148
+ delete: (documentId) => {
149
+ if (!projectId)
150
+ throw new Error("projectId is required to delete pages");
151
+ return request(`/api/projects/${projectId}/pages/${documentId}?environment=${environment}`, {
152
+ method: "DELETE"
153
+ });
72
154
  }
73
155
  },
74
156
  deploy: (targetProjectId = projectId) => {
@@ -84,11 +166,36 @@ function createSdk(options = {}) {
84
166
  throw new Error("projectId is required to list documents");
85
167
  return request(`/api/projects/${projectId}/pages?environment=${environment}`);
86
168
  },
87
- create: (input) => request(`/api/projects/${projectId ?? ""}/pages`, {
88
- method: "POST",
89
- headers: { "Content-Type": "application/json" },
90
- body: JSON.stringify({ ...input, environment })
91
- })
169
+ create: (input) => {
170
+ if (!projectId)
171
+ throw new Error("projectId is required to create documents");
172
+ return request(`/api/projects/${projectId}/pages`, {
173
+ method: "POST",
174
+ headers: { "Content-Type": "application/json" },
175
+ body: JSON.stringify({ ...input, environment, content: input.content ?? emptyPageContent })
176
+ });
177
+ },
178
+ get: (documentId) => {
179
+ if (!projectId)
180
+ throw new Error("projectId is required to get documents");
181
+ return request(`/api/projects/${projectId}/pages/${documentId}?environment=${environment}`);
182
+ },
183
+ update: (documentId, input) => {
184
+ if (!projectId)
185
+ throw new Error("projectId is required to update documents");
186
+ return request(`/api/projects/${projectId}/pages/${documentId}`, {
187
+ method: "PATCH",
188
+ headers: { "Content-Type": "application/json" },
189
+ body: JSON.stringify({ ...input, environment })
190
+ });
191
+ },
192
+ delete: (documentId) => {
193
+ if (!projectId)
194
+ throw new Error("projectId is required to delete documents");
195
+ return request(`/api/projects/${projectId}/pages/${documentId}?environment=${environment}`, {
196
+ method: "DELETE"
197
+ });
198
+ }
92
199
  }
93
200
  };
94
201
  }
@@ -260,6 +367,11 @@ async function ensureCmsDirectory(destination, project, baseUrl) {
260
367
  apiUrl: process.env.OPENCMS_API_URL ?? "${baseUrl}",
261
368
  environment: process.env.OPENCMS_ENVIRONMENT ?? "development",
262
369
  } as const;
370
+ `, "utf8");
371
+ }
372
+ const schemaFile = join(cmsDirectory, "schema.json");
373
+ if (!await fileExists(schemaFile)) {
374
+ await writeFile(schemaFile, `${JSON.stringify(defaultSchema, null, 2)}
263
375
  `, "utf8");
264
376
  }
265
377
  }
@@ -283,7 +395,7 @@ async function installDependencies(destination) {
283
395
  }
284
396
  }
285
397
  async function pullTemplate(destination) {
286
- const repository = process.env.OPENCMS_TEMPLATE_REPO ?? "https://github.com/opencms/template-nextjs.git";
398
+ const repository = process.env.OPENCMS_TEMPLATE_REPO ?? "https://github.com/maker-or/nextjs-template.git";
287
399
  if (await fileExists(destination))
288
400
  throw new Error(`Destination already exists: ${destination}`);
289
401
  console.log("Pulling the OpenCMS Next.js template…");
@@ -331,10 +443,26 @@ Next steps:
331
443
  async function runDev() {
332
444
  const config = await readConfig();
333
445
  await ensureToken(config);
446
+ await syncLocalSchema(await projectIdFromEnv(), await readConfig());
334
447
  const manager = await packageManager(process.cwd());
335
448
  const command = manager[0] === "npm" ? ["npm", "run", "dev"] : manager[0] === "pnpm" ? ["pnpm", "dev"] : manager[0] === "yarn" ? ["yarn", "dev"] : ["bun", "run", "dev"];
336
449
  process.exit(await runCommand(command[0], command.slice(1), { cwd: process.cwd(), env: { ...process.env, OPENCMS_ENVIRONMENT: "development" }, inherit: true }));
337
450
  }
451
+ async function syncLocalSchema(projectId, config) {
452
+ if (!projectId)
453
+ return;
454
+ const schemaPath = join(process.cwd(), "cms", "schema.json");
455
+ if (!await fileExists(schemaPath))
456
+ return;
457
+ let schema;
458
+ try {
459
+ schema = JSON.parse(await readFile(schemaPath, "utf8"));
460
+ } catch {
461
+ throw new Error("cms/schema.json is not valid JSON.");
462
+ }
463
+ console.log("Syncing the OpenCMS schema to development…");
464
+ await sdk(config, projectId).schema.update(schema);
465
+ }
338
466
  function projectIdFromEnv() {
339
467
  const envPath = join(process.cwd(), ".env.local");
340
468
  return fileExists(envPath).then(async (exists) => {
@@ -350,6 +478,7 @@ async function deploy() {
350
478
  const projectId = await projectIdFromEnv() ?? config.projectId;
351
479
  if (!projectId)
352
480
  throw new Error("No OpenCMS project is configured in this directory.");
481
+ await syncLocalSchema(projectId, await readConfig());
353
482
  const deployment = await sdk(await readConfig()).deploy(projectId);
354
483
  console.log(`Deployed ${deployment.sourceEnvironment} content to ${deployment.targetEnvironment}.`);
355
484
  if (process.env.VERCEL_TOKEN) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maker-or/opencms",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "The developer-first CLI for OpenCMS",
5
5
  "type": "module",
6
6
  "repository": {