@angeloashmore/prismic-cli-poc 0.0.0-pr.8.b80fefa → 0.0.0-pr.9.5366ece
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/index.mjs +302 -168
- package/package.json +1 -1
- package/src/custom-type-add-field-boolean.ts +49 -12
- package/src/custom-type-add-field-color.ts +46 -12
- package/src/custom-type-add-field-date.ts +46 -12
- package/src/custom-type-add-field-embed.ts +46 -12
- package/src/custom-type-add-field-geo-point.ts +46 -12
- package/src/custom-type-add-field-group.ts +179 -0
- package/src/custom-type-add-field-image.ts +46 -12
- package/src/custom-type-add-field-key-text.ts +46 -12
- package/src/custom-type-add-field-link.ts +46 -12
- package/src/custom-type-add-field-number.ts +46 -12
- package/src/custom-type-add-field-rich-text.ts +46 -12
- package/src/custom-type-add-field-select.ts +47 -21
- package/src/custom-type-add-field-timestamp.ts +46 -12
- package/src/custom-type-add-field-uid.ts +17 -0
- package/src/custom-type-add-field.ts +5 -0
- package/src/index.ts +5 -0
- package/src/lib/field-path.ts +81 -0
- package/src/page-type-add-field-boolean.ts +66 -13
- package/src/page-type-add-field-color.ts +66 -13
- package/src/page-type-add-field-date.ts +66 -13
- package/src/page-type-add-field-embed.ts +66 -13
- package/src/page-type-add-field-geo-point.ts +66 -13
- package/src/page-type-add-field-group.ts +198 -0
- package/src/page-type-add-field-image.ts +66 -13
- package/src/page-type-add-field-key-text.ts +66 -13
- package/src/page-type-add-field-link.ts +66 -13
- package/src/page-type-add-field-number.ts +66 -13
- package/src/page-type-add-field-rich-text.ts +66 -13
- package/src/page-type-add-field-select.ts +67 -22
- package/src/page-type-add-field-timestamp.ts +66 -13
- package/src/page-type-add-field-uid.ts +37 -1
- package/src/page-type-add-field.ts +5 -0
- package/src/page-type-create.ts +25 -0
- package/src/repo-create.ts +59 -0
- package/src/skill-install.ts +177 -0
- package/src/skill-uninstall.ts +85 -0
- package/src/skill.ts +50 -0
- package/src/slice-add-field-boolean.ts +90 -16
- package/src/slice-add-field-color.ts +90 -16
- package/src/slice-add-field-date.ts +90 -16
- package/src/slice-add-field-embed.ts +90 -16
- package/src/slice-add-field-geo-point.ts +90 -16
- package/src/slice-add-field-group.ts +191 -0
- package/src/slice-add-field-image.ts +90 -16
- package/src/slice-add-field-key-text.ts +90 -16
- package/src/slice-add-field-link.ts +90 -16
- package/src/slice-add-field-number.ts +90 -16
- package/src/slice-add-field-rich-text.ts +90 -16
- package/src/slice-add-field-select.ts +91 -25
- package/src/slice-add-field-timestamp.ts +90 -16
- package/src/slice-add-field.ts +5 -0
- package/src/slice-create.ts +66 -5
- package/src/slice-set-screenshot.ts +235 -0
- package/src/slice-view.ts +3 -0
- package/src/slice.ts +5 -0
- package/src/status.ts +164 -124
|
@@ -6,6 +6,8 @@ import * as v from "valibot";
|
|
|
6
6
|
|
|
7
7
|
import { buildTypes } from "./codegen-types";
|
|
8
8
|
import { findUpward } from "./lib/file";
|
|
9
|
+
import { findGroupInTab, isGroupField, parseFieldPath, validateNestedFieldPath } from "./lib/field-path";
|
|
10
|
+
import { type Framework, detectFrameworkInfo } from "./lib/framework";
|
|
9
11
|
import { stringify } from "./lib/json";
|
|
10
12
|
import { humanReadable } from "./lib/string";
|
|
11
13
|
|
|
@@ -44,6 +46,17 @@ const CustomTypeSchema = v.object({
|
|
|
44
46
|
json: v.record(v.string(), v.record(v.string(), v.unknown())),
|
|
45
47
|
});
|
|
46
48
|
|
|
49
|
+
function getDocsPath(framework: Framework): string {
|
|
50
|
+
switch (framework) {
|
|
51
|
+
case "next":
|
|
52
|
+
return "nextjs/with-cli";
|
|
53
|
+
case "nuxt":
|
|
54
|
+
return "nuxt/with-cli";
|
|
55
|
+
case "sveltekit":
|
|
56
|
+
return "sveltekit/with-cli";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
47
60
|
export async function pageTypeAddFieldNumber(): Promise<void> {
|
|
48
61
|
const {
|
|
49
62
|
values: { help, tab, label, placeholder, min, max, step, types },
|
|
@@ -82,6 +95,15 @@ export async function pageTypeAddFieldNumber(): Promise<void> {
|
|
|
82
95
|
return;
|
|
83
96
|
}
|
|
84
97
|
|
|
98
|
+
// Parse and validate field path
|
|
99
|
+
const fieldPath = parseFieldPath(fieldId);
|
|
100
|
+
const pathValidation = validateNestedFieldPath(fieldPath);
|
|
101
|
+
if (!pathValidation.ok) {
|
|
102
|
+
console.error(pathValidation.error);
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
85
107
|
// Parse numeric values
|
|
86
108
|
const minValue = min !== undefined ? Number(min) : undefined;
|
|
87
109
|
const maxValue = max !== undefined ? Number(max) : undefined;
|
|
@@ -151,20 +173,11 @@ export async function pageTypeAddFieldNumber(): Promise<void> {
|
|
|
151
173
|
model.json[targetTab] = {};
|
|
152
174
|
}
|
|
153
175
|
|
|
154
|
-
// Check if field already exists in any tab
|
|
155
|
-
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
156
|
-
if (tabFields[fieldId]) {
|
|
157
|
-
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
158
|
-
process.exitCode = 1;
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
176
|
// Build field definition
|
|
164
177
|
const fieldDefinition: NumberField = {
|
|
165
178
|
type: "Number",
|
|
166
179
|
config: {
|
|
167
|
-
label: label ?? humanReadable(fieldId),
|
|
180
|
+
label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
|
|
168
181
|
...(placeholder && { placeholder }),
|
|
169
182
|
...(minValue !== undefined && { min: minValue }),
|
|
170
183
|
...(maxValue !== undefined && { max: maxValue }),
|
|
@@ -173,7 +186,36 @@ export async function pageTypeAddFieldNumber(): Promise<void> {
|
|
|
173
186
|
};
|
|
174
187
|
|
|
175
188
|
// Add field to model
|
|
176
|
-
|
|
189
|
+
if (fieldPath.type === "nested") {
|
|
190
|
+
const groupResult = findGroupInTab(model.json[targetTab], fieldPath.groupId, targetTab);
|
|
191
|
+
if (!groupResult.ok) {
|
|
192
|
+
console.error(groupResult.error);
|
|
193
|
+
process.exitCode = 1;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (groupResult.group.config.fields[fieldPath.nestedFieldId]) {
|
|
197
|
+
console.error(`Field "${fieldPath.nestedFieldId}" already exists in group "${fieldPath.groupId}"`);
|
|
198
|
+
process.exitCode = 1;
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
groupResult.group.config.fields[fieldPath.nestedFieldId] = fieldDefinition;
|
|
202
|
+
} else {
|
|
203
|
+
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
204
|
+
if (tabFields[fieldId]) {
|
|
205
|
+
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
206
|
+
process.exitCode = 1;
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
for (const [groupFieldId, groupField] of Object.entries(tabFields)) {
|
|
210
|
+
if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
|
|
211
|
+
console.error(`Field "${fieldId}" already exists in group "${groupFieldId}" in tab "${tabName}"`);
|
|
212
|
+
process.exitCode = 1;
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
model.json[targetTab][fieldId] = fieldDefinition;
|
|
218
|
+
}
|
|
177
219
|
|
|
178
220
|
// Write updated model
|
|
179
221
|
try {
|
|
@@ -188,7 +230,11 @@ export async function pageTypeAddFieldNumber(): Promise<void> {
|
|
|
188
230
|
return;
|
|
189
231
|
}
|
|
190
232
|
|
|
191
|
-
|
|
233
|
+
if (fieldPath.type === "nested") {
|
|
234
|
+
console.info(`Added field "${fieldPath.nestedFieldId}" (Number) to group "${fieldPath.groupId}" in ${typeId}`);
|
|
235
|
+
} else {
|
|
236
|
+
console.info(`Added field "${fieldId}" (Number) to "${targetTab}" tab in ${typeId}`);
|
|
237
|
+
}
|
|
192
238
|
|
|
193
239
|
try {
|
|
194
240
|
await buildTypes({ output: types });
|
|
@@ -199,5 +245,12 @@ export async function pageTypeAddFieldNumber(): Promise<void> {
|
|
|
199
245
|
|
|
200
246
|
console.info();
|
|
201
247
|
console.info("Next: Add more fields with `prismic page-type add-field`");
|
|
202
|
-
|
|
248
|
+
|
|
249
|
+
const frameworkInfo = await detectFrameworkInfo();
|
|
250
|
+
if (frameworkInfo?.framework) {
|
|
251
|
+
const docsPath = getDocsPath(frameworkInfo.framework);
|
|
252
|
+
console.info(
|
|
253
|
+
` Run \`prismic docs ${docsPath}#write-page-components\` to learn how to implement a page file`,
|
|
254
|
+
);
|
|
255
|
+
}
|
|
203
256
|
}
|
|
@@ -6,6 +6,8 @@ import * as v from "valibot";
|
|
|
6
6
|
|
|
7
7
|
import { buildTypes } from "./codegen-types";
|
|
8
8
|
import { findUpward } from "./lib/file";
|
|
9
|
+
import { findGroupInTab, isGroupField, parseFieldPath, validateNestedFieldPath } from "./lib/field-path";
|
|
10
|
+
import { type Framework, detectFrameworkInfo } from "./lib/framework";
|
|
9
11
|
import { stringify } from "./lib/json";
|
|
10
12
|
import { humanReadable } from "./lib/string";
|
|
11
13
|
|
|
@@ -50,6 +52,17 @@ const CustomTypeSchema = v.object({
|
|
|
50
52
|
json: v.record(v.string(), v.record(v.string(), v.unknown())),
|
|
51
53
|
});
|
|
52
54
|
|
|
55
|
+
function getDocsPath(framework: Framework): string {
|
|
56
|
+
switch (framework) {
|
|
57
|
+
case "next":
|
|
58
|
+
return "nextjs/with-cli";
|
|
59
|
+
case "nuxt":
|
|
60
|
+
return "nuxt/with-cli";
|
|
61
|
+
case "sveltekit":
|
|
62
|
+
return "sveltekit/with-cli";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
53
66
|
export async function pageTypeAddFieldRichText(): Promise<void> {
|
|
54
67
|
const {
|
|
55
68
|
values: {
|
|
@@ -97,6 +110,15 @@ export async function pageTypeAddFieldRichText(): Promise<void> {
|
|
|
97
110
|
return;
|
|
98
111
|
}
|
|
99
112
|
|
|
113
|
+
// Parse and validate field path
|
|
114
|
+
const fieldPath = parseFieldPath(fieldId);
|
|
115
|
+
const pathValidation = validateNestedFieldPath(fieldPath);
|
|
116
|
+
if (!pathValidation.ok) {
|
|
117
|
+
console.error(pathValidation.error);
|
|
118
|
+
process.exitCode = 1;
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
100
122
|
// Find the page type file
|
|
101
123
|
const projectRoot = await findUpward("package.json");
|
|
102
124
|
if (!projectRoot) {
|
|
@@ -143,20 +165,11 @@ export async function pageTypeAddFieldRichText(): Promise<void> {
|
|
|
143
165
|
model.json[targetTab] = {};
|
|
144
166
|
}
|
|
145
167
|
|
|
146
|
-
// Check if field already exists in any tab
|
|
147
|
-
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
148
|
-
if (tabFields[fieldId]) {
|
|
149
|
-
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
150
|
-
process.exitCode = 1;
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
168
|
// Build field definition
|
|
156
169
|
const fieldDefinition: RichText = {
|
|
157
170
|
type: "StructuredText",
|
|
158
171
|
config: {
|
|
159
|
-
label: label ?? humanReadable(fieldId),
|
|
172
|
+
label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
|
|
160
173
|
...(placeholder && { placeholder }),
|
|
161
174
|
...(single && { single }),
|
|
162
175
|
...(multi && { multi }),
|
|
@@ -165,7 +178,36 @@ export async function pageTypeAddFieldRichText(): Promise<void> {
|
|
|
165
178
|
};
|
|
166
179
|
|
|
167
180
|
// Add field to model
|
|
168
|
-
|
|
181
|
+
if (fieldPath.type === "nested") {
|
|
182
|
+
const groupResult = findGroupInTab(model.json[targetTab], fieldPath.groupId, targetTab);
|
|
183
|
+
if (!groupResult.ok) {
|
|
184
|
+
console.error(groupResult.error);
|
|
185
|
+
process.exitCode = 1;
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (groupResult.group.config.fields[fieldPath.nestedFieldId]) {
|
|
189
|
+
console.error(`Field "${fieldPath.nestedFieldId}" already exists in group "${fieldPath.groupId}"`);
|
|
190
|
+
process.exitCode = 1;
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
groupResult.group.config.fields[fieldPath.nestedFieldId] = fieldDefinition;
|
|
194
|
+
} else {
|
|
195
|
+
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
196
|
+
if (tabFields[fieldId]) {
|
|
197
|
+
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
198
|
+
process.exitCode = 1;
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
for (const [groupFieldId, groupField] of Object.entries(tabFields)) {
|
|
202
|
+
if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
|
|
203
|
+
console.error(`Field "${fieldId}" already exists in group "${groupFieldId}" in tab "${tabName}"`);
|
|
204
|
+
process.exitCode = 1;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
model.json[targetTab][fieldId] = fieldDefinition;
|
|
210
|
+
}
|
|
169
211
|
|
|
170
212
|
// Write updated model
|
|
171
213
|
try {
|
|
@@ -180,7 +222,11 @@ export async function pageTypeAddFieldRichText(): Promise<void> {
|
|
|
180
222
|
return;
|
|
181
223
|
}
|
|
182
224
|
|
|
183
|
-
|
|
225
|
+
if (fieldPath.type === "nested") {
|
|
226
|
+
console.info(`Added field "${fieldPath.nestedFieldId}" (StructuredText) to group "${fieldPath.groupId}" in ${typeId}`);
|
|
227
|
+
} else {
|
|
228
|
+
console.info(`Added field "${fieldId}" (StructuredText) to "${targetTab}" tab in ${typeId}`);
|
|
229
|
+
}
|
|
184
230
|
|
|
185
231
|
try {
|
|
186
232
|
await buildTypes({ output: types });
|
|
@@ -191,5 +237,12 @@ export async function pageTypeAddFieldRichText(): Promise<void> {
|
|
|
191
237
|
|
|
192
238
|
console.info();
|
|
193
239
|
console.info("Next: Add more fields with `prismic page-type add-field`");
|
|
194
|
-
|
|
240
|
+
|
|
241
|
+
const frameworkInfo = await detectFrameworkInfo();
|
|
242
|
+
if (frameworkInfo?.framework) {
|
|
243
|
+
const docsPath = getDocsPath(frameworkInfo.framework);
|
|
244
|
+
console.info(
|
|
245
|
+
` Run \`prismic docs ${docsPath}#write-page-components\` to learn how to implement a page file`,
|
|
246
|
+
);
|
|
247
|
+
}
|
|
195
248
|
}
|
|
@@ -6,6 +6,8 @@ import * as v from "valibot";
|
|
|
6
6
|
|
|
7
7
|
import { buildTypes } from "./codegen-types";
|
|
8
8
|
import { findUpward } from "./lib/file";
|
|
9
|
+
import { findGroupInTab, isGroupField, parseFieldPath, validateNestedFieldPath } from "./lib/field-path";
|
|
10
|
+
import { type Framework, detectFrameworkInfo } from "./lib/framework";
|
|
9
11
|
import { stringify } from "./lib/json";
|
|
10
12
|
import { humanReadable } from "./lib/string";
|
|
11
13
|
|
|
@@ -43,17 +45,20 @@ const CustomTypeSchema = v.object({
|
|
|
43
45
|
json: v.record(v.string(), v.record(v.string(), v.unknown())),
|
|
44
46
|
});
|
|
45
47
|
|
|
48
|
+
function getDocsPath(framework: Framework): string {
|
|
49
|
+
switch (framework) {
|
|
50
|
+
case "next":
|
|
51
|
+
return "nextjs/with-cli";
|
|
52
|
+
case "nuxt":
|
|
53
|
+
return "nuxt/with-cli";
|
|
54
|
+
case "sveltekit":
|
|
55
|
+
return "sveltekit/with-cli";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
46
59
|
export async function pageTypeAddFieldSelect(): Promise<void> {
|
|
47
60
|
const {
|
|
48
|
-
values: {
|
|
49
|
-
help,
|
|
50
|
-
tab,
|
|
51
|
-
label,
|
|
52
|
-
placeholder,
|
|
53
|
-
option,
|
|
54
|
-
default: defaultValue,
|
|
55
|
-
types,
|
|
56
|
-
},
|
|
61
|
+
values: { help, tab, label, placeholder, option, default: defaultValue, types },
|
|
57
62
|
positionals: [typeId, fieldId],
|
|
58
63
|
} = parseArgs({
|
|
59
64
|
args: process.argv.slice(5), // skip: node, script, "page-type", "add-field", "select"
|
|
@@ -88,6 +93,15 @@ export async function pageTypeAddFieldSelect(): Promise<void> {
|
|
|
88
93
|
return;
|
|
89
94
|
}
|
|
90
95
|
|
|
96
|
+
// Parse and validate field path
|
|
97
|
+
const fieldPath = parseFieldPath(fieldId);
|
|
98
|
+
const pathValidation = validateNestedFieldPath(fieldPath);
|
|
99
|
+
if (!pathValidation.ok) {
|
|
100
|
+
console.error(pathValidation.error);
|
|
101
|
+
process.exitCode = 1;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
91
105
|
// Find the page type file
|
|
92
106
|
const projectRoot = await findUpward("package.json");
|
|
93
107
|
if (!projectRoot) {
|
|
@@ -134,20 +148,11 @@ export async function pageTypeAddFieldSelect(): Promise<void> {
|
|
|
134
148
|
model.json[targetTab] = {};
|
|
135
149
|
}
|
|
136
150
|
|
|
137
|
-
// Check if field already exists in any tab
|
|
138
|
-
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
139
|
-
if (tabFields[fieldId]) {
|
|
140
|
-
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
141
|
-
process.exitCode = 1;
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
151
|
// Build field definition
|
|
147
152
|
const fieldDefinition: Select = {
|
|
148
153
|
type: "Select",
|
|
149
154
|
config: {
|
|
150
|
-
label: label ?? humanReadable(fieldId),
|
|
155
|
+
label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
|
|
151
156
|
...(placeholder && { placeholder }),
|
|
152
157
|
...(option && option.length > 0 && { options: option }),
|
|
153
158
|
...(defaultValue && { default_value: defaultValue }),
|
|
@@ -155,7 +160,36 @@ export async function pageTypeAddFieldSelect(): Promise<void> {
|
|
|
155
160
|
};
|
|
156
161
|
|
|
157
162
|
// Add field to model
|
|
158
|
-
|
|
163
|
+
if (fieldPath.type === "nested") {
|
|
164
|
+
const groupResult = findGroupInTab(model.json[targetTab], fieldPath.groupId, targetTab);
|
|
165
|
+
if (!groupResult.ok) {
|
|
166
|
+
console.error(groupResult.error);
|
|
167
|
+
process.exitCode = 1;
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (groupResult.group.config.fields[fieldPath.nestedFieldId]) {
|
|
171
|
+
console.error(`Field "${fieldPath.nestedFieldId}" already exists in group "${fieldPath.groupId}"`);
|
|
172
|
+
process.exitCode = 1;
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
groupResult.group.config.fields[fieldPath.nestedFieldId] = fieldDefinition;
|
|
176
|
+
} else {
|
|
177
|
+
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
178
|
+
if (tabFields[fieldId]) {
|
|
179
|
+
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
180
|
+
process.exitCode = 1;
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
for (const [groupFieldId, groupField] of Object.entries(tabFields)) {
|
|
184
|
+
if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
|
|
185
|
+
console.error(`Field "${fieldId}" already exists in group "${groupFieldId}" in tab "${tabName}"`);
|
|
186
|
+
process.exitCode = 1;
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
model.json[targetTab][fieldId] = fieldDefinition;
|
|
192
|
+
}
|
|
159
193
|
|
|
160
194
|
// Write updated model
|
|
161
195
|
try {
|
|
@@ -170,7 +204,11 @@ export async function pageTypeAddFieldSelect(): Promise<void> {
|
|
|
170
204
|
return;
|
|
171
205
|
}
|
|
172
206
|
|
|
173
|
-
|
|
207
|
+
if (fieldPath.type === "nested") {
|
|
208
|
+
console.info(`Added field "${fieldPath.nestedFieldId}" (Select) to group "${fieldPath.groupId}" in ${typeId}`);
|
|
209
|
+
} else {
|
|
210
|
+
console.info(`Added field "${fieldId}" (Select) to "${targetTab}" tab in ${typeId}`);
|
|
211
|
+
}
|
|
174
212
|
|
|
175
213
|
try {
|
|
176
214
|
await buildTypes({ output: types });
|
|
@@ -181,5 +219,12 @@ export async function pageTypeAddFieldSelect(): Promise<void> {
|
|
|
181
219
|
|
|
182
220
|
console.info();
|
|
183
221
|
console.info("Next: Add more fields with `prismic page-type add-field`");
|
|
184
|
-
|
|
222
|
+
|
|
223
|
+
const frameworkInfo = await detectFrameworkInfo();
|
|
224
|
+
if (frameworkInfo?.framework) {
|
|
225
|
+
const docsPath = getDocsPath(frameworkInfo.framework);
|
|
226
|
+
console.info(
|
|
227
|
+
` Run \`prismic docs ${docsPath}#write-page-components\` to learn how to implement a page file`,
|
|
228
|
+
);
|
|
229
|
+
}
|
|
185
230
|
}
|
|
@@ -6,6 +6,8 @@ import * as v from "valibot";
|
|
|
6
6
|
|
|
7
7
|
import { buildTypes } from "./codegen-types";
|
|
8
8
|
import { findUpward } from "./lib/file";
|
|
9
|
+
import { findGroupInTab, isGroupField, parseFieldPath, validateNestedFieldPath } from "./lib/field-path";
|
|
10
|
+
import { type Framework, detectFrameworkInfo } from "./lib/framework";
|
|
9
11
|
import { stringify } from "./lib/json";
|
|
10
12
|
import { humanReadable } from "./lib/string";
|
|
11
13
|
|
|
@@ -42,6 +44,17 @@ const CustomTypeSchema = v.object({
|
|
|
42
44
|
json: v.record(v.string(), v.record(v.string(), v.unknown())),
|
|
43
45
|
});
|
|
44
46
|
|
|
47
|
+
function getDocsPath(framework: Framework): string {
|
|
48
|
+
switch (framework) {
|
|
49
|
+
case "next":
|
|
50
|
+
return "nextjs/with-cli";
|
|
51
|
+
case "nuxt":
|
|
52
|
+
return "nuxt/with-cli";
|
|
53
|
+
case "sveltekit":
|
|
54
|
+
return "sveltekit/with-cli";
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
45
58
|
export async function pageTypeAddFieldTimestamp(): Promise<void> {
|
|
46
59
|
const {
|
|
47
60
|
values: { help, tab, label, placeholder, default: defaultValue, types },
|
|
@@ -78,6 +91,15 @@ export async function pageTypeAddFieldTimestamp(): Promise<void> {
|
|
|
78
91
|
return;
|
|
79
92
|
}
|
|
80
93
|
|
|
94
|
+
// Parse and validate field path
|
|
95
|
+
const fieldPath = parseFieldPath(fieldId);
|
|
96
|
+
const pathValidation = validateNestedFieldPath(fieldPath);
|
|
97
|
+
if (!pathValidation.ok) {
|
|
98
|
+
console.error(pathValidation.error);
|
|
99
|
+
process.exitCode = 1;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
81
103
|
// Find the page type file
|
|
82
104
|
const projectRoot = await findUpward("package.json");
|
|
83
105
|
if (!projectRoot) {
|
|
@@ -124,27 +146,47 @@ export async function pageTypeAddFieldTimestamp(): Promise<void> {
|
|
|
124
146
|
model.json[targetTab] = {};
|
|
125
147
|
}
|
|
126
148
|
|
|
127
|
-
// Check if field already exists in any tab
|
|
128
|
-
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
129
|
-
if (tabFields[fieldId]) {
|
|
130
|
-
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
131
|
-
process.exitCode = 1;
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
149
|
// Build field definition
|
|
137
150
|
const fieldDefinition: Timestamp = {
|
|
138
151
|
type: "Timestamp",
|
|
139
152
|
config: {
|
|
140
|
-
label: label ?? humanReadable(fieldId),
|
|
153
|
+
label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
|
|
141
154
|
...(placeholder && { placeholder }),
|
|
142
155
|
...(defaultValue && { default: defaultValue }),
|
|
143
156
|
},
|
|
144
157
|
};
|
|
145
158
|
|
|
146
159
|
// Add field to model
|
|
147
|
-
|
|
160
|
+
if (fieldPath.type === "nested") {
|
|
161
|
+
const groupResult = findGroupInTab(model.json[targetTab], fieldPath.groupId, targetTab);
|
|
162
|
+
if (!groupResult.ok) {
|
|
163
|
+
console.error(groupResult.error);
|
|
164
|
+
process.exitCode = 1;
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (groupResult.group.config.fields[fieldPath.nestedFieldId]) {
|
|
168
|
+
console.error(`Field "${fieldPath.nestedFieldId}" already exists in group "${fieldPath.groupId}"`);
|
|
169
|
+
process.exitCode = 1;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
groupResult.group.config.fields[fieldPath.nestedFieldId] = fieldDefinition;
|
|
173
|
+
} else {
|
|
174
|
+
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
175
|
+
if (tabFields[fieldId]) {
|
|
176
|
+
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
177
|
+
process.exitCode = 1;
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
for (const [groupFieldId, groupField] of Object.entries(tabFields)) {
|
|
181
|
+
if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
|
|
182
|
+
console.error(`Field "${fieldId}" already exists in group "${groupFieldId}" in tab "${tabName}"`);
|
|
183
|
+
process.exitCode = 1;
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
model.json[targetTab][fieldId] = fieldDefinition;
|
|
189
|
+
}
|
|
148
190
|
|
|
149
191
|
// Write updated model
|
|
150
192
|
try {
|
|
@@ -159,7 +201,11 @@ export async function pageTypeAddFieldTimestamp(): Promise<void> {
|
|
|
159
201
|
return;
|
|
160
202
|
}
|
|
161
203
|
|
|
162
|
-
|
|
204
|
+
if (fieldPath.type === "nested") {
|
|
205
|
+
console.info(`Added field "${fieldPath.nestedFieldId}" (Timestamp) to group "${fieldPath.groupId}" in ${typeId}`);
|
|
206
|
+
} else {
|
|
207
|
+
console.info(`Added field "${fieldId}" (Timestamp) to "${targetTab}" tab in ${typeId}`);
|
|
208
|
+
}
|
|
163
209
|
|
|
164
210
|
try {
|
|
165
211
|
await buildTypes({ output: types });
|
|
@@ -170,5 +216,12 @@ export async function pageTypeAddFieldTimestamp(): Promise<void> {
|
|
|
170
216
|
|
|
171
217
|
console.info();
|
|
172
218
|
console.info("Next: Add more fields with `prismic page-type add-field`");
|
|
173
|
-
|
|
219
|
+
|
|
220
|
+
const frameworkInfo = await detectFrameworkInfo();
|
|
221
|
+
if (frameworkInfo?.framework) {
|
|
222
|
+
const docsPath = getDocsPath(frameworkInfo.framework);
|
|
223
|
+
console.info(
|
|
224
|
+
` Run \`prismic docs ${docsPath}#write-page-components\` to learn how to implement a page file`,
|
|
225
|
+
);
|
|
226
|
+
}
|
|
174
227
|
}
|
|
@@ -6,6 +6,8 @@ import * as v from "valibot";
|
|
|
6
6
|
|
|
7
7
|
import { buildTypes } from "./codegen-types";
|
|
8
8
|
import { findUpward } from "./lib/file";
|
|
9
|
+
import { parseFieldPath, validateNestedFieldPath } from "./lib/field-path";
|
|
10
|
+
import { type Framework, detectFrameworkInfo } from "./lib/framework";
|
|
9
11
|
import { stringify } from "./lib/json";
|
|
10
12
|
import { humanReadable } from "./lib/string";
|
|
11
13
|
|
|
@@ -41,6 +43,17 @@ const CustomTypeSchema = v.object({
|
|
|
41
43
|
json: v.record(v.string(), v.record(v.string(), v.unknown())),
|
|
42
44
|
});
|
|
43
45
|
|
|
46
|
+
function getDocsPath(framework: Framework): string {
|
|
47
|
+
switch (framework) {
|
|
48
|
+
case "next":
|
|
49
|
+
return "nextjs/with-cli";
|
|
50
|
+
case "nuxt":
|
|
51
|
+
return "nuxt/with-cli";
|
|
52
|
+
case "sveltekit":
|
|
53
|
+
return "sveltekit/with-cli";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
44
57
|
export async function pageTypeAddFieldUid(): Promise<void> {
|
|
45
58
|
const {
|
|
46
59
|
values: { help, tab, label, placeholder, types },
|
|
@@ -76,6 +89,22 @@ export async function pageTypeAddFieldUid(): Promise<void> {
|
|
|
76
89
|
return;
|
|
77
90
|
}
|
|
78
91
|
|
|
92
|
+
// Parse and validate field path
|
|
93
|
+
const fieldPath = parseFieldPath(fieldId);
|
|
94
|
+
const pathValidation = validateNestedFieldPath(fieldPath);
|
|
95
|
+
if (!pathValidation.ok) {
|
|
96
|
+
console.error(pathValidation.error);
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// UID fields cannot be nested in groups
|
|
102
|
+
if (fieldPath.type === "nested") {
|
|
103
|
+
console.error("UID fields cannot be nested inside groups");
|
|
104
|
+
process.exitCode = 1;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
79
108
|
// Find the page type file
|
|
80
109
|
const projectRoot = await findUpward("package.json");
|
|
81
110
|
if (!projectRoot) {
|
|
@@ -167,5 +196,12 @@ export async function pageTypeAddFieldUid(): Promise<void> {
|
|
|
167
196
|
|
|
168
197
|
console.info();
|
|
169
198
|
console.info("Next: Add more fields with `prismic page-type add-field`");
|
|
170
|
-
|
|
199
|
+
|
|
200
|
+
const frameworkInfo = await detectFrameworkInfo();
|
|
201
|
+
if (frameworkInfo?.framework) {
|
|
202
|
+
const docsPath = getDocsPath(frameworkInfo.framework);
|
|
203
|
+
console.info(
|
|
204
|
+
` Run \`prismic docs ${docsPath}#write-page-components\` to learn how to implement a page file`,
|
|
205
|
+
);
|
|
206
|
+
}
|
|
171
207
|
}
|
|
@@ -5,6 +5,7 @@ import { pageTypeAddFieldColor } from "./page-type-add-field-color";
|
|
|
5
5
|
import { pageTypeAddFieldDate } from "./page-type-add-field-date";
|
|
6
6
|
import { pageTypeAddFieldEmbed } from "./page-type-add-field-embed";
|
|
7
7
|
import { pageTypeAddFieldGeoPoint } from "./page-type-add-field-geo-point";
|
|
8
|
+
import { pageTypeAddFieldGroup } from "./page-type-add-field-group";
|
|
8
9
|
import { pageTypeAddFieldImage } from "./page-type-add-field-image";
|
|
9
10
|
import { pageTypeAddFieldKeyText } from "./page-type-add-field-key-text";
|
|
10
11
|
import { pageTypeAddFieldLink } from "./page-type-add-field-link";
|
|
@@ -26,6 +27,7 @@ FIELD TYPES
|
|
|
26
27
|
date Date picker
|
|
27
28
|
embed Embed (oEmbed)
|
|
28
29
|
geo-point Geographic coordinates
|
|
30
|
+
group Repeatable group of fields
|
|
29
31
|
image Image
|
|
30
32
|
key-text Single-line text
|
|
31
33
|
link Any link type
|
|
@@ -76,6 +78,9 @@ export async function pageTypeAddField(): Promise<void> {
|
|
|
76
78
|
case "geo-point":
|
|
77
79
|
await pageTypeAddFieldGeoPoint();
|
|
78
80
|
break;
|
|
81
|
+
case "group":
|
|
82
|
+
await pageTypeAddFieldGroup();
|
|
83
|
+
break;
|
|
79
84
|
case "image":
|
|
80
85
|
await pageTypeAddFieldImage();
|
|
81
86
|
break;
|
package/src/page-type-create.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { parseArgs } from "node:util";
|
|
|
5
5
|
|
|
6
6
|
import { buildTypes } from "./codegen-types";
|
|
7
7
|
import { findUpward } from "./lib/file";
|
|
8
|
+
import { type Framework, detectFrameworkInfo } from "./lib/framework";
|
|
8
9
|
import { stringify } from "./lib/json";
|
|
9
10
|
|
|
10
11
|
const HELP = `
|
|
@@ -26,6 +27,21 @@ LEARN MORE
|
|
|
26
27
|
Use \`prismic page-type <command> --help\` for more information about a command.
|
|
27
28
|
`.trim();
|
|
28
29
|
|
|
30
|
+
function getDocsPath(framework: Framework): string {
|
|
31
|
+
switch (framework) {
|
|
32
|
+
case "next":
|
|
33
|
+
return "nextjs/with-cli";
|
|
34
|
+
case "nuxt":
|
|
35
|
+
return "nuxt/with-cli";
|
|
36
|
+
case "sveltekit":
|
|
37
|
+
return "sveltekit/with-cli";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getWritePageComponentsAnchor(_framework: Framework): string {
|
|
42
|
+
return "#write-page-components";
|
|
43
|
+
}
|
|
44
|
+
|
|
29
45
|
export async function pageTypeCreate(): Promise<void> {
|
|
30
46
|
const {
|
|
31
47
|
values: { help, name, single, types },
|
|
@@ -129,6 +145,15 @@ export async function pageTypeCreate(): Promise<void> {
|
|
|
129
145
|
|
|
130
146
|
console.info();
|
|
131
147
|
console.info("Next: Add fields with `prismic page-type add-field`");
|
|
148
|
+
|
|
149
|
+
const frameworkInfo = await detectFrameworkInfo();
|
|
150
|
+
if (frameworkInfo?.framework) {
|
|
151
|
+
const docsPath = getDocsPath(frameworkInfo.framework);
|
|
152
|
+
const anchor = getWritePageComponentsAnchor(frameworkInfo.framework);
|
|
153
|
+
console.info(
|
|
154
|
+
` Run \`prismic docs ${docsPath}${anchor}\` to learn how to implement a page file`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
132
157
|
}
|
|
133
158
|
|
|
134
159
|
export function pascalCase(input: string): string {
|