@wp-typia/project-tools 0.21.0 → 0.22.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.
- package/dist/runtime/ai-feature-capability.js +2 -33
- package/dist/runtime/built-in-block-artifact-types.js +11 -0
- package/dist/runtime/built-in-block-code-artifacts.js +5 -1
- package/dist/runtime/built-in-block-code-templates/interactivity.d.ts +4 -3
- package/dist/runtime/built-in-block-code-templates/interactivity.js +259 -100
- package/dist/runtime/built-in-block-code-templates.d.ts +1 -1
- package/dist/runtime/built-in-block-code-templates.js +1 -1
- package/dist/runtime/cli-add-shared.d.ts +4 -3
- package/dist/runtime/cli-add-shared.js +5 -2
- package/dist/runtime/cli-add-workspace-ability.js +3 -4
- package/dist/runtime/cli-add-workspace-admin-view.d.ts +2 -0
- package/dist/runtime/cli-add-workspace-admin-view.js +560 -31
- package/dist/runtime/cli-doctor-workspace.js +5 -4
- package/dist/runtime/cli-help.js +5 -2
- package/dist/runtime/external-layer-selection.d.ts +8 -2
- package/dist/runtime/external-layer-selection.js +3 -4
- package/dist/runtime/package-versions.d.ts +13 -0
- package/dist/runtime/package-versions.js +13 -0
- package/dist/runtime/scaffold-compatibility.d.ts +2 -2
- package/dist/runtime/scaffold-compatibility.js +22 -48
- package/dist/runtime/version-floor.d.ts +26 -0
- package/dist/runtime/version-floor.js +56 -0
- package/dist/runtime/workspace-inventory.d.ts +2 -1
- package/package.json +3 -2
|
@@ -8,14 +8,22 @@ import { PROJECT_TOOLS_PACKAGE_ROOT } from "./template-registry.js";
|
|
|
8
8
|
import { toPascalCase, toTitleCase } from "./string-case.js";
|
|
9
9
|
import { findPhpFunctionRange, hasPhpFunctionDefinition, quotePhpString, replacePhpFunctionDefinition, } from "./php-utils.js";
|
|
10
10
|
import { assertAdminViewDoesNotExist, assertValidGeneratedSlug, getWorkspaceBootstrapPath, normalizeBlockSlug, patchFile, quoteTsString, rollbackWorkspaceMutation, snapshotWorkspaceFiles, } from "./cli-add-shared.js";
|
|
11
|
-
|
|
11
|
+
import { CLI_DIAGNOSTIC_CODES, createCliDiagnosticCodeError, } from "./cli-diagnostics.js";
|
|
12
|
+
import { DEFAULT_WORDPRESS_DATAVIEWS_VERSION, DEFAULT_WORDPRESS_CORE_DATA_VERSION, DEFAULT_WORDPRESS_DATA_VERSION, DEFAULT_WP_TYPIA_DATAVIEWS_VERSION, } from "./package-versions.js";
|
|
13
|
+
const ADMIN_VIEW_REST_SOURCE_KIND = "rest-resource";
|
|
14
|
+
const ADMIN_VIEW_CORE_DATA_SOURCE_KIND = "core-data";
|
|
15
|
+
const ADMIN_VIEW_CORE_DATA_ENTITY_KIND_IDS = ["postType", "taxonomy"];
|
|
16
|
+
const ADMIN_VIEW_CORE_DATA_ENTITY_SEGMENT_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*$/u;
|
|
17
|
+
const ADMIN_VIEW_CORE_DATA_ENTITY_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/u;
|
|
18
|
+
const ADMIN_VIEW_SOURCE_USAGE = "wp-typia add admin-view <name> --source <rest-resource:slug|core-data:kind/name>";
|
|
12
19
|
const ADMIN_VIEWS_SCRIPT = "build/admin-views/index.js";
|
|
13
20
|
const ADMIN_VIEWS_ASSET = "build/admin-views/index.asset.php";
|
|
14
21
|
const ADMIN_VIEWS_STYLE = "build/admin-views/style-index.css";
|
|
15
22
|
const ADMIN_VIEWS_STYLE_RTL = "build/admin-views/style-index-rtl.css";
|
|
16
23
|
const ADMIN_VIEWS_PHP_GLOB = "/inc/admin-views/*.php";
|
|
17
|
-
const
|
|
18
|
-
|
|
24
|
+
const ADMIN_VIEW_ALLOW_UNPUBLISHED_DATAVIEWS_ENV = "WP_TYPIA_ALLOW_UNPUBLISHED_DATAVIEWS";
|
|
25
|
+
// Lift this gate in the same release that publishes @wp-typia/dataviews.
|
|
26
|
+
const ADMIN_VIEW_PUBLIC_INSTALLS_ENABLED = false;
|
|
19
27
|
const require = createRequire(import.meta.url);
|
|
20
28
|
function toCamelCase(input) {
|
|
21
29
|
const pascalCase = toPascalCase(input);
|
|
@@ -28,15 +36,26 @@ function normalizeVersionRange(value, fallback) {
|
|
|
28
36
|
}
|
|
29
37
|
return /^[~^<>=]/u.test(trimmed) ? trimmed : `^${trimmed}`;
|
|
30
38
|
}
|
|
31
|
-
function
|
|
39
|
+
function readPackageManifest(packageJsonPath) {
|
|
32
40
|
try {
|
|
33
|
-
|
|
34
|
-
return packageJson.version;
|
|
41
|
+
return JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
35
42
|
}
|
|
36
43
|
catch {
|
|
37
44
|
return undefined;
|
|
38
45
|
}
|
|
39
46
|
}
|
|
47
|
+
function readPackageManifestVersion(packageJsonPath) {
|
|
48
|
+
return readPackageManifest(packageJsonPath)?.version;
|
|
49
|
+
}
|
|
50
|
+
function isAdminViewUnpublishedDataViewsOverrideEnabled() {
|
|
51
|
+
return process.env[ADMIN_VIEW_ALLOW_UNPUBLISHED_DATAVIEWS_ENV]?.trim() === "1";
|
|
52
|
+
}
|
|
53
|
+
function assertAdminViewPackageAvailability() {
|
|
54
|
+
if (isAdminViewUnpublishedDataViewsOverrideEnabled() || ADMIN_VIEW_PUBLIC_INSTALLS_ENABLED) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, "`wp-typia add admin-view` is temporarily unavailable because `@wp-typia/dataviews` is not published to npm for public installs yet.");
|
|
58
|
+
}
|
|
40
59
|
function detectJsonIndent(source) {
|
|
41
60
|
const indentMatch = /\n([ \t]+)"/u.exec(source);
|
|
42
61
|
return indentMatch?.[1] ?? 2;
|
|
@@ -62,22 +81,77 @@ function getAdminViewRelativeModuleSpecifier(adminViewSlug, workspaceFile) {
|
|
|
62
81
|
const relativeModulePath = path.posix.relative(adminViewDir, modulePath);
|
|
63
82
|
return relativeModulePath.startsWith(".") ? relativeModulePath : `./${relativeModulePath}`;
|
|
64
83
|
}
|
|
84
|
+
function isAdminViewCoreDataSource(source) {
|
|
85
|
+
return source?.kind === ADMIN_VIEW_CORE_DATA_SOURCE_KIND;
|
|
86
|
+
}
|
|
87
|
+
function isAdminViewRestResourceSource(source) {
|
|
88
|
+
return source?.kind === ADMIN_VIEW_REST_SOURCE_KIND;
|
|
89
|
+
}
|
|
90
|
+
function assertValidCoreDataEntitySegment(label, value) {
|
|
91
|
+
const trimmed = value.trim();
|
|
92
|
+
if (!trimmed) {
|
|
93
|
+
throw new Error(`${label} is required. Use \`${ADMIN_VIEW_SOURCE_USAGE}\`.`);
|
|
94
|
+
}
|
|
95
|
+
if (!ADMIN_VIEW_CORE_DATA_ENTITY_SEGMENT_PATTERN.test(trimmed)) {
|
|
96
|
+
throw new Error(`${label} must start with a letter and contain only letters, numbers, underscores, or hyphens.`);
|
|
97
|
+
}
|
|
98
|
+
return trimmed;
|
|
99
|
+
}
|
|
100
|
+
function assertValidCoreDataEntityName(value) {
|
|
101
|
+
const normalized = value.trim();
|
|
102
|
+
if (!normalized) {
|
|
103
|
+
throw new Error(`Admin view source entity name is required. Use \`${ADMIN_VIEW_SOURCE_USAGE}\`.`);
|
|
104
|
+
}
|
|
105
|
+
if (!ADMIN_VIEW_CORE_DATA_ENTITY_NAME_PATTERN.test(normalized)) {
|
|
106
|
+
throw new Error("Admin view source entity name must start with a lowercase letter or number and contain only lowercase letters, numbers, underscores, or hyphens.");
|
|
107
|
+
}
|
|
108
|
+
return normalized;
|
|
109
|
+
}
|
|
110
|
+
function assertValidCoreDataEntityKind(value) {
|
|
111
|
+
const normalized = assertValidCoreDataEntitySegment("Admin view source entity kind", value);
|
|
112
|
+
if (!ADMIN_VIEW_CORE_DATA_ENTITY_KIND_IDS.includes(normalized)) {
|
|
113
|
+
throw new Error(`Admin view core-data sources currently support only: ${ADMIN_VIEW_CORE_DATA_ENTITY_KIND_IDS.join(", ")}.`);
|
|
114
|
+
}
|
|
115
|
+
return normalized;
|
|
116
|
+
}
|
|
117
|
+
function formatAdminViewSourceLocator(source) {
|
|
118
|
+
if (isAdminViewCoreDataSource(source)) {
|
|
119
|
+
return `${source.kind}:${source.entityKind}/${source.entityName}`;
|
|
120
|
+
}
|
|
121
|
+
return `${source.kind}:${source.slug}`;
|
|
122
|
+
}
|
|
65
123
|
function parseAdminViewSource(source) {
|
|
66
124
|
const trimmed = source?.trim();
|
|
67
125
|
if (!trimmed) {
|
|
68
126
|
return undefined;
|
|
69
127
|
}
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
128
|
+
const separatorIndex = trimmed.indexOf(":");
|
|
129
|
+
const kind = separatorIndex === -1 ? trimmed : trimmed.slice(0, separatorIndex);
|
|
130
|
+
const locator = separatorIndex === -1 ? "" : trimmed.slice(separatorIndex + 1);
|
|
131
|
+
if (!locator) {
|
|
132
|
+
throw new Error("Admin view source must use `rest-resource:<slug>` or `core-data:<kind>/<name>`.");
|
|
73
133
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
134
|
+
if (kind === ADMIN_VIEW_REST_SOURCE_KIND) {
|
|
135
|
+
return {
|
|
136
|
+
kind,
|
|
137
|
+
slug: assertValidGeneratedSlug("Admin view source slug", locator, ADMIN_VIEW_SOURCE_USAGE),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
if (kind === ADMIN_VIEW_CORE_DATA_SOURCE_KIND) {
|
|
141
|
+
const [entityKind, entityName, extra] = locator.split("/");
|
|
142
|
+
if (!entityKind || !entityName || extra !== undefined) {
|
|
143
|
+
throw new Error("Admin view core-data sources must use `core-data:<kind>/<name>`, for example `core-data:postType/post`.");
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
entityKind: assertValidCoreDataEntityKind(entityKind),
|
|
147
|
+
entityName: assertValidCoreDataEntityName(entityName),
|
|
148
|
+
kind,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
throw new Error("Admin view source must use `rest-resource:<slug>` or `core-data:<kind>/<name>`.");
|
|
78
152
|
}
|
|
79
153
|
function resolveRestResourceSource(restResources, source) {
|
|
80
|
-
if (!source) {
|
|
154
|
+
if (!isAdminViewRestResourceSource(source)) {
|
|
81
155
|
return undefined;
|
|
82
156
|
}
|
|
83
157
|
const restResource = restResources.find((entry) => entry.slug === source.slug);
|
|
@@ -97,7 +171,9 @@ function buildAdminViewConfigEntry(adminViewSlug, source) {
|
|
|
97
171
|
`\t\tfile: ${quoteTsString(`src/admin-views/${adminViewSlug}/index.tsx`)},`,
|
|
98
172
|
`\t\tphpFile: ${quoteTsString(`inc/admin-views/${adminViewSlug}.php`)},`,
|
|
99
173
|
`\t\tslug: ${quoteTsString(adminViewSlug)},`,
|
|
100
|
-
source
|
|
174
|
+
source
|
|
175
|
+
? `\t\tsource: ${quoteTsString(formatAdminViewSourceLocator(source))},`
|
|
176
|
+
: null,
|
|
101
177
|
"\t},",
|
|
102
178
|
]
|
|
103
179
|
.filter((line) => typeof line === "string")
|
|
@@ -109,8 +185,12 @@ function buildAdminViewRegistrySource(adminViewSlugs) {
|
|
|
109
185
|
.join("\n");
|
|
110
186
|
return `${importLines}${importLines ? "\n\n" : ""}// wp-typia add admin-view entries\n`;
|
|
111
187
|
}
|
|
112
|
-
|
|
188
|
+
/**
|
|
189
|
+
* Build the generated admin-view item and dataset types for the selected source.
|
|
190
|
+
*/
|
|
191
|
+
function buildAdminViewTypesSource(adminViewSlug, restResource, coreDataSource) {
|
|
113
192
|
const pascalName = toPascalCase(adminViewSlug);
|
|
193
|
+
const coreDataRecordTypeName = `${pascalName}CoreDataRecord`;
|
|
114
194
|
const itemTypeName = `${pascalName}AdminViewItem`;
|
|
115
195
|
const dataSetTypeName = `${pascalName}AdminViewDataSet`;
|
|
116
196
|
if (restResource) {
|
|
@@ -120,6 +200,74 @@ function buildAdminViewTypesSource(adminViewSlug, restResource) {
|
|
|
120
200
|
|
|
121
201
|
export type ${itemTypeName} = ${restPascalName}Record;
|
|
122
202
|
|
|
203
|
+
export interface ${dataSetTypeName} {
|
|
204
|
+
\titems: ${itemTypeName}[];
|
|
205
|
+
\tpaginationInfo: {
|
|
206
|
+
\t\ttotalItems: number;
|
|
207
|
+
\t\ttotalPages: number;
|
|
208
|
+
\t};
|
|
209
|
+
}
|
|
210
|
+
`;
|
|
211
|
+
}
|
|
212
|
+
if (coreDataSource) {
|
|
213
|
+
if (coreDataSource.entityKind === "taxonomy") {
|
|
214
|
+
return `export interface ${coreDataRecordTypeName} {
|
|
215
|
+
\tcount?: number;
|
|
216
|
+
\tdescription?: string;
|
|
217
|
+
\tid: number;
|
|
218
|
+
\tlink?: string;
|
|
219
|
+
\tmeta?: Record<string, unknown>;
|
|
220
|
+
\tname?: string;
|
|
221
|
+
\tparent?: number;
|
|
222
|
+
\tslug?: string;
|
|
223
|
+
\ttaxonomy?: string;
|
|
224
|
+
\t[key: string]: unknown;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface ${itemTypeName} {
|
|
228
|
+
\tcount: number;
|
|
229
|
+
\tdescription: string;
|
|
230
|
+
\tid: number;
|
|
231
|
+
\tlink: string;
|
|
232
|
+
\tname: string;
|
|
233
|
+
\tparent: number;
|
|
234
|
+
\traw: ${coreDataRecordTypeName};
|
|
235
|
+
\tslug: string;
|
|
236
|
+
\ttaxonomy: string;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export interface ${dataSetTypeName} {
|
|
240
|
+
\titems: ${itemTypeName}[];
|
|
241
|
+
\tpaginationInfo: {
|
|
242
|
+
\t\ttotalItems: number;
|
|
243
|
+
\t\ttotalPages: number;
|
|
244
|
+
\t};
|
|
245
|
+
}
|
|
246
|
+
`;
|
|
247
|
+
}
|
|
248
|
+
return `export interface ${coreDataRecordTypeName} {
|
|
249
|
+
\tid: number;
|
|
250
|
+
\tdate?: string;
|
|
251
|
+
\tmodified?: string;
|
|
252
|
+
\tname?: string;
|
|
253
|
+
\tslug?: string;
|
|
254
|
+
\tstatus?: string;
|
|
255
|
+
\ttitle?: string | {
|
|
256
|
+
\t\traw?: string;
|
|
257
|
+
\t\trendered?: string;
|
|
258
|
+
\t};
|
|
259
|
+
\t[key: string]: unknown;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export interface ${itemTypeName} {
|
|
263
|
+
\tid: number;
|
|
264
|
+
\traw: ${coreDataRecordTypeName};
|
|
265
|
+
\tslug: string;
|
|
266
|
+
\tstatus: string;
|
|
267
|
+
\ttitle: string;
|
|
268
|
+
\tupdatedAt: string;
|
|
269
|
+
}
|
|
270
|
+
|
|
123
271
|
export interface ${dataSetTypeName} {
|
|
124
272
|
\titems: ${itemTypeName}[];
|
|
125
273
|
\tpaginationInfo: {
|
|
@@ -148,19 +296,37 @@ export interface ${dataSetTypeName} {
|
|
|
148
296
|
}
|
|
149
297
|
`;
|
|
150
298
|
}
|
|
151
|
-
|
|
299
|
+
/**
|
|
300
|
+
* Build the generated DataViews config source for an admin-view scaffold.
|
|
301
|
+
*/
|
|
302
|
+
function buildAdminViewConfigSource(adminViewSlug, textDomain, source, restResource) {
|
|
152
303
|
const pascalName = toPascalCase(adminViewSlug);
|
|
153
304
|
const camelName = toCamelCase(adminViewSlug);
|
|
154
305
|
const itemTypeName = `${pascalName}AdminViewItem`;
|
|
155
306
|
const dataViewsName = `${camelName}AdminDataViews`;
|
|
307
|
+
const isCoreDataSource = source?.kind === ADMIN_VIEW_CORE_DATA_SOURCE_KIND;
|
|
308
|
+
const isTaxonomyCoreDataSource = source?.kind === ADMIN_VIEW_CORE_DATA_SOURCE_KIND &&
|
|
309
|
+
source.entityKind === "taxonomy";
|
|
156
310
|
const defaultViewFields = restResource
|
|
157
311
|
? "['id']"
|
|
158
|
-
:
|
|
312
|
+
: isTaxonomyCoreDataSource
|
|
313
|
+
? "['name', 'slug', 'count']"
|
|
314
|
+
: isCoreDataSource
|
|
315
|
+
? "['title', 'slug', 'status', 'updatedAt']"
|
|
316
|
+
: "['title', 'status', 'updatedAt']";
|
|
159
317
|
const searchEnabled = restResource ? "false" : "true";
|
|
160
|
-
const titleFieldSource = restResource
|
|
318
|
+
const titleFieldSource = restResource
|
|
319
|
+
? ""
|
|
320
|
+
: isTaxonomyCoreDataSource
|
|
321
|
+
? "\ttitleField: 'name',\n"
|
|
322
|
+
: "\ttitleField: 'title',\n";
|
|
161
323
|
const defaultViewEnhancementsSource = restResource
|
|
162
324
|
? ""
|
|
163
|
-
:
|
|
325
|
+
: isTaxonomyCoreDataSource
|
|
326
|
+
? "\t\ttitleField: 'name',\n"
|
|
327
|
+
: isCoreDataSource
|
|
328
|
+
? "\t\ttitleField: 'title',\n"
|
|
329
|
+
: `\t\tsort: {
|
|
164
330
|
\t\t\tdirection: 'desc',
|
|
165
331
|
\t\t\tfield: 'updatedAt',
|
|
166
332
|
\t\t},
|
|
@@ -168,7 +334,58 @@ function buildAdminViewConfigSource(adminViewSlug, textDomain, restResource) {
|
|
|
168
334
|
`;
|
|
169
335
|
const additionalFieldsSource = restResource
|
|
170
336
|
? "\t\t// REST-backed screens start with the guaranteed ID column. Add project-owned fields here once they are declared on the REST record type."
|
|
171
|
-
:
|
|
337
|
+
: isTaxonomyCoreDataSource
|
|
338
|
+
? `\t\tcount: {
|
|
339
|
+
\t\t\tlabel: __( 'Count', ${quoteTsString(textDomain)} ),
|
|
340
|
+
\t\t\tschema: { type: 'integer' },
|
|
341
|
+
\t\t},
|
|
342
|
+
\t\tdescription: {
|
|
343
|
+
\t\t\tlabel: __( 'Description', ${quoteTsString(textDomain)} ),
|
|
344
|
+
\t\t\tschema: { type: 'string' },
|
|
345
|
+
\t\t},
|
|
346
|
+
\t\tlink: {
|
|
347
|
+
\t\t\tlabel: __( 'Link', ${quoteTsString(textDomain)} ),
|
|
348
|
+
\t\t\tschema: { format: 'uri', type: 'string' },
|
|
349
|
+
\t\t},
|
|
350
|
+
\t\tname: {
|
|
351
|
+
\t\t\tenableGlobalSearch: true,
|
|
352
|
+
\t\t\tlabel: __( 'Name', ${quoteTsString(textDomain)} ),
|
|
353
|
+
\t\t\tschema: { type: 'string' },
|
|
354
|
+
\t\t},
|
|
355
|
+
\t\tparent: {
|
|
356
|
+
\t\t\tlabel: __( 'Parent', ${quoteTsString(textDomain)} ),
|
|
357
|
+
\t\t\tschema: { type: 'integer' },
|
|
358
|
+
\t\t},
|
|
359
|
+
\t\tslug: {
|
|
360
|
+
\t\t\tenableGlobalSearch: true,
|
|
361
|
+
\t\t\tlabel: __( 'Slug', ${quoteTsString(textDomain)} ),
|
|
362
|
+
\t\t\tschema: { type: 'string' },
|
|
363
|
+
\t\t},
|
|
364
|
+
\t\ttaxonomy: {
|
|
365
|
+
\t\t\tlabel: __( 'Taxonomy', ${quoteTsString(textDomain)} ),
|
|
366
|
+
\t\t\tschema: { type: 'string' },
|
|
367
|
+
\t\t},`
|
|
368
|
+
: isCoreDataSource
|
|
369
|
+
? `\t\tslug: {
|
|
370
|
+
\t\t\tenableGlobalSearch: true,
|
|
371
|
+
\t\t\tlabel: __( 'Slug', ${quoteTsString(textDomain)} ),
|
|
372
|
+
\t\t\tschema: { type: 'string' },
|
|
373
|
+
\t\t},
|
|
374
|
+
\t\tstatus: {
|
|
375
|
+
\t\t\tlabel: __( 'Status', ${quoteTsString(textDomain)} ),
|
|
376
|
+
\t\t\tschema: { type: 'string' },
|
|
377
|
+
\t\t},
|
|
378
|
+
\t\ttitle: {
|
|
379
|
+
\t\t\tenableGlobalSearch: true,
|
|
380
|
+
\t\t\tlabel: __( 'Name', ${quoteTsString(textDomain)} ),
|
|
381
|
+
\t\t\tschema: { type: 'string' },
|
|
382
|
+
\t\t},
|
|
383
|
+
\t\tupdatedAt: {
|
|
384
|
+
\t\t\tlabel: __( 'Updated', ${quoteTsString(textDomain)} ),
|
|
385
|
+
\t\t\tschema: { format: 'date-time', type: 'string' },
|
|
386
|
+
\t\t\ttype: 'datetime',
|
|
387
|
+
\t\t},`
|
|
388
|
+
: `\t\towner: {
|
|
172
389
|
\t\t\tlabel: __( 'Owner', ${quoteTsString(textDomain)} ),
|
|
173
390
|
\t\t\tschema: { type: 'string' },
|
|
174
391
|
\t\t},
|
|
@@ -355,6 +572,220 @@ export async function ${fetchName}(
|
|
|
355
572
|
}
|
|
356
573
|
`;
|
|
357
574
|
}
|
|
575
|
+
/**
|
|
576
|
+
* Build a core-data-backed admin-view data module for a supported entity family.
|
|
577
|
+
*/
|
|
578
|
+
function buildCoreDataAdminViewDataSource(adminViewSlug, coreDataSource) {
|
|
579
|
+
const pascalName = toPascalCase(adminViewSlug);
|
|
580
|
+
const camelName = toCamelCase(adminViewSlug);
|
|
581
|
+
const coreDataRecordTypeName = `${pascalName}CoreDataRecord`;
|
|
582
|
+
const dataSetTypeName = `${pascalName}AdminViewDataSet`;
|
|
583
|
+
const itemTypeName = `${pascalName}AdminViewItem`;
|
|
584
|
+
const queryTypeName = `${pascalName}AdminViewQuery`;
|
|
585
|
+
const dataViewsName = `${camelName}AdminDataViews`;
|
|
586
|
+
const useEntityRecordName = `use${pascalName}EntityRecord`;
|
|
587
|
+
const useEntityRecordsName = `use${pascalName}EntityRecords`;
|
|
588
|
+
const useAdminViewDataName = `use${pascalName}AdminViewData`;
|
|
589
|
+
if (coreDataSource.entityKind === "taxonomy") {
|
|
590
|
+
return `import type { DataViewsView } from '@wp-typia/dataviews';
|
|
591
|
+
import { useEntityRecord, useEntityRecords } from '@wordpress/core-data';
|
|
592
|
+
import { useMemo } from '@wordpress/element';
|
|
593
|
+
|
|
594
|
+
import { ${dataViewsName} } from './config';
|
|
595
|
+
import type {
|
|
596
|
+
\t${coreDataRecordTypeName},
|
|
597
|
+
\t${dataSetTypeName},
|
|
598
|
+
\t${itemTypeName},
|
|
599
|
+
} from './types';
|
|
600
|
+
|
|
601
|
+
export interface ${queryTypeName} {
|
|
602
|
+
\tpage?: number;
|
|
603
|
+
\tper_page?: number;
|
|
604
|
+
\tsearch?: string;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const CORE_DATA_ENTITY_KIND = ${quoteTsString(coreDataSource.entityKind)};
|
|
608
|
+
const CORE_DATA_ENTITY_NAME = ${quoteTsString(coreDataSource.entityName)};
|
|
609
|
+
|
|
610
|
+
function normalizeCoreDataNumber(value: unknown): number {
|
|
611
|
+
\treturn typeof value === 'number' && Number.isFinite(value) ? value : 0;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
function normalizeCoreDataString(value: unknown): string {
|
|
615
|
+
\treturn typeof value === 'string' ? value : '';
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function normalizeTaxonomyRecord(record: ${coreDataRecordTypeName}): ${itemTypeName} {
|
|
619
|
+
\treturn {
|
|
620
|
+
\t\tcount: normalizeCoreDataNumber(record.count),
|
|
621
|
+
\t\tdescription: normalizeCoreDataString(record.description),
|
|
622
|
+
\t\tid: record.id,
|
|
623
|
+
\t\tlink: normalizeCoreDataString(record.link),
|
|
624
|
+
\t\tname: normalizeCoreDataString(record.name) || normalizeCoreDataString(record.slug),
|
|
625
|
+
\t\tparent: normalizeCoreDataNumber(record.parent),
|
|
626
|
+
\t\traw: record,
|
|
627
|
+
\t\tslug: normalizeCoreDataString(record.slug),
|
|
628
|
+
\t\ttaxonomy: normalizeCoreDataString(record.taxonomy),
|
|
629
|
+
\t};
|
|
630
|
+
\t}
|
|
631
|
+
|
|
632
|
+
export function ${useEntityRecordName}(recordId: number | undefined) {
|
|
633
|
+
\treturn useEntityRecord<${coreDataRecordTypeName}>(
|
|
634
|
+
\t\tCORE_DATA_ENTITY_KIND,
|
|
635
|
+
\t\tCORE_DATA_ENTITY_NAME,
|
|
636
|
+
\t\trecordId ?? 0,
|
|
637
|
+
\t\t{ enabled: typeof recordId === 'number' },
|
|
638
|
+
\t);
|
|
639
|
+
\t}
|
|
640
|
+
|
|
641
|
+
export function ${useEntityRecordsName}(view: DataViewsView<${itemTypeName}>) {
|
|
642
|
+
\tconst query = ${dataViewsName}.toQueryArgs<${queryTypeName}>(view, {
|
|
643
|
+
\t\tperPageParam: 'per_page',
|
|
644
|
+
\t});
|
|
645
|
+
|
|
646
|
+
\treturn useEntityRecords<${coreDataRecordTypeName}>(
|
|
647
|
+
\t\tCORE_DATA_ENTITY_KIND,
|
|
648
|
+
\t\tCORE_DATA_ENTITY_NAME,
|
|
649
|
+
\t\tquery,
|
|
650
|
+
\t);
|
|
651
|
+
\t}
|
|
652
|
+
|
|
653
|
+
export function ${useAdminViewDataName}(view: DataViewsView<${itemTypeName}>) {
|
|
654
|
+
\tconst { hasResolved, isResolving, records, totalItems, totalPages } =
|
|
655
|
+
\t\t${useEntityRecordsName}(view);
|
|
656
|
+
\tconst items = useMemo(
|
|
657
|
+
\t\t() => (records ?? []).map((record) => normalizeTaxonomyRecord(record)),
|
|
658
|
+
\t\t[records],
|
|
659
|
+
\t);
|
|
660
|
+
\tconst dataSet = useMemo<${dataSetTypeName}>(
|
|
661
|
+
\t\t() => ({
|
|
662
|
+
\t\t\titems,
|
|
663
|
+
\t\t\tpaginationInfo: {
|
|
664
|
+
\t\t\t\ttotalItems: totalItems ?? items.length,
|
|
665
|
+
\t\t\t\ttotalPages: Math.max(1, totalPages ?? 1),
|
|
666
|
+
\t\t\t},
|
|
667
|
+
\t\t}),
|
|
668
|
+
\t\t[items, totalItems, totalPages],
|
|
669
|
+
\t);
|
|
670
|
+
\tconst error =
|
|
671
|
+
\t\t!isResolving && hasResolved && records === null
|
|
672
|
+
\t\t\t? 'Unable to load core-data entity records.'
|
|
673
|
+
\t\t\t: null;
|
|
674
|
+
|
|
675
|
+
\treturn {
|
|
676
|
+
\t\tdataSet,
|
|
677
|
+
\t\terror,
|
|
678
|
+
\t\tisLoading: isResolving,
|
|
679
|
+
\t};
|
|
680
|
+
\t}
|
|
681
|
+
`;
|
|
682
|
+
}
|
|
683
|
+
return `import type { DataViewsView } from '@wp-typia/dataviews';
|
|
684
|
+
import { useEntityRecord, useEntityRecords } from '@wordpress/core-data';
|
|
685
|
+
import { useMemo } from '@wordpress/element';
|
|
686
|
+
|
|
687
|
+
import { ${dataViewsName} } from './config';
|
|
688
|
+
import type {
|
|
689
|
+
\t${coreDataRecordTypeName},
|
|
690
|
+
\t${dataSetTypeName},
|
|
691
|
+
\t${itemTypeName},
|
|
692
|
+
} from './types';
|
|
693
|
+
|
|
694
|
+
export interface ${queryTypeName} {
|
|
695
|
+
\tpage?: number;
|
|
696
|
+
\tper_page?: number;
|
|
697
|
+
\tsearch?: string;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
const CORE_DATA_ENTITY_KIND = ${quoteTsString(coreDataSource.entityKind)};
|
|
701
|
+
const CORE_DATA_ENTITY_NAME = ${quoteTsString(coreDataSource.entityName)};
|
|
702
|
+
|
|
703
|
+
function normalizeCoreDataString(value: unknown): string {
|
|
704
|
+
\treturn typeof value === 'string' ? value : '';
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
function normalizeCoreDataTitle(record: ${coreDataRecordTypeName}): string {
|
|
708
|
+
\tif (typeof record.title === 'string') {
|
|
709
|
+
\t\treturn record.title;
|
|
710
|
+
\t}
|
|
711
|
+
\tif (record.title && typeof record.title === 'object') {
|
|
712
|
+
\t\tif (typeof record.title.rendered === 'string') {
|
|
713
|
+
\t\t\treturn record.title.rendered;
|
|
714
|
+
\t\t}
|
|
715
|
+
\t\tif (typeof record.title.raw === 'string') {
|
|
716
|
+
\t\t\treturn record.title.raw;
|
|
717
|
+
\t\t}
|
|
718
|
+
\t}
|
|
719
|
+
|
|
720
|
+
\treturn normalizeCoreDataString(record.name) || normalizeCoreDataString(record.slug);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
function normalizeCoreDataUpdatedAt(record: ${coreDataRecordTypeName}): string {
|
|
724
|
+
\treturn normalizeCoreDataString(record.modified) || normalizeCoreDataString(record.date);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
function normalizeCoreDataRecord(record: ${coreDataRecordTypeName}): ${itemTypeName} {
|
|
728
|
+
\treturn {
|
|
729
|
+
\t\tid: record.id,
|
|
730
|
+
\t\traw: record,
|
|
731
|
+
\t\tslug: normalizeCoreDataString(record.slug),
|
|
732
|
+
\t\tstatus: normalizeCoreDataString(record.status),
|
|
733
|
+
\t\ttitle: normalizeCoreDataTitle(record),
|
|
734
|
+
\t\tupdatedAt: normalizeCoreDataUpdatedAt(record),
|
|
735
|
+
\t};
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
export function ${useEntityRecordName}(recordId: number | undefined) {
|
|
739
|
+
\treturn useEntityRecord<${coreDataRecordTypeName}>(
|
|
740
|
+
\t\tCORE_DATA_ENTITY_KIND,
|
|
741
|
+
\t\tCORE_DATA_ENTITY_NAME,
|
|
742
|
+
\t\trecordId ?? 0,
|
|
743
|
+
\t\t{ enabled: typeof recordId === 'number' },
|
|
744
|
+
\t);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
export function ${useEntityRecordsName}(view: DataViewsView<${itemTypeName}>) {
|
|
748
|
+
\tconst query = ${dataViewsName}.toQueryArgs<${queryTypeName}>(view, {
|
|
749
|
+
\t\tperPageParam: 'per_page',
|
|
750
|
+
\t});
|
|
751
|
+
|
|
752
|
+
\treturn useEntityRecords<${coreDataRecordTypeName}>(
|
|
753
|
+
\t\tCORE_DATA_ENTITY_KIND,
|
|
754
|
+
\t\tCORE_DATA_ENTITY_NAME,
|
|
755
|
+
\t\tquery,
|
|
756
|
+
\t);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
export function ${useAdminViewDataName}(view: DataViewsView<${itemTypeName}>) {
|
|
760
|
+
\tconst { hasResolved, isResolving, records, totalItems, totalPages } =
|
|
761
|
+
\t\t${useEntityRecordsName}(view);
|
|
762
|
+
\tconst items = useMemo(
|
|
763
|
+
\t\t() => (records ?? []).map((record) => normalizeCoreDataRecord(record)),
|
|
764
|
+
\t\t[records],
|
|
765
|
+
\t);
|
|
766
|
+
\tconst dataSet = useMemo<${dataSetTypeName}>(
|
|
767
|
+
\t\t() => ({
|
|
768
|
+
\t\t\titems,
|
|
769
|
+
\t\t\tpaginationInfo: {
|
|
770
|
+
\t\t\t\ttotalItems: totalItems ?? items.length,
|
|
771
|
+
\t\t\t\ttotalPages: Math.max(1, totalPages ?? 1),
|
|
772
|
+
\t\t\t},
|
|
773
|
+
\t\t}),
|
|
774
|
+
\t\t[items, totalItems, totalPages],
|
|
775
|
+
\t);
|
|
776
|
+
\tconst error =
|
|
777
|
+
\t\t!isResolving && hasResolved && records === null
|
|
778
|
+
\t\t\t? 'Unable to load core-data entity records.'
|
|
779
|
+
\t\t\t: null;
|
|
780
|
+
|
|
781
|
+
\treturn {
|
|
782
|
+
\t\tdataSet,
|
|
783
|
+
\t\terror,
|
|
784
|
+
\t\tisLoading: isResolving,
|
|
785
|
+
\t};
|
|
786
|
+
}
|
|
787
|
+
`;
|
|
788
|
+
}
|
|
358
789
|
function buildAdminViewScreenSource(adminViewSlug, textDomain) {
|
|
359
790
|
const pascalName = toPascalCase(adminViewSlug);
|
|
360
791
|
const camelName = toCamelCase(adminViewSlug);
|
|
@@ -468,6 +899,81 @@ export function ${componentName}() {
|
|
|
468
899
|
}
|
|
469
900
|
`;
|
|
470
901
|
}
|
|
902
|
+
function buildCoreDataAdminViewScreenSource(adminViewSlug, textDomain) {
|
|
903
|
+
const pascalName = toPascalCase(adminViewSlug);
|
|
904
|
+
const camelName = toCamelCase(adminViewSlug);
|
|
905
|
+
const itemTypeName = `${pascalName}AdminViewItem`;
|
|
906
|
+
const dataSetTypeName = `${pascalName}AdminViewDataSet`;
|
|
907
|
+
const componentName = `${pascalName}AdminViewScreen`;
|
|
908
|
+
const dataViewsName = `${camelName}AdminDataViews`;
|
|
909
|
+
const useAdminViewDataName = `use${pascalName}AdminViewData`;
|
|
910
|
+
const title = toTitleCase(adminViewSlug);
|
|
911
|
+
return `import type { DataViewsConfig, DataViewsView } from '@wp-typia/dataviews';
|
|
912
|
+
import { Notice, Spinner } from '@wordpress/components';
|
|
913
|
+
import { useState } from '@wordpress/element';
|
|
914
|
+
import { __ } from '@wordpress/i18n';
|
|
915
|
+
import { DataViews } from '@wordpress/dataviews/wp';
|
|
916
|
+
|
|
917
|
+
import { ${dataViewsName} } from './config';
|
|
918
|
+
import { ${useAdminViewDataName} } from './data';
|
|
919
|
+
import type { ${dataSetTypeName}, ${itemTypeName} } from './types';
|
|
920
|
+
|
|
921
|
+
const TypedDataViews = DataViews as unknown as <TItem extends object>(
|
|
922
|
+
\tprops: DataViewsConfig<TItem>,
|
|
923
|
+
) => ReturnType<typeof DataViews>;
|
|
924
|
+
|
|
925
|
+
const EMPTY_DATA_SET: ${dataSetTypeName} = {
|
|
926
|
+
\titems: [],
|
|
927
|
+
\tpaginationInfo: {
|
|
928
|
+
\t\ttotalItems: 0,
|
|
929
|
+
\t\ttotalPages: 1,
|
|
930
|
+
\t},
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
export function ${componentName}() {
|
|
934
|
+
\tconst [view, setView] = useState<DataViewsView<${itemTypeName}>>(
|
|
935
|
+
\t\t${dataViewsName}.defaultView,
|
|
936
|
+
\t);
|
|
937
|
+
\tconst {
|
|
938
|
+
\t\tdataSet = EMPTY_DATA_SET,
|
|
939
|
+
\t\terror,
|
|
940
|
+
\t\tisLoading,
|
|
941
|
+
\t} = ${useAdminViewDataName}(view);
|
|
942
|
+
\tconst config = ${dataViewsName}.createConfig({
|
|
943
|
+
\t\tdata: dataSet.items,
|
|
944
|
+
\t\tisLoading,
|
|
945
|
+
\t\tonChangeView: setView,
|
|
946
|
+
\t\tpaginationInfo: dataSet.paginationInfo,
|
|
947
|
+
\t\tview,
|
|
948
|
+
\t});
|
|
949
|
+
|
|
950
|
+
\treturn (
|
|
951
|
+
\t\t<div className="wp-typia-admin-view-screen">
|
|
952
|
+
\t\t\t<header className="wp-typia-admin-view-screen__header">
|
|
953
|
+
\t\t\t\t<div>
|
|
954
|
+
\t\t\t\t\t<p className="wp-typia-admin-view-screen__eyebrow">
|
|
955
|
+
\t\t\t\t\t\t{ __( 'DataViews admin screen', ${quoteTsString(textDomain)} ) }
|
|
956
|
+
\t\t\t\t\t</p>
|
|
957
|
+
\t\t\t\t\t<h1>{ __( ${quoteTsString(title)}, ${quoteTsString(textDomain)} ) }</h1>
|
|
958
|
+
\t\t\t\t\t<p>
|
|
959
|
+
\t\t\t\t\t\t{ __( 'This screen reads from the WordPress core-data entity store. Extend data.ts when you need entity-specific field mapping or edit flows.', ${quoteTsString(textDomain)} ) }
|
|
960
|
+
\t\t\t\t\t</p>
|
|
961
|
+
\t\t\t\t</div>
|
|
962
|
+
\t\t\t\t<div className="wp-typia-admin-view-screen__actions">
|
|
963
|
+
\t\t\t\t\t{ isLoading ? <Spinner /> : null }
|
|
964
|
+
\t\t\t\t</div>
|
|
965
|
+
\t\t\t</header>
|
|
966
|
+
\t\t\t{ error ? (
|
|
967
|
+
\t\t\t\t<Notice isDismissible={ false } status="error">
|
|
968
|
+
\t\t\t\t\t{ error }
|
|
969
|
+
\t\t\t\t</Notice>
|
|
970
|
+
\t\t\t) : null }
|
|
971
|
+
\t\t\t<TypedDataViews<${itemTypeName}> { ...config } />
|
|
972
|
+
\t\t</div>
|
|
973
|
+
\t);
|
|
974
|
+
}
|
|
975
|
+
`;
|
|
976
|
+
}
|
|
471
977
|
function buildAdminViewEntrySource(adminViewSlug) {
|
|
472
978
|
const pascalName = toPascalCase(adminViewSlug);
|
|
473
979
|
const componentName = `${pascalName}AdminViewScreen`;
|
|
@@ -637,15 +1143,26 @@ add_action( 'admin_menu', '${registerFunctionName}' );
|
|
|
637
1143
|
add_action( 'admin_enqueue_scripts', '${enqueueFunctionName}' );
|
|
638
1144
|
`;
|
|
639
1145
|
}
|
|
640
|
-
async function ensureAdminViewPackageDependencies(workspace) {
|
|
1146
|
+
async function ensureAdminViewPackageDependencies(workspace, adminViewSource) {
|
|
641
1147
|
const packageJsonPath = path.join(workspace.projectDir, "package.json");
|
|
642
1148
|
const wpTypiaDataViewsVersion = resolvePackageVersionRange("@wp-typia/dataviews", DEFAULT_WP_TYPIA_DATAVIEWS_VERSION, "wp-typia-dataviews");
|
|
643
1149
|
const wordpressDataViewsVersion = resolvePackageVersionRange("@wordpress/dataviews", DEFAULT_WORDPRESS_DATAVIEWS_VERSION);
|
|
1150
|
+
const wordpressCoreDataVersion = resolvePackageVersionRange("@wordpress/core-data", DEFAULT_WORDPRESS_CORE_DATA_VERSION);
|
|
1151
|
+
const wordpressDataVersion = resolvePackageVersionRange("@wordpress/data", DEFAULT_WORDPRESS_DATA_VERSION);
|
|
644
1152
|
await patchFile(packageJsonPath, (source) => {
|
|
645
1153
|
const packageJson = JSON.parse(source);
|
|
1154
|
+
const coreDataDependencies = isAdminViewCoreDataSource(adminViewSource)
|
|
1155
|
+
? {
|
|
1156
|
+
"@wordpress/core-data": packageJson.dependencies?.["@wordpress/core-data"] ??
|
|
1157
|
+
wordpressCoreDataVersion,
|
|
1158
|
+
"@wordpress/data": packageJson.dependencies?.["@wordpress/data"] ??
|
|
1159
|
+
wordpressDataVersion,
|
|
1160
|
+
}
|
|
1161
|
+
: {};
|
|
646
1162
|
const nextDependencies = {
|
|
647
1163
|
...(packageJson.dependencies ?? {}),
|
|
648
1164
|
"@wordpress/dataviews": packageJson.dependencies?.["@wordpress/dataviews"] ?? wordpressDataViewsVersion,
|
|
1165
|
+
...coreDataDependencies,
|
|
649
1166
|
};
|
|
650
1167
|
const nextDevDependencies = {
|
|
651
1168
|
...(packageJson.devDependencies ?? {}),
|
|
@@ -806,6 +1323,8 @@ async function writeAdminViewRegistry(projectDir, adminViewSlug) {
|
|
|
806
1323
|
* Defaults to `process.cwd()`.
|
|
807
1324
|
* @param options.source Optional data source locator. `rest-resource:<slug>`
|
|
808
1325
|
* wires the screen to an existing list-capable REST resource.
|
|
1326
|
+
* `core-data:<kind>/<name>` binds the screen to a supported WordPress-owned
|
|
1327
|
+
* core-data entity collection.
|
|
809
1328
|
* @returns A promise that resolves with the normalized `adminViewSlug`, optional
|
|
810
1329
|
* `source`, and owning `projectDir` after scaffold files and inventory entries
|
|
811
1330
|
* are written successfully.
|
|
@@ -814,10 +1333,14 @@ async function writeAdminViewRegistry(projectDir, adminViewSlug) {
|
|
|
814
1333
|
*/
|
|
815
1334
|
export async function runAddAdminViewCommand({ adminViewName, cwd = process.cwd(), source, }) {
|
|
816
1335
|
const workspace = resolveWorkspaceProject(cwd);
|
|
817
|
-
|
|
1336
|
+
assertAdminViewPackageAvailability();
|
|
1337
|
+
const adminViewSlug = assertValidGeneratedSlug("Admin view name", normalizeBlockSlug(adminViewName), "wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>]");
|
|
818
1338
|
const parsedSource = parseAdminViewSource(source);
|
|
819
1339
|
const inventory = readWorkspaceInventory(workspace.projectDir);
|
|
820
1340
|
const restResource = resolveRestResourceSource(inventory.restResources, parsedSource);
|
|
1341
|
+
const coreDataSource = isAdminViewCoreDataSource(parsedSource)
|
|
1342
|
+
? parsedSource
|
|
1343
|
+
: undefined;
|
|
821
1344
|
assertAdminViewDoesNotExist(workspace.projectDir, adminViewSlug, inventory);
|
|
822
1345
|
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
823
1346
|
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
@@ -842,16 +1365,20 @@ export async function runAddAdminViewCommand({ adminViewName, cwd = process.cwd(
|
|
|
842
1365
|
try {
|
|
843
1366
|
await fsp.mkdir(adminViewDir, { recursive: true });
|
|
844
1367
|
await fsp.mkdir(path.dirname(adminViewPhpPath), { recursive: true });
|
|
845
|
-
await ensureAdminViewPackageDependencies(workspace);
|
|
1368
|
+
await ensureAdminViewPackageDependencies(workspace, parsedSource);
|
|
846
1369
|
await ensureAdminViewBootstrapAnchors(workspace);
|
|
847
1370
|
await ensureAdminViewBuildScriptAnchors(workspace);
|
|
848
1371
|
await ensureAdminViewWebpackAnchors(workspace);
|
|
849
|
-
await fsp.writeFile(path.join(adminViewDir, "types.ts"), buildAdminViewTypesSource(adminViewSlug, restResource), "utf8");
|
|
850
|
-
await fsp.writeFile(path.join(adminViewDir, "config.ts"), buildAdminViewConfigSource(adminViewSlug, workspace.workspace.textDomain, restResource), "utf8");
|
|
851
|
-
await fsp.writeFile(path.join(adminViewDir, "data.ts"),
|
|
852
|
-
?
|
|
853
|
-
:
|
|
854
|
-
|
|
1372
|
+
await fsp.writeFile(path.join(adminViewDir, "types.ts"), buildAdminViewTypesSource(adminViewSlug, restResource, coreDataSource), "utf8");
|
|
1373
|
+
await fsp.writeFile(path.join(adminViewDir, "config.ts"), buildAdminViewConfigSource(adminViewSlug, workspace.workspace.textDomain, parsedSource, restResource), "utf8");
|
|
1374
|
+
await fsp.writeFile(path.join(adminViewDir, "data.ts"), coreDataSource
|
|
1375
|
+
? buildCoreDataAdminViewDataSource(adminViewSlug, coreDataSource)
|
|
1376
|
+
: restResource
|
|
1377
|
+
? buildRestAdminViewDataSource(adminViewSlug, restResource)
|
|
1378
|
+
: buildDefaultAdminViewDataSource(adminViewSlug), "utf8");
|
|
1379
|
+
await fsp.writeFile(path.join(adminViewDir, "Screen.tsx"), coreDataSource
|
|
1380
|
+
? buildCoreDataAdminViewScreenSource(adminViewSlug, workspace.workspace.textDomain)
|
|
1381
|
+
: buildAdminViewScreenSource(adminViewSlug, workspace.workspace.textDomain), "utf8");
|
|
855
1382
|
await fsp.writeFile(path.join(adminViewDir, "index.tsx"), buildAdminViewEntrySource(adminViewSlug), "utf8");
|
|
856
1383
|
await fsp.writeFile(path.join(adminViewDir, "style.scss"), buildAdminViewStyleSource(), "utf8");
|
|
857
1384
|
await fsp.writeFile(adminViewPhpPath, buildAdminViewPhpSource(adminViewSlug, workspace), "utf8");
|
|
@@ -862,7 +1389,9 @@ export async function runAddAdminViewCommand({ adminViewName, cwd = process.cwd(
|
|
|
862
1389
|
return {
|
|
863
1390
|
adminViewSlug,
|
|
864
1391
|
projectDir: workspace.projectDir,
|
|
865
|
-
source: parsedSource
|
|
1392
|
+
source: parsedSource
|
|
1393
|
+
? formatAdminViewSourceLocator(parsedSource)
|
|
1394
|
+
: undefined,
|
|
866
1395
|
};
|
|
867
1396
|
}
|
|
868
1397
|
catch (error) {
|