@wp-typia/create-workspace-template 0.14.0 → 0.16.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/README.md CHANGED
@@ -12,6 +12,11 @@ The generated project starts with an empty `src/blocks/*` workspace shell and is
12
12
 
13
13
  ```bash
14
14
  wp-typia add block my-block --template basic
15
+ wp-typia add style callout-emphasis --block my-block
16
+ wp-typia add transform quote-to-block --from core/quote --to my-block
15
17
  wp-typia add binding-source hero-data
18
+ wp-typia add binding-source hero-data --block my-block --attribute headline
19
+ wp-typia add editor-plugin review-workflow --slot sidebar
20
+ wp-typia add editor-plugin seo-notes --slot document-setting-panel
16
21
  wp-typia add hooked-block my-block --anchor core/post-content --position after
17
22
  ```
@@ -20,11 +20,15 @@ wp-typia add block counter-card --template persistence --data-storage custom-tab
20
20
  wp-typia add block faq-stack --template compound --data-storage custom-table --persistence-policy public
21
21
  ```
22
22
 
23
- Variations and patterns can also be added after the first block exists:
23
+ Variations, block styles, transforms, patterns, and REST resources can also be
24
+ added after the first block exists:
24
25
 
25
26
  ```bash
26
27
  wp-typia add variation hero-card --block counter-card
28
+ wp-typia add style callout-emphasis --block counter-card
29
+ wp-typia add transform quote-to-counter --from core/quote --to counter-card
27
30
  wp-typia add pattern hero-layout
31
+ wp-typia add rest-resource snapshots --namespace {{namespace}}/v1 --methods list,read,create
28
32
  ```
29
33
 
30
34
  ## Development
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wp-typia/create-workspace-template",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "description": "Official empty wp-typia workspace template package",
5
5
  "packageManager": "bun@1.3.11",
6
6
  "type": "module",
@@ -29,6 +29,7 @@
29
29
  "@wp-typia/api-client": "{{apiClientPackageVersion}}",
30
30
  "@wp-typia/block-runtime": "{{blockRuntimePackageVersion}}",
31
31
  "@wp-typia/block-types": "{{blockTypesPackageVersion}}",
32
+ "@wp-typia/project-tools": "{{projectToolsPackageVersion}}",
32
33
  "@wp-typia/rest": "{{restPackageVersion}}",
33
34
  "@typia/unplugin": "^12.0.1",
34
35
  "@types/node": "^24.5.2",
@@ -36,7 +37,6 @@
36
37
  "@types/wordpress__blocks": "^12.5.18",
37
38
  "@wordpress/browserslist-config": "^6.42.0",
38
39
  "@wordpress/scripts": "^30.22.0",
39
- "ajv": "^8.18.0",
40
40
  "eslint-plugin-jsx-a11y": "^6.10.2",
41
41
  "tsx": "^4.20.5",
42
42
  "typescript": "^5.9.2",
@@ -47,8 +47,10 @@
47
47
  "@wordpress/block-editor": "^15.2.0",
48
48
  "@wordpress/blocks": "^15.2.0",
49
49
  "@wordpress/components": "^30.2.0",
50
+ "@wordpress/editor": "^14.44.0",
50
51
  "@wordpress/element": "^6.29.0",
51
52
  "@wordpress/i18n": "^6.2.0",
52
- "@wordpress/interactivity": "^6.29.0"
53
+ "@wordpress/interactivity": "^6.29.0",
54
+ "@wordpress/plugins": "^7.44.0"
53
55
  }
54
56
  }
@@ -15,17 +15,62 @@ export interface WorkspaceVariationConfig {
15
15
  slug: string;
16
16
  }
17
17
 
18
+ export interface WorkspaceBlockStyleConfig {
19
+ block: string;
20
+ file: string;
21
+ slug: string;
22
+ }
23
+
24
+ export interface WorkspaceBlockTransformConfig {
25
+ block: string;
26
+ file: string;
27
+ from: string;
28
+ slug: string;
29
+ to: string;
30
+ }
31
+
18
32
  export interface WorkspacePatternConfig {
19
33
  file: string;
20
34
  slug: string;
21
35
  }
22
36
 
23
37
  export interface WorkspaceBindingSourceConfig {
38
+ attribute?: string;
39
+ block?: string;
24
40
  editorFile: string;
25
41
  serverFile: string;
26
42
  slug: string;
27
43
  }
28
44
 
45
+ export interface WorkspaceRestResourceConfig {
46
+ apiFile: string;
47
+ clientFile: string;
48
+ dataFile: string;
49
+ methods: Array< 'list' | 'read' | 'create' | 'update' | 'delete' >;
50
+ namespace: string;
51
+ openApiFile: string;
52
+ phpFile: string;
53
+ restManifest?: ReturnType<
54
+ typeof import( '@wp-typia/block-runtime/metadata-core' ).defineEndpointManifest
55
+ >;
56
+ slug: string;
57
+ typesFile: string;
58
+ validatorsFile: string;
59
+ }
60
+
61
+ export interface WorkspaceEditorPluginConfig {
62
+ file: string;
63
+ slug: string;
64
+ slot: string;
65
+ }
66
+
67
+ export interface WorkspaceAdminViewConfig {
68
+ file: string;
69
+ phpFile: string;
70
+ slug: string;
71
+ source?: string;
72
+ }
73
+
29
74
  export const BLOCKS: WorkspaceBlockConfig[] = [
30
75
  // wp-typia add block entries
31
76
  ];
@@ -34,6 +79,14 @@ export const VARIATIONS: WorkspaceVariationConfig[] = [
34
79
  // wp-typia add variation entries
35
80
  ];
36
81
 
82
+ export const BLOCK_STYLES: WorkspaceBlockStyleConfig[] = [
83
+ // wp-typia add style entries
84
+ ];
85
+
86
+ export const BLOCK_TRANSFORMS: WorkspaceBlockTransformConfig[] = [
87
+ // wp-typia add transform entries
88
+ ];
89
+
37
90
  export const PATTERNS: WorkspacePatternConfig[] = [
38
91
  // wp-typia add pattern entries
39
92
  ];
@@ -41,3 +94,15 @@ export const PATTERNS: WorkspacePatternConfig[] = [
41
94
  export const BINDING_SOURCES: WorkspaceBindingSourceConfig[] = [
42
95
  // wp-typia add binding-source entries
43
96
  ];
97
+
98
+ export const REST_RESOURCES: WorkspaceRestResourceConfig[] = [
99
+ // wp-typia add rest-resource entries
100
+ ];
101
+
102
+ export const EDITOR_PLUGINS: WorkspaceEditorPluginConfig[] = [
103
+ // wp-typia add editor-plugin entries
104
+ ];
105
+
106
+ export const ADMIN_VIEWS: WorkspaceAdminViewConfig[] = [
107
+ // wp-typia add admin-view entries
108
+ ];
@@ -22,7 +22,14 @@ function getBlockSlugs() {
22
22
  }
23
23
 
24
24
  function hasSharedEditorEntries() {
25
- for ( const relativePath of [ 'src/bindings/index.ts', 'src/bindings/index.js' ] ) {
25
+ for ( const relativePath of [
26
+ 'src/bindings/index.ts',
27
+ 'src/bindings/index.js',
28
+ 'src/editor-plugins/index.ts',
29
+ 'src/editor-plugins/index.js',
30
+ 'src/admin-views/index.ts',
31
+ 'src/admin-views/index.js',
32
+ ] ) {
26
33
  if ( fs.existsSync( path.join( process.cwd(), relativePath ) ) ) {
27
34
  return true;
28
35
  }
@@ -8,7 +8,12 @@ import {
8
8
  syncTypeSchemas,
9
9
  } from '@wp-typia/block-runtime/metadata-core';
10
10
 
11
- import { BLOCKS, type WorkspaceBlockConfig } from './block-config';
11
+ import {
12
+ BLOCKS,
13
+ REST_RESOURCES,
14
+ type WorkspaceBlockConfig,
15
+ type WorkspaceRestResourceConfig,
16
+ } from './block-config';
12
17
 
13
18
  function parseCliOptions( argv: string[] ) {
14
19
  const options = {
@@ -42,6 +47,25 @@ function isRestEnabledBlock(
42
47
  );
43
48
  }
44
49
 
50
+ function isWorkspaceRestResource(
51
+ resource: WorkspaceRestResourceConfig
52
+ ): resource is WorkspaceRestResourceConfig & {
53
+ clientFile: string;
54
+ openApiFile: string;
55
+ restManifest: NonNullable< WorkspaceRestResourceConfig[ 'restManifest' ] >;
56
+ typesFile: string;
57
+ validatorsFile: string;
58
+ } {
59
+ return (
60
+ typeof resource.clientFile === 'string' &&
61
+ typeof resource.openApiFile === 'string' &&
62
+ typeof resource.typesFile === 'string' &&
63
+ typeof resource.validatorsFile === 'string' &&
64
+ typeof resource.restManifest === 'object' &&
65
+ resource.restManifest !== null
66
+ );
67
+ }
68
+
45
69
  async function assertTypeArtifactsCurrent( block: WorkspaceBlockConfig ) {
46
70
  const report = await runSyncBlockMetadata(
47
71
  {
@@ -73,12 +97,13 @@ async function assertTypeArtifactsCurrent( block: WorkspaceBlockConfig ) {
73
97
  async function main() {
74
98
  const options = parseCliOptions( process.argv.slice( 2 ) );
75
99
  const restBlocks = BLOCKS.filter( isRestEnabledBlock );
100
+ const restResources = REST_RESOURCES.filter( isWorkspaceRestResource );
76
101
 
77
- if ( restBlocks.length === 0 ) {
102
+ if ( restBlocks.length === 0 && restResources.length === 0 ) {
78
103
  console.log(
79
104
  options.check
80
- ? 'ℹ️ No REST-enabled workspace blocks are registered yet. `sync-rest --check` is already clean.'
81
- : 'ℹ️ No REST-enabled workspace blocks are registered yet.'
105
+ ? 'ℹ️ No REST-enabled workspace blocks or plugin-level REST resources are registered yet. `sync-rest --check` is already clean.'
106
+ : 'ℹ️ No REST-enabled workspace blocks or plugin-level REST resources are registered yet.'
82
107
  );
83
108
  return;
84
109
  }
@@ -142,10 +167,59 @@ async function main() {
142
167
  );
143
168
  }
144
169
 
170
+ for ( const resource of restResources ) {
171
+ const contracts = resource.restManifest.contracts;
172
+
173
+ for ( const [ baseName, contract ] of Object.entries( contracts ) ) {
174
+ await syncTypeSchemas(
175
+ {
176
+ jsonSchemaFile: path.join(
177
+ path.dirname( resource.typesFile ),
178
+ 'api-schemas',
179
+ `${ baseName }.schema.json`
180
+ ),
181
+ openApiFile: path.join(
182
+ path.dirname( resource.typesFile ),
183
+ 'api-schemas',
184
+ `${ baseName }.openapi.json`
185
+ ),
186
+ sourceTypeName: contract.sourceTypeName,
187
+ typesFile: resource.typesFile,
188
+ },
189
+ {
190
+ check: options.check,
191
+ }
192
+ );
193
+ }
194
+
195
+ await syncRestOpenApi(
196
+ {
197
+ manifest: resource.restManifest,
198
+ openApiFile: resource.openApiFile,
199
+ typesFile: resource.typesFile,
200
+ },
201
+ {
202
+ check: options.check,
203
+ }
204
+ );
205
+
206
+ await syncEndpointClient(
207
+ {
208
+ clientFile: resource.clientFile,
209
+ manifest: resource.restManifest,
210
+ typesFile: resource.typesFile,
211
+ validatorsFile: resource.validatorsFile,
212
+ },
213
+ {
214
+ check: options.check,
215
+ }
216
+ );
217
+ }
218
+
145
219
  console.log(
146
220
  options.check
147
- ? '✅ REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents are already up to date with the TypeScript types!'
148
- : '✅ REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents generated from TypeScript types!'
221
+ ? '✅ REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents are already up to date for workspace blocks and plugin-level resources!'
222
+ : '✅ REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents generated for workspace blocks and plugin-level resources!'
149
223
  );
150
224
  }
151
225
 
@@ -0,0 +1 @@
1
+
@@ -189,14 +189,29 @@ function getEditorEntries() {
189
189
  function getSharedEditorEntries() {
190
190
  const entries = [];
191
191
 
192
- for ( const relativePath of [ 'src/bindings/index.ts', 'src/bindings/index.js' ] ) {
193
- const entryPath = path.resolve( process.cwd(), relativePath );
194
- if ( ! fs.existsSync( entryPath ) ) {
195
- continue;
196
- }
192
+ for ( const [ entryName, candidates ] of [
193
+ [
194
+ 'bindings/index',
195
+ [ 'src/bindings/index.ts', 'src/bindings/index.js' ],
196
+ ],
197
+ [
198
+ 'editor-plugins/index',
199
+ [ 'src/editor-plugins/index.ts', 'src/editor-plugins/index.js' ],
200
+ ],
201
+ [
202
+ 'admin-views/index',
203
+ [ 'src/admin-views/index.ts', 'src/admin-views/index.js' ],
204
+ ],
205
+ ] ) {
206
+ for ( const relativePath of candidates ) {
207
+ const entryPath = path.resolve( process.cwd(), relativePath );
208
+ if ( ! fs.existsSync( entryPath ) ) {
209
+ continue;
210
+ }
197
211
 
198
- entries.push( [ 'bindings/index', entryPath ] );
199
- break;
212
+ entries.push( [ entryName, entryPath ] );
213
+ break;
214
+ }
200
215
  }
201
216
 
202
217
  return Object.fromEntries( entries );
@@ -117,6 +117,42 @@ function {{phpPrefix}}_enqueue_binding_sources_editor() {
117
117
  );
118
118
  }
119
119
 
120
+ function {{phpPrefix}}_enqueue_editor_plugins_editor() {
121
+ $script_path = __DIR__ . '/build/editor-plugins/index.js';
122
+ $asset_path = __DIR__ . '/build/editor-plugins/index.asset.php';
123
+ $style_path = __DIR__ . '/build/editor-plugins/style-index.css';
124
+ $style_rtl_path = __DIR__ . '/build/editor-plugins/style-index-rtl.css';
125
+
126
+ if ( ! file_exists( $script_path ) || ! file_exists( $asset_path ) ) {
127
+ return;
128
+ }
129
+
130
+ $asset = require $asset_path;
131
+ if ( ! is_array( $asset ) ) {
132
+ $asset = array();
133
+ }
134
+
135
+ wp_enqueue_script(
136
+ '{{slugKebabCase}}-editor-plugins',
137
+ plugins_url( 'build/editor-plugins/index.js', __FILE__ ),
138
+ isset( $asset['dependencies'] ) && is_array( $asset['dependencies'] ) ? $asset['dependencies'] : array(),
139
+ isset( $asset['version'] ) ? $asset['version'] : filemtime( $script_path ),
140
+ true
141
+ );
142
+
143
+ if ( file_exists( $style_path ) ) {
144
+ wp_enqueue_style(
145
+ '{{slugKebabCase}}-editor-plugins',
146
+ plugins_url( 'build/editor-plugins/style-index.css', __FILE__ ),
147
+ array(),
148
+ isset( $asset['version'] ) ? $asset['version'] : filemtime( $style_path )
149
+ );
150
+ if ( file_exists( $style_rtl_path ) ) {
151
+ wp_style_add_data( '{{slugKebabCase}}-editor-plugins', 'rtl', 'replace' );
152
+ }
153
+ }
154
+ }
155
+
120
156
  function {{phpPrefix}}_register_pattern_category() {
121
157
  if ( function_exists( 'register_block_pattern_category' ) ) {
122
158
  register_block_pattern_category(
@@ -143,3 +179,4 @@ add_action( 'init', '{{phpPrefix}}_register_binding_sources', 20 );
143
179
  add_action( 'init', '{{phpPrefix}}_register_pattern_category' );
144
180
  add_action( 'init', '{{phpPrefix}}_register_patterns', 20 );
145
181
  add_action( 'enqueue_block_editor_assets', '{{phpPrefix}}_enqueue_binding_sources_editor' );
182
+ add_action( 'enqueue_block_editor_assets', '{{phpPrefix}}_enqueue_editor_plugins_editor' );