@angeloashmore/prismic-cli-poc 0.0.0-pr.8.d3fbd0b → 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
package/package.json
CHANGED
|
@@ -6,6 +6,7 @@ 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";
|
|
9
10
|
import { stringify } from "./lib/json";
|
|
10
11
|
import { humanReadable } from "./lib/string";
|
|
11
12
|
|
|
@@ -88,6 +89,15 @@ export async function customTypeAddFieldBoolean(): Promise<void> {
|
|
|
88
89
|
return;
|
|
89
90
|
}
|
|
90
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
|
+
|
|
91
101
|
// Find the custom type file
|
|
92
102
|
const projectRoot = await findUpward("package.json");
|
|
93
103
|
if (!projectRoot) {
|
|
@@ -134,20 +144,11 @@ export async function customTypeAddFieldBoolean(): Promise<void> {
|
|
|
134
144
|
model.json[targetTab] = {};
|
|
135
145
|
}
|
|
136
146
|
|
|
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
147
|
// Build field definition
|
|
147
148
|
const fieldDefinition: BooleanField = {
|
|
148
149
|
type: "Boolean",
|
|
149
150
|
config: {
|
|
150
|
-
label: label ?? humanReadable(fieldId),
|
|
151
|
+
label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
|
|
151
152
|
...(defaultValue && { default_value: true }),
|
|
152
153
|
...(trueLabel && { placeholder_true: trueLabel }),
|
|
153
154
|
...(falseLabel && { placeholder_false: falseLabel }),
|
|
@@ -155,7 +156,39 @@ export async function customTypeAddFieldBoolean(): Promise<void> {
|
|
|
155
156
|
};
|
|
156
157
|
|
|
157
158
|
// Add field to model
|
|
158
|
-
|
|
159
|
+
if (fieldPath.type === "nested") {
|
|
160
|
+
const groupResult = findGroupInTab(model.json[targetTab], fieldPath.groupId, targetTab);
|
|
161
|
+
if (!groupResult.ok) {
|
|
162
|
+
console.error(groupResult.error);
|
|
163
|
+
process.exitCode = 1;
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Check if field already exists in the group
|
|
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
|
+
// Check if field already exists in any tab
|
|
175
|
+
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
176
|
+
if (tabFields[fieldId]) {
|
|
177
|
+
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
178
|
+
process.exitCode = 1;
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// Also check inside groups
|
|
182
|
+
for (const [groupFieldId, groupField] of Object.entries(tabFields)) {
|
|
183
|
+
if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
|
|
184
|
+
console.error(`Field "${fieldId}" already exists in group "${groupFieldId}" in tab "${tabName}"`);
|
|
185
|
+
process.exitCode = 1;
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
model.json[targetTab][fieldId] = fieldDefinition;
|
|
191
|
+
}
|
|
159
192
|
|
|
160
193
|
// Write updated model
|
|
161
194
|
try {
|
|
@@ -170,7 +203,11 @@ export async function customTypeAddFieldBoolean(): Promise<void> {
|
|
|
170
203
|
return;
|
|
171
204
|
}
|
|
172
205
|
|
|
173
|
-
|
|
206
|
+
if (fieldPath.type === "nested") {
|
|
207
|
+
console.info(`Added field "${fieldPath.nestedFieldId}" (Boolean) to group "${fieldPath.groupId}" in ${typeId}`);
|
|
208
|
+
} else {
|
|
209
|
+
console.info(`Added field "${fieldId}" (Boolean) to "${targetTab}" tab in ${typeId}`);
|
|
210
|
+
}
|
|
174
211
|
|
|
175
212
|
try {
|
|
176
213
|
await buildTypes({ output: types });
|
|
@@ -6,6 +6,7 @@ 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";
|
|
9
10
|
import { stringify } from "./lib/json";
|
|
10
11
|
import { humanReadable } from "./lib/string";
|
|
11
12
|
|
|
@@ -76,6 +77,15 @@ export async function customTypeAddFieldColor(): Promise<void> {
|
|
|
76
77
|
return;
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
// Parse and validate field path
|
|
81
|
+
const fieldPath = parseFieldPath(fieldId);
|
|
82
|
+
const pathValidation = validateNestedFieldPath(fieldPath);
|
|
83
|
+
if (!pathValidation.ok) {
|
|
84
|
+
console.error(pathValidation.error);
|
|
85
|
+
process.exitCode = 1;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
79
89
|
// Find the custom type file
|
|
80
90
|
const projectRoot = await findUpward("package.json");
|
|
81
91
|
if (!projectRoot) {
|
|
@@ -122,26 +132,46 @@ export async function customTypeAddFieldColor(): Promise<void> {
|
|
|
122
132
|
model.json[targetTab] = {};
|
|
123
133
|
}
|
|
124
134
|
|
|
125
|
-
// Check if field already exists in any tab
|
|
126
|
-
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
127
|
-
if (tabFields[fieldId]) {
|
|
128
|
-
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
129
|
-
process.exitCode = 1;
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
135
|
// Build field definition
|
|
135
136
|
const fieldDefinition: Color = {
|
|
136
137
|
type: "Color",
|
|
137
138
|
config: {
|
|
138
|
-
label: label ?? humanReadable(fieldId),
|
|
139
|
+
label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
|
|
139
140
|
...(placeholder && { placeholder }),
|
|
140
141
|
},
|
|
141
142
|
};
|
|
142
143
|
|
|
143
144
|
// Add field to model
|
|
144
|
-
|
|
145
|
+
if (fieldPath.type === "nested") {
|
|
146
|
+
const groupResult = findGroupInTab(model.json[targetTab], fieldPath.groupId, targetTab);
|
|
147
|
+
if (!groupResult.ok) {
|
|
148
|
+
console.error(groupResult.error);
|
|
149
|
+
process.exitCode = 1;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (groupResult.group.config.fields[fieldPath.nestedFieldId]) {
|
|
153
|
+
console.error(`Field "${fieldPath.nestedFieldId}" already exists in group "${fieldPath.groupId}"`);
|
|
154
|
+
process.exitCode = 1;
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
groupResult.group.config.fields[fieldPath.nestedFieldId] = fieldDefinition;
|
|
158
|
+
} else {
|
|
159
|
+
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
160
|
+
if (tabFields[fieldId]) {
|
|
161
|
+
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
162
|
+
process.exitCode = 1;
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
for (const [groupFieldId, groupField] of Object.entries(tabFields)) {
|
|
166
|
+
if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
|
|
167
|
+
console.error(`Field "${fieldId}" already exists in group "${groupFieldId}" in tab "${tabName}"`);
|
|
168
|
+
process.exitCode = 1;
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
model.json[targetTab][fieldId] = fieldDefinition;
|
|
174
|
+
}
|
|
145
175
|
|
|
146
176
|
// Write updated model
|
|
147
177
|
try {
|
|
@@ -156,7 +186,11 @@ export async function customTypeAddFieldColor(): Promise<void> {
|
|
|
156
186
|
return;
|
|
157
187
|
}
|
|
158
188
|
|
|
159
|
-
|
|
189
|
+
if (fieldPath.type === "nested") {
|
|
190
|
+
console.info(`Added field "${fieldPath.nestedFieldId}" (Color) to group "${fieldPath.groupId}" in ${typeId}`);
|
|
191
|
+
} else {
|
|
192
|
+
console.info(`Added field "${fieldId}" (Color) to "${targetTab}" tab in ${typeId}`);
|
|
193
|
+
}
|
|
160
194
|
|
|
161
195
|
try {
|
|
162
196
|
await buildTypes({ output: types });
|
|
@@ -6,6 +6,7 @@ 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";
|
|
9
10
|
import { stringify } from "./lib/json";
|
|
10
11
|
import { humanReadable } from "./lib/string";
|
|
11
12
|
|
|
@@ -78,6 +79,15 @@ export async function customTypeAddFieldDate(): Promise<void> {
|
|
|
78
79
|
return;
|
|
79
80
|
}
|
|
80
81
|
|
|
82
|
+
// Parse and validate field path
|
|
83
|
+
const fieldPath = parseFieldPath(fieldId);
|
|
84
|
+
const pathValidation = validateNestedFieldPath(fieldPath);
|
|
85
|
+
if (!pathValidation.ok) {
|
|
86
|
+
console.error(pathValidation.error);
|
|
87
|
+
process.exitCode = 1;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
81
91
|
// Find the custom type file
|
|
82
92
|
const projectRoot = await findUpward("package.json");
|
|
83
93
|
if (!projectRoot) {
|
|
@@ -124,27 +134,47 @@ export async function customTypeAddFieldDate(): Promise<void> {
|
|
|
124
134
|
model.json[targetTab] = {};
|
|
125
135
|
}
|
|
126
136
|
|
|
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
137
|
// Build field definition
|
|
137
138
|
const fieldDefinition: DateField = {
|
|
138
139
|
type: "Date",
|
|
139
140
|
config: {
|
|
140
|
-
label: label ?? humanReadable(fieldId),
|
|
141
|
+
label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
|
|
141
142
|
...(placeholder && { placeholder }),
|
|
142
143
|
...(defaultValue && { default: defaultValue }),
|
|
143
144
|
},
|
|
144
145
|
};
|
|
145
146
|
|
|
146
147
|
// Add field to model
|
|
147
|
-
|
|
148
|
+
if (fieldPath.type === "nested") {
|
|
149
|
+
const groupResult = findGroupInTab(model.json[targetTab], fieldPath.groupId, targetTab);
|
|
150
|
+
if (!groupResult.ok) {
|
|
151
|
+
console.error(groupResult.error);
|
|
152
|
+
process.exitCode = 1;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (groupResult.group.config.fields[fieldPath.nestedFieldId]) {
|
|
156
|
+
console.error(`Field "${fieldPath.nestedFieldId}" already exists in group "${fieldPath.groupId}"`);
|
|
157
|
+
process.exitCode = 1;
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
groupResult.group.config.fields[fieldPath.nestedFieldId] = fieldDefinition;
|
|
161
|
+
} else {
|
|
162
|
+
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
163
|
+
if (tabFields[fieldId]) {
|
|
164
|
+
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
165
|
+
process.exitCode = 1;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
for (const [groupFieldId, groupField] of Object.entries(tabFields)) {
|
|
169
|
+
if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
|
|
170
|
+
console.error(`Field "${fieldId}" already exists in group "${groupFieldId}" in tab "${tabName}"`);
|
|
171
|
+
process.exitCode = 1;
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
model.json[targetTab][fieldId] = fieldDefinition;
|
|
177
|
+
}
|
|
148
178
|
|
|
149
179
|
// Write updated model
|
|
150
180
|
try {
|
|
@@ -159,7 +189,11 @@ export async function customTypeAddFieldDate(): Promise<void> {
|
|
|
159
189
|
return;
|
|
160
190
|
}
|
|
161
191
|
|
|
162
|
-
|
|
192
|
+
if (fieldPath.type === "nested") {
|
|
193
|
+
console.info(`Added field "${fieldPath.nestedFieldId}" (Date) to group "${fieldPath.groupId}" in ${typeId}`);
|
|
194
|
+
} else {
|
|
195
|
+
console.info(`Added field "${fieldId}" (Date) to "${targetTab}" tab in ${typeId}`);
|
|
196
|
+
}
|
|
163
197
|
|
|
164
198
|
try {
|
|
165
199
|
await buildTypes({ output: types });
|
|
@@ -6,6 +6,7 @@ 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";
|
|
9
10
|
import { stringify } from "./lib/json";
|
|
10
11
|
import { humanReadable } from "./lib/string";
|
|
11
12
|
|
|
@@ -76,6 +77,15 @@ export async function customTypeAddFieldEmbed(): Promise<void> {
|
|
|
76
77
|
return;
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
// Parse and validate field path
|
|
81
|
+
const fieldPath = parseFieldPath(fieldId);
|
|
82
|
+
const pathValidation = validateNestedFieldPath(fieldPath);
|
|
83
|
+
if (!pathValidation.ok) {
|
|
84
|
+
console.error(pathValidation.error);
|
|
85
|
+
process.exitCode = 1;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
79
89
|
// Find the custom type file
|
|
80
90
|
const projectRoot = await findUpward("package.json");
|
|
81
91
|
if (!projectRoot) {
|
|
@@ -122,26 +132,46 @@ export async function customTypeAddFieldEmbed(): Promise<void> {
|
|
|
122
132
|
model.json[targetTab] = {};
|
|
123
133
|
}
|
|
124
134
|
|
|
125
|
-
// Check if field already exists in any tab
|
|
126
|
-
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
127
|
-
if (tabFields[fieldId]) {
|
|
128
|
-
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
129
|
-
process.exitCode = 1;
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
135
|
// Build field definition
|
|
135
136
|
const fieldDefinition: Embed = {
|
|
136
137
|
type: "Embed",
|
|
137
138
|
config: {
|
|
138
|
-
label: label ?? humanReadable(fieldId),
|
|
139
|
+
label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
|
|
139
140
|
...(placeholder && { placeholder }),
|
|
140
141
|
},
|
|
141
142
|
};
|
|
142
143
|
|
|
143
144
|
// Add field to model
|
|
144
|
-
|
|
145
|
+
if (fieldPath.type === "nested") {
|
|
146
|
+
const groupResult = findGroupInTab(model.json[targetTab], fieldPath.groupId, targetTab);
|
|
147
|
+
if (!groupResult.ok) {
|
|
148
|
+
console.error(groupResult.error);
|
|
149
|
+
process.exitCode = 1;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (groupResult.group.config.fields[fieldPath.nestedFieldId]) {
|
|
153
|
+
console.error(`Field "${fieldPath.nestedFieldId}" already exists in group "${fieldPath.groupId}"`);
|
|
154
|
+
process.exitCode = 1;
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
groupResult.group.config.fields[fieldPath.nestedFieldId] = fieldDefinition;
|
|
158
|
+
} else {
|
|
159
|
+
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
160
|
+
if (tabFields[fieldId]) {
|
|
161
|
+
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
162
|
+
process.exitCode = 1;
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
for (const [groupFieldId, groupField] of Object.entries(tabFields)) {
|
|
166
|
+
if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
|
|
167
|
+
console.error(`Field "${fieldId}" already exists in group "${groupFieldId}" in tab "${tabName}"`);
|
|
168
|
+
process.exitCode = 1;
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
model.json[targetTab][fieldId] = fieldDefinition;
|
|
174
|
+
}
|
|
145
175
|
|
|
146
176
|
// Write updated model
|
|
147
177
|
try {
|
|
@@ -156,7 +186,11 @@ export async function customTypeAddFieldEmbed(): Promise<void> {
|
|
|
156
186
|
return;
|
|
157
187
|
}
|
|
158
188
|
|
|
159
|
-
|
|
189
|
+
if (fieldPath.type === "nested") {
|
|
190
|
+
console.info(`Added field "${fieldPath.nestedFieldId}" (Embed) to group "${fieldPath.groupId}" in ${typeId}`);
|
|
191
|
+
} else {
|
|
192
|
+
console.info(`Added field "${fieldId}" (Embed) to "${targetTab}" tab in ${typeId}`);
|
|
193
|
+
}
|
|
160
194
|
|
|
161
195
|
try {
|
|
162
196
|
await buildTypes({ output: types });
|
|
@@ -6,6 +6,7 @@ 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";
|
|
9
10
|
import { stringify } from "./lib/json";
|
|
10
11
|
import { humanReadable } from "./lib/string";
|
|
11
12
|
|
|
@@ -74,6 +75,15 @@ export async function customTypeAddFieldGeoPoint(): Promise<void> {
|
|
|
74
75
|
return;
|
|
75
76
|
}
|
|
76
77
|
|
|
78
|
+
// Parse and validate field path
|
|
79
|
+
const fieldPath = parseFieldPath(fieldId);
|
|
80
|
+
const pathValidation = validateNestedFieldPath(fieldPath);
|
|
81
|
+
if (!pathValidation.ok) {
|
|
82
|
+
console.error(pathValidation.error);
|
|
83
|
+
process.exitCode = 1;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
77
87
|
// Find the custom type file
|
|
78
88
|
const projectRoot = await findUpward("package.json");
|
|
79
89
|
if (!projectRoot) {
|
|
@@ -120,25 +130,45 @@ export async function customTypeAddFieldGeoPoint(): Promise<void> {
|
|
|
120
130
|
model.json[targetTab] = {};
|
|
121
131
|
}
|
|
122
132
|
|
|
123
|
-
// Check if field already exists in any tab
|
|
124
|
-
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
125
|
-
if (tabFields[fieldId]) {
|
|
126
|
-
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
127
|
-
process.exitCode = 1;
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
133
|
// Build field definition
|
|
133
134
|
const fieldDefinition: GeoPoint = {
|
|
134
135
|
type: "GeoPoint",
|
|
135
136
|
config: {
|
|
136
|
-
label: label ?? humanReadable(fieldId),
|
|
137
|
+
label: label ?? humanReadable(fieldPath.type === "nested" ? fieldPath.nestedFieldId : fieldId),
|
|
137
138
|
},
|
|
138
139
|
};
|
|
139
140
|
|
|
140
141
|
// Add field to model
|
|
141
|
-
|
|
142
|
+
if (fieldPath.type === "nested") {
|
|
143
|
+
const groupResult = findGroupInTab(model.json[targetTab], fieldPath.groupId, targetTab);
|
|
144
|
+
if (!groupResult.ok) {
|
|
145
|
+
console.error(groupResult.error);
|
|
146
|
+
process.exitCode = 1;
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (groupResult.group.config.fields[fieldPath.nestedFieldId]) {
|
|
150
|
+
console.error(`Field "${fieldPath.nestedFieldId}" already exists in group "${fieldPath.groupId}"`);
|
|
151
|
+
process.exitCode = 1;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
groupResult.group.config.fields[fieldPath.nestedFieldId] = fieldDefinition;
|
|
155
|
+
} else {
|
|
156
|
+
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
157
|
+
if (tabFields[fieldId]) {
|
|
158
|
+
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
159
|
+
process.exitCode = 1;
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
for (const [groupFieldId, groupField] of Object.entries(tabFields)) {
|
|
163
|
+
if (isGroupField(groupField) && groupField.config.fields[fieldId]) {
|
|
164
|
+
console.error(`Field "${fieldId}" already exists in group "${groupFieldId}" in tab "${tabName}"`);
|
|
165
|
+
process.exitCode = 1;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
model.json[targetTab][fieldId] = fieldDefinition;
|
|
171
|
+
}
|
|
142
172
|
|
|
143
173
|
// Write updated model
|
|
144
174
|
try {
|
|
@@ -153,7 +183,11 @@ export async function customTypeAddFieldGeoPoint(): Promise<void> {
|
|
|
153
183
|
return;
|
|
154
184
|
}
|
|
155
185
|
|
|
156
|
-
|
|
186
|
+
if (fieldPath.type === "nested") {
|
|
187
|
+
console.info(`Added field "${fieldPath.nestedFieldId}" (GeoPoint) to group "${fieldPath.groupId}" in ${typeId}`);
|
|
188
|
+
} else {
|
|
189
|
+
console.info(`Added field "${fieldId}" (GeoPoint) to "${targetTab}" tab in ${typeId}`);
|
|
190
|
+
}
|
|
157
191
|
|
|
158
192
|
try {
|
|
159
193
|
await buildTypes({ output: types });
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import type { CustomType, Group } from "@prismicio/types-internal/lib/customtypes";
|
|
2
|
+
|
|
3
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import { parseArgs } from "node:util";
|
|
5
|
+
import * as v from "valibot";
|
|
6
|
+
|
|
7
|
+
import { buildTypes } from "./codegen-types";
|
|
8
|
+
import { findUpward } from "./lib/file";
|
|
9
|
+
import { stringify } from "./lib/json";
|
|
10
|
+
import { humanReadable } from "./lib/string";
|
|
11
|
+
|
|
12
|
+
const HELP = `
|
|
13
|
+
Add a group field to an existing custom type.
|
|
14
|
+
|
|
15
|
+
USAGE
|
|
16
|
+
prismic custom-type add-field group <type-id> <field-id> [flags]
|
|
17
|
+
|
|
18
|
+
ARGUMENTS
|
|
19
|
+
type-id Custom type identifier (required)
|
|
20
|
+
field-id Field identifier (required)
|
|
21
|
+
|
|
22
|
+
FLAGS
|
|
23
|
+
-t, --tab string Target tab (default: first existing tab, or "Main")
|
|
24
|
+
-l, --label string Display label for the field (inferred from field-id if omitted)
|
|
25
|
+
--non-repeatable Make this a non-repeating group (default: repeatable)
|
|
26
|
+
--types string Output file for generated types (default: "prismicio-types.d.ts")
|
|
27
|
+
-h, --help Show help for command
|
|
28
|
+
|
|
29
|
+
EXAMPLES
|
|
30
|
+
prismic custom-type add-field group homepage buttons
|
|
31
|
+
prismic custom-type add-field group article authors --non-repeatable
|
|
32
|
+
prismic custom-type add-field group product variants --tab "Content"
|
|
33
|
+
`.trim();
|
|
34
|
+
|
|
35
|
+
const CustomTypeSchema = v.object({
|
|
36
|
+
id: v.string(),
|
|
37
|
+
label: v.string(),
|
|
38
|
+
repeatable: v.boolean(),
|
|
39
|
+
status: v.boolean(),
|
|
40
|
+
format: v.string(),
|
|
41
|
+
json: v.record(v.string(), v.record(v.string(), v.unknown())),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
export async function customTypeAddFieldGroup(): Promise<void> {
|
|
45
|
+
const {
|
|
46
|
+
values: { help, tab, label, "non-repeatable": nonRepeatable, types },
|
|
47
|
+
positionals: [typeId, fieldId],
|
|
48
|
+
} = parseArgs({
|
|
49
|
+
args: process.argv.slice(5), // skip: node, script, "custom-type", "add-field", "group"
|
|
50
|
+
options: {
|
|
51
|
+
tab: { type: "string", short: "t" },
|
|
52
|
+
label: { type: "string", short: "l" },
|
|
53
|
+
"non-repeatable": { type: "boolean" },
|
|
54
|
+
types: { type: "string" },
|
|
55
|
+
help: { type: "boolean", short: "h" },
|
|
56
|
+
},
|
|
57
|
+
allowPositionals: true,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (help) {
|
|
61
|
+
console.info(HELP);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!typeId) {
|
|
66
|
+
console.error("Missing required argument: type-id\n");
|
|
67
|
+
console.error("Usage: prismic custom-type add-field group <type-id> <field-id>");
|
|
68
|
+
process.exitCode = 1;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!fieldId) {
|
|
73
|
+
console.error("Missing required argument: field-id\n");
|
|
74
|
+
console.error("Usage: prismic custom-type add-field group <type-id> <field-id>");
|
|
75
|
+
process.exitCode = 1;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Groups cannot be nested
|
|
80
|
+
if (fieldId.includes(".")) {
|
|
81
|
+
console.error("Groups cannot be nested inside other groups");
|
|
82
|
+
process.exitCode = 1;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Find the custom type file
|
|
87
|
+
const projectRoot = await findUpward("package.json");
|
|
88
|
+
if (!projectRoot) {
|
|
89
|
+
console.error("Could not find project root (no package.json found)");
|
|
90
|
+
process.exitCode = 1;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const modelPath = new URL(`customtypes/${typeId}/index.json`, projectRoot);
|
|
95
|
+
|
|
96
|
+
// Read and parse the model
|
|
97
|
+
let model: CustomType;
|
|
98
|
+
try {
|
|
99
|
+
const contents = await readFile(modelPath, "utf8");
|
|
100
|
+
const result = v.safeParse(CustomTypeSchema, JSON.parse(contents));
|
|
101
|
+
if (!result.success) {
|
|
102
|
+
console.error(`Invalid custom type model: ${modelPath.href}`);
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
model = result.output as CustomType;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
109
|
+
console.error(`Custom type not found: ${typeId}\n`);
|
|
110
|
+
console.error(`Create it first with: prismic custom-type create ${typeId}`);
|
|
111
|
+
process.exitCode = 1;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (error instanceof Error) {
|
|
115
|
+
console.error(`Failed to read custom type: ${error.message}`);
|
|
116
|
+
} else {
|
|
117
|
+
console.error("Failed to read custom type");
|
|
118
|
+
}
|
|
119
|
+
process.exitCode = 1;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Determine target tab
|
|
124
|
+
const existingTabs = Object.keys(model.json);
|
|
125
|
+
const targetTab = tab ?? existingTabs[0] ?? "Main";
|
|
126
|
+
|
|
127
|
+
// Initialize tab if it doesn't exist
|
|
128
|
+
if (!model.json[targetTab]) {
|
|
129
|
+
model.json[targetTab] = {};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Check if field already exists in any tab
|
|
133
|
+
for (const [tabName, tabFields] of Object.entries(model.json)) {
|
|
134
|
+
if (tabFields[fieldId]) {
|
|
135
|
+
console.error(`Field "${fieldId}" already exists in tab "${tabName}"`);
|
|
136
|
+
process.exitCode = 1;
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Build field definition
|
|
142
|
+
const fieldDefinition: Group = {
|
|
143
|
+
type: "Group",
|
|
144
|
+
config: {
|
|
145
|
+
label: label ?? humanReadable(fieldId),
|
|
146
|
+
repeat: !nonRepeatable,
|
|
147
|
+
fields: {},
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Add field to model
|
|
152
|
+
model.json[targetTab][fieldId] = fieldDefinition;
|
|
153
|
+
|
|
154
|
+
// Write updated model
|
|
155
|
+
try {
|
|
156
|
+
await writeFile(modelPath, stringify(model));
|
|
157
|
+
} catch (error) {
|
|
158
|
+
if (error instanceof Error) {
|
|
159
|
+
console.error(`Failed to update custom type: ${error.message}`);
|
|
160
|
+
} else {
|
|
161
|
+
console.error("Failed to update custom type");
|
|
162
|
+
}
|
|
163
|
+
process.exitCode = 1;
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
console.info(`Added field "${fieldId}" (Group) to "${targetTab}" tab in ${typeId}`);
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
await buildTypes({ output: types });
|
|
171
|
+
console.info(`Updated types in ${types ?? "prismicio-types.d.ts"}`);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
console.warn(`Could not generate types: ${error instanceof Error ? error.message : error}`);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
console.info();
|
|
177
|
+
console.info(`Next: Add fields to the group with \`prismic custom-type add-field <type> ${typeId} ${fieldId}.<field-id>\``);
|
|
178
|
+
console.info(" Run `prismic status` when done to find next steps");
|
|
179
|
+
}
|