@wp-typia/project-tools 0.16.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. package/dist/runtime/cli-help.js +1 -1
  2. package/dist/runtime/scaffold.js +21 -13
  3. package/package.json +2 -2
  4. package/templates/_shared/compound/core/scripts/add-compound-child.ts.mustache +42 -28
  5. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/interactivity.ts.mustache +8 -0
  6. package/templates/_shared/compound/persistence-auth/{{slugKebabCase}}.php.mustache +5 -5
  7. package/templates/_shared/compound/persistence-public/{{slugKebabCase}}.php.mustache +5 -5
  8. package/templates/_shared/persistence/auth/{{slugKebabCase}}.php.mustache +5 -5
  9. package/templates/_shared/persistence/core/src/interactivity.ts.mustache +5 -0
  10. package/templates/_shared/persistence/core/{{slugKebabCase}}.php.mustache +5 -5
  11. package/templates/_shared/persistence/public/{{slugKebabCase}}.php.mustache +5 -5
  12. package/templates/_shared/workspace/persistence-auth/server.php.mustache +7 -5
  13. package/templates/_shared/workspace/persistence-public/server.php.mustache +7 -5
  14. package/templates/compound/src/blocks/{{slugKebabCase}}/types.ts.mustache +5 -0
  15. package/templates/compound/src/blocks/{{slugKebabCase}}/validators.ts.mustache +10 -3
  16. package/templates/compound/src/blocks/{{slugKebabCase}}-item/types.ts.mustache +5 -0
  17. package/templates/compound/src/blocks/{{slugKebabCase}}-item/validators.ts.mustache +10 -3
  18. package/templates/interactivity/src/edit.tsx.mustache +1 -1
  19. package/templates/interactivity/src/save.tsx.mustache +1 -1
  20. package/templates/persistence/src/edit.tsx.mustache +2 -2
@@ -34,7 +34,7 @@ Package managers: ${PACKAGE_MANAGER_IDS.join(", ")}
34
34
  Notes:
35
35
  \`wp-typia create\` is the canonical scaffold command.
36
36
  \`wp-typia <project-dir>\` remains a backward-compatible alias to \`create\`.
37
- Use \`--template @wp-typia/create-workspace-template\` for the official empty workspace scaffold behind \`wp-typia add ...\`.
37
+ Use \`--template workspace\` as shorthand for \`@wp-typia/create-workspace-template\`, the official empty workspace scaffold behind \`wp-typia add ...\`.
38
38
  \`add variation\` uses an existing workspace block from \`scripts/block-config.ts\`.
39
39
  \`add pattern\` scaffolds a namespaced PHP pattern shell under \`src/patterns/\`.
40
40
  \`add binding-source\` scaffolds shared PHP and editor registration under \`src/bindings/\`.
@@ -19,6 +19,7 @@ const BLOCK_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/;
19
19
  const PHP_PREFIX_PATTERN = /^[a-z_][a-z0-9_]*$/;
20
20
  const PHP_PREFIX_MAX_LENGTH = 50;
21
21
  const OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE = "@wp-typia/create-workspace-template";
22
+ const WORKSPACE_TEMPLATE_ALIAS = "workspace";
22
23
  const EPHEMERAL_NODE_MODULES_LINK_TYPE = process.platform === "win32" ? "junction" : "dir";
23
24
  const LOCKFILES = {
24
25
  bun: ["bun.lock", "bun.lockb"],
@@ -138,15 +139,21 @@ export function getDefaultAnswers(projectName, templateId) {
138
139
  title: toTitleCase(slugDefault),
139
140
  };
140
141
  }
142
+ function normalizeTemplateSelection(templateId) {
143
+ return templateId === WORKSPACE_TEMPLATE_ALIAS
144
+ ? OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE
145
+ : templateId;
146
+ }
141
147
  export async function resolveTemplateId({ templateId, yes = false, isInteractive = false, selectTemplate, }) {
142
148
  if (templateId) {
149
+ const normalizedTemplateId = normalizeTemplateSelection(templateId);
143
150
  if (isRemovedBuiltInTemplateId(templateId)) {
144
151
  throw new Error(getRemovedBuiltInTemplateMessage(templateId));
145
152
  }
146
- if (isBuiltInTemplateId(templateId)) {
147
- return getTemplateById(templateId).id;
153
+ if (isBuiltInTemplateId(normalizedTemplateId)) {
154
+ return getTemplateById(normalizedTemplateId).id;
148
155
  }
149
- return templateId;
156
+ return normalizedTemplateId;
150
157
  }
151
158
  if (yes) {
152
159
  return "basic";
@@ -154,7 +161,7 @@ export async function resolveTemplateId({ templateId, yes = false, isInteractive
154
161
  if (!isInteractive || !selectTemplate) {
155
162
  throw new Error(`Template is required in non-interactive mode. Use --template <${TEMPLATE_IDS.join("|")}|./path|github:owner/repo/path[#ref]|npm-package>.`);
156
163
  }
157
- return selectTemplate();
164
+ return normalizeTemplateSelection(await selectTemplate());
158
165
  }
159
166
  export async function resolvePackageManagerId({ packageManager, yes = false, isInteractive = false, selectPackageManager, }) {
160
167
  if (packageManager) {
@@ -628,14 +635,15 @@ async function applyWorkspaceMigrationCapability(projectDir, packageManager) {
628
635
  writeInitialMigrationScaffold(projectDir, "v1", []);
629
636
  }
630
637
  export async function scaffoldProject({ projectDir, templateId, answers, dataStorageMode, persistencePolicy, packageManager, cwd = process.cwd(), allowExistingDir = false, noInstall = false, installDependencies = undefined, variant, withMigrationUi = false, withTestPreset = false, withWpEnv = false, }) {
638
+ const resolvedTemplateId = normalizeTemplateSelection(templateId);
631
639
  const resolvedPackageManager = getPackageManager(packageManager).id;
632
- const isBuiltInTemplate = isBuiltInTemplateId(templateId);
633
- const variables = getTemplateVariables(templateId, {
640
+ const isBuiltInTemplate = isBuiltInTemplateId(resolvedTemplateId);
641
+ const variables = getTemplateVariables(resolvedTemplateId, {
634
642
  ...answers,
635
643
  dataStorageMode: dataStorageMode ?? answers.dataStorageMode,
636
644
  persistencePolicy: persistencePolicy ?? answers.persistencePolicy,
637
645
  });
638
- const templateSource = await resolveTemplateSource(templateId, cwd, variables, variant);
646
+ const templateSource = await resolveTemplateSource(resolvedTemplateId, cwd, variables, variant);
639
647
  const supportsMigrationUi = isBuiltInTemplate || templateSource.isOfficialWorkspaceTemplate === true;
640
648
  if (withMigrationUi && !supportsMigrationUi) {
641
649
  await templateSource.cleanup?.();
@@ -652,8 +660,8 @@ export async function scaffoldProject({ projectDir, templateId, answers, dataSto
652
660
  }
653
661
  const isOfficialWorkspace = isOfficialWorkspaceProject(projectDir);
654
662
  if (isBuiltInTemplate) {
655
- await writeStarterManifestFiles(projectDir, templateId, variables);
656
- await seedBuiltInPersistenceArtifacts(projectDir, templateId, variables);
663
+ await writeStarterManifestFiles(projectDir, resolvedTemplateId, variables);
664
+ await seedBuiltInPersistenceArtifacts(projectDir, resolvedTemplateId, variables);
657
665
  await applyLocalDevPresetFiles({
658
666
  projectDir,
659
667
  variables,
@@ -664,7 +672,7 @@ export async function scaffoldProject({ projectDir, templateId, answers, dataSto
664
672
  await applyMigrationUiCapability({
665
673
  packageManager: resolvedPackageManager,
666
674
  projectDir,
667
- templateId,
675
+ templateId: resolvedTemplateId,
668
676
  variables,
669
677
  });
670
678
  }
@@ -674,7 +682,7 @@ export async function scaffoldProject({ projectDir, templateId, answers, dataSto
674
682
  }
675
683
  const readmePath = path.join(projectDir, "README.md");
676
684
  if (!fs.existsSync(readmePath)) {
677
- await fsp.writeFile(readmePath, buildReadme(templateId, variables, resolvedPackageManager, {
685
+ await fsp.writeFile(readmePath, buildReadme(resolvedTemplateId, variables, resolvedPackageManager, {
678
686
  withMigrationUi: isBuiltInTemplate || isOfficialWorkspace ? withMigrationUi : false,
679
687
  withTestPreset: isBuiltInTemplate ? withTestPreset : false,
680
688
  withWpEnv: isBuiltInTemplate ? withWpEnv : false,
@@ -691,7 +699,7 @@ export async function scaffoldProject({ projectDir, templateId, answers, dataSto
691
699
  compoundPersistenceEnabled: variables.compoundPersistenceEnabled === "true",
692
700
  packageManager: resolvedPackageManager,
693
701
  projectDir,
694
- templateId,
702
+ templateId: resolvedTemplateId,
695
703
  withTestPreset,
696
704
  withWpEnv,
697
705
  });
@@ -709,7 +717,7 @@ export async function scaffoldProject({ projectDir, templateId, answers, dataSto
709
717
  return {
710
718
  projectDir,
711
719
  selectedVariant: templateSource.selectedVariant ?? null,
712
- templateId,
720
+ templateId: resolvedTemplateId,
713
721
  packageManager: resolvedPackageManager,
714
722
  variables,
715
723
  warnings: templateSource.warnings ?? [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wp-typia/project-tools",
3
- "version": "0.16.0",
3
+ "version": "0.16.1",
4
4
  "description": "Project orchestration and programmatic tooling for wp-typia",
5
5
  "packageManager": "bun@1.3.11",
6
6
  "type": "module",
@@ -62,7 +62,7 @@
62
62
  },
63
63
  "dependencies": {
64
64
  "@wp-typia/api-client": "^0.4.2",
65
- "@wp-typia/block-runtime": "^0.4.3",
65
+ "@wp-typia/block-runtime": "^0.4.4",
66
66
  "@wp-typia/rest": "^0.3.5",
67
67
  "@wp-typia/block-types": "^0.2.1",
68
68
  "mustache": "^4.2.0",
@@ -346,8 +346,15 @@ function renderBlockJson(
346
346
  ) }\n`;
347
347
  }
348
348
 
349
- function renderTypesFile( childTypeName: string, childTitle: string ): string {
350
- return `import { tags } from 'typia';
349
+ function renderTypesFile(
350
+ childTypeName: string,
351
+ childInterfaceName: string,
352
+ childTitle: string
353
+ ): string {
354
+ return `import type { ValidationResult } from '@wp-typia/block-runtime/validation';
355
+ import { tags } from 'typia';
356
+
357
+ export type { ValidationResult } from '@wp-typia/block-runtime/validation';
351
358
 
352
359
  export interface ${ childTypeName } {
353
360
  \ttitle: string &
@@ -359,6 +366,8 @@ export interface ${ childTypeName } {
359
366
  \t\ttags.MaxLength< 280 > &
360
367
  \t\ttags.Default< ${ JSON.stringify( CHILD_PLACEHOLDER ) } >;
361
368
  }
369
+
370
+ export type ${ childInterfaceName }ValidationResult = ValidationResult< ${ childTypeName } >;
362
371
  `;
363
372
  }
364
373
 
@@ -407,36 +416,37 @@ function renderValidatorsFile(
407
416
  ): string {
408
417
  return `import typia from 'typia';
409
418
  import currentManifest from './typia.manifest.json';
410
- import {
411
- \ttype ManifestDefaultsDocument,
412
- } from '@wp-typia/block-runtime/defaults';
413
- import {
414
- \tcreateScaffoldValidatorToolkit,
415
- } from '@wp-typia/block-runtime/validation';
416
-
417
- import type { ${ childTypeName } } from './types';
418
-
419
- const validate = typia.createValidate< ${ childTypeName } >();
420
- const assert = typia.createAssert< ${ childTypeName } >();
421
- const is = typia.createIs< ${ childTypeName } >();
422
- const random = typia.createRandom< ${ childTypeName } >();
423
- const clone = typia.misc.createClone< ${ childTypeName } >();
424
- const prune = typia.misc.createPrune< ${ childTypeName } >();
425
- const scaffoldValidators = createScaffoldValidatorToolkit< ${ childTypeName } >( {
426
- \tmanifest: currentManifest as ManifestDefaultsDocument,
427
- \tvalidate,
428
- \tassert,
429
- \tis,
430
- \trandom,
431
- \tclone,
432
- \tprune,
419
+ import type {
420
+ \t${ childTypeName },
421
+ \t${ childInterfaceName }ValidationResult,
422
+ } from './types';
423
+ import { createTemplateValidatorToolkit } from '../../validator-toolkit';
424
+
425
+ const scaffoldValidators = createTemplateValidatorToolkit< ${ childTypeName } >( {
426
+ \tassert: typia.createAssert< ${ childTypeName } >(),
427
+ \tclone: typia.misc.createClone< ${ childTypeName } >() as (
428
+ \t\tvalue: ${ childTypeName },
429
+ \t) => ${ childTypeName },
430
+ \tis: typia.createIs< ${ childTypeName } >(),
431
+ \tmanifest: currentManifest,
432
+ \tprune: typia.misc.createPrune< ${ childTypeName } >(),
433
+ \trandom: typia.createRandom< ${ childTypeName } >() as (
434
+ \t\t...args: unknown[]
435
+ \t) => ${ childTypeName },
436
+ \tvalidate: typia.createValidate< ${ childTypeName } >(),
433
437
  } );
434
438
 
435
- export const validate${ childInterfaceName } = scaffoldValidators.validateAttributes;
439
+ export const validate${ childInterfaceName } =
440
+ \tscaffoldValidators.validateAttributes as (
441
+ \t\tattributes: unknown
442
+ \t) => ${ childInterfaceName }ValidationResult;
436
443
 
437
444
  export const validators = scaffoldValidators.validators;
438
445
 
439
- export const sanitize${ childInterfaceName } = scaffoldValidators.sanitizeAttributes;
446
+ export const sanitize${ childInterfaceName } =
447
+ \tscaffoldValidators.sanitizeAttributes as (
448
+ \t\tattributes: Partial< ${ childTypeName } >
449
+ \t) => ${ childTypeName };
440
450
 
441
451
  export const createAttributeUpdater = scaffoldValidators.createAttributeUpdater;
442
452
  `;
@@ -605,7 +615,11 @@ function main() {
605
615
  renderBlockJson( childBlockName, childFolderSlug, childTitle ),
606
616
  'utf8'
607
617
  );
608
- fs.writeFileSync( path.join( childDir, 'types.ts' ), renderTypesFile( childTypeName, childTitle ), 'utf8' );
618
+ fs.writeFileSync(
619
+ path.join( childDir, 'types.ts' ),
620
+ renderTypesFile( childTypeName, childInterfaceName, childTitle ),
621
+ 'utf8'
622
+ );
609
623
  fs.writeFileSync(
610
624
  path.join( childDir, 'typia.manifest.json' ),
611
625
  renderStarterManifestFile( childTypeName, childTitle ),
@@ -123,6 +123,8 @@ const { actions, state } = store( '{{slugKebabCase}}', {
123
123
  let bootstrapSucceeded = false;
124
124
  let lastBootstrapError =
125
125
  'Unable to initialize write access';
126
+ const includePublicWriteCredentials = {{isPublicPersistencePolicy}};
127
+ const includeRestNonce = {{isAuthenticatedPersistencePolicy}};
126
128
 
127
129
  for ( let attempt = 1; attempt <= BOOTSTRAP_MAX_ATTEMPTS; attempt += 1 ) {
128
130
  try {
@@ -146,16 +148,22 @@ const { actions, state } = store( '{{slugKebabCase}}', {
146
148
  }
147
149
 
148
150
  clientState.writeExpiry =
151
+ includePublicWriteCredentials &&
152
+ 'publicWriteExpiresAt' in result.data &&
149
153
  typeof result.data.publicWriteExpiresAt === 'number' &&
150
154
  result.data.publicWriteExpiresAt > 0
151
155
  ? result.data.publicWriteExpiresAt
152
156
  : 0;
153
157
  clientState.writeToken =
158
+ includePublicWriteCredentials &&
159
+ 'publicWriteToken' in result.data &&
154
160
  typeof result.data.publicWriteToken === 'string' &&
155
161
  result.data.publicWriteToken.length > 0
156
162
  ? result.data.publicWriteToken
157
163
  : '';
158
164
  clientState.writeNonce =
165
+ includeRestNonce &&
166
+ 'restNonce' in result.data &&
159
167
  typeof result.data.restNonce === 'string' &&
160
168
  result.data.restNonce.length > 0
161
169
  ? result.data.restNonce
@@ -79,7 +79,7 @@ function {{phpPrefix}}_with_counter_lock( $post_id, $resource_key, $callback ) {
79
79
  }
80
80
 
81
81
  function {{phpPrefix}}_maybe_install_storage() {
82
- if ( 'custom-table' !== '{{dataStorageMode}}' ) {
82
+ if ( 'custom-table' !== {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
83
83
  return;
84
84
  }
85
85
 
@@ -110,7 +110,7 @@ function {{phpPrefix}}_maybe_install_storage() {
110
110
  }
111
111
 
112
112
  function {{phpPrefix}}_ensure_storage_installed() {
113
- if ( 'custom-table' === '{{dataStorageMode}}' && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
113
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
114
114
  {{phpPrefix}}_maybe_install_storage();
115
115
  }
116
116
  }
@@ -122,7 +122,7 @@ function {{phpPrefix}}_get_rest_build_dir() {
122
122
  function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
123
123
  global $wpdb;
124
124
 
125
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
125
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
126
126
  $table_name = {{phpPrefix}}_get_counter_table_name();
127
127
  $count = $wpdb->get_var(
128
128
  $wpdb->prepare(
@@ -144,7 +144,7 @@ function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
144
144
  function {{phpPrefix}}_increment_counter( $post_id, $resource_key, $delta ) {
145
145
  global $wpdb;
146
146
 
147
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
147
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
148
148
  $table_name = {{phpPrefix}}_get_counter_table_name();
149
149
  $delta_value = (int) $delta;
150
150
  $initial_count = max( 0, $delta_value );
@@ -188,7 +188,7 @@ function {{phpPrefix}}_build_state_response( $post_id, $resource_key, $count ) {
188
188
  'postId' => (int) $post_id,
189
189
  'resourceKey' => (string) $resource_key,
190
190
  'count' => (int) $count,
191
- 'storage' => '{{dataStorageMode}}',
191
+ 'storage' => {{phpPrefixUpper}}_DATA_STORAGE_MODE,
192
192
  );
193
193
  }
194
194
 
@@ -82,7 +82,7 @@ function {{phpPrefix}}_with_counter_lock( $post_id, $resource_key, $callback ) {
82
82
  }
83
83
 
84
84
  function {{phpPrefix}}_maybe_install_storage() {
85
- if ( 'custom-table' !== '{{dataStorageMode}}' ) {
85
+ if ( 'custom-table' !== {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
86
86
  return;
87
87
  }
88
88
 
@@ -113,7 +113,7 @@ function {{phpPrefix}}_maybe_install_storage() {
113
113
  }
114
114
 
115
115
  function {{phpPrefix}}_ensure_storage_installed() {
116
- if ( 'custom-table' === '{{dataStorageMode}}' && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
116
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
117
117
  {{phpPrefix}}_maybe_install_storage();
118
118
  }
119
119
  }
@@ -125,7 +125,7 @@ function {{phpPrefix}}_get_rest_build_dir() {
125
125
  function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
126
126
  global $wpdb;
127
127
 
128
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
128
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
129
129
  $table_name = {{phpPrefix}}_get_counter_table_name();
130
130
  $count = $wpdb->get_var(
131
131
  $wpdb->prepare(
@@ -147,7 +147,7 @@ function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
147
147
  function {{phpPrefix}}_increment_counter( $post_id, $resource_key, $delta ) {
148
148
  global $wpdb;
149
149
 
150
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
150
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
151
151
  $table_name = {{phpPrefix}}_get_counter_table_name();
152
152
  $delta_value = (int) $delta;
153
153
  $initial_count = max( 0, $delta_value );
@@ -191,7 +191,7 @@ function {{phpPrefix}}_build_state_response( $post_id, $resource_key, $count ) {
191
191
  'postId' => (int) $post_id,
192
192
  'resourceKey' => (string) $resource_key,
193
193
  'count' => (int) $count,
194
- 'storage' => '{{dataStorageMode}}',
194
+ 'storage' => {{phpPrefixUpper}}_DATA_STORAGE_MODE,
195
195
  );
196
196
  }
197
197
 
@@ -84,7 +84,7 @@ function {{phpPrefix}}_with_counter_lock( $post_id, $resource_key, $callback ) {
84
84
  }
85
85
 
86
86
  function {{phpPrefix}}_maybe_install_storage() {
87
- if ( 'custom-table' !== '{{dataStorageMode}}' ) {
87
+ if ( 'custom-table' !== {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
88
88
  return;
89
89
  }
90
90
 
@@ -115,7 +115,7 @@ function {{phpPrefix}}_maybe_install_storage() {
115
115
  }
116
116
 
117
117
  function {{phpPrefix}}_ensure_storage_installed() {
118
- if ( 'custom-table' === '{{dataStorageMode}}' && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
118
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
119
119
  {{phpPrefix}}_maybe_install_storage();
120
120
  }
121
121
  }
@@ -127,7 +127,7 @@ function {{phpPrefix}}_get_rest_build_dir() {
127
127
  function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
128
128
  global $wpdb;
129
129
 
130
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
130
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
131
131
  $table_name = {{phpPrefix}}_get_counter_table_name();
132
132
  $count = $wpdb->get_var(
133
133
  $wpdb->prepare(
@@ -149,7 +149,7 @@ function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
149
149
  function {{phpPrefix}}_increment_counter( $post_id, $resource_key, $delta ) {
150
150
  global $wpdb;
151
151
 
152
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
152
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
153
153
  $table_name = {{phpPrefix}}_get_counter_table_name();
154
154
  $delta_value = (int) $delta;
155
155
  $initial_count = max( 0, $delta_value );
@@ -193,7 +193,7 @@ function {{phpPrefix}}_build_state_response( $post_id, $resource_key, $count ) {
193
193
  'postId' => (int) $post_id,
194
194
  'resourceKey' => (string) $resource_key,
195
195
  'count' => (int) $count,
196
- 'storage' => '{{dataStorageMode}}',
196
+ 'storage' => {{phpPrefixUpper}}_DATA_STORAGE_MODE,
197
197
  );
198
198
  }
199
199
 
@@ -126,6 +126,7 @@ const { actions, state } = store( '{{slugKebabCase}}', {
126
126
  let bootstrapSucceeded = false;
127
127
  let lastBootstrapError =
128
128
  'Unable to initialize write access';
129
+ const includePublicWriteCredentials = {{isPublicPersistencePolicy}};
129
130
  const includeRestNonce = {{isAuthenticatedPersistencePolicy}};
130
131
 
131
132
  for ( let attempt = 1; attempt <= BOOTSTRAP_MAX_ATTEMPTS; attempt += 1 ) {
@@ -150,11 +151,15 @@ const { actions, state } = store( '{{slugKebabCase}}', {
150
151
  }
151
152
 
152
153
  clientState.writeExpiry =
154
+ includePublicWriteCredentials &&
155
+ 'publicWriteExpiresAt' in result.data &&
153
156
  typeof result.data.publicWriteExpiresAt === 'number' &&
154
157
  result.data.publicWriteExpiresAt > 0
155
158
  ? result.data.publicWriteExpiresAt
156
159
  : 0;
157
160
  clientState.writeToken =
161
+ includePublicWriteCredentials &&
162
+ 'publicWriteToken' in result.data &&
158
163
  typeof result.data.publicWriteToken === 'string' &&
159
164
  result.data.publicWriteToken.length > 0
160
165
  ? result.data.publicWriteToken
@@ -81,7 +81,7 @@ function {{phpPrefix}}_with_counter_lock( $post_id, $resource_key, $callback ) {
81
81
  }
82
82
 
83
83
  function {{phpPrefix}}_maybe_install_storage() {
84
- if ( 'custom-table' !== '{{dataStorageMode}}' ) {
84
+ if ( 'custom-table' !== {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
85
85
  return;
86
86
  }
87
87
 
@@ -112,7 +112,7 @@ function {{phpPrefix}}_maybe_install_storage() {
112
112
  }
113
113
 
114
114
  function {{phpPrefix}}_ensure_storage_installed() {
115
- if ( 'custom-table' === '{{dataStorageMode}}' && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
115
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
116
116
  {{phpPrefix}}_maybe_install_storage();
117
117
  }
118
118
  }
@@ -170,7 +170,7 @@ function {{phpPrefix}}_validate_and_sanitize_request( $value, $schema_name, $par
170
170
  function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
171
171
  global $wpdb;
172
172
 
173
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
173
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
174
174
  $table_name = {{phpPrefix}}_get_counter_table_name();
175
175
  $count = $wpdb->get_var(
176
176
  $wpdb->prepare(
@@ -191,7 +191,7 @@ function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
191
191
  function {{phpPrefix}}_increment_counter( $post_id, $resource_key, $delta ) {
192
192
  global $wpdb;
193
193
 
194
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
194
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
195
195
  $table_name = {{phpPrefix}}_get_counter_table_name();
196
196
  $delta_value = (int) $delta;
197
197
  $initial_count = max( 0, $delta_value );
@@ -235,7 +235,7 @@ function {{phpPrefix}}_build_state_response( $post_id, $resource_key, $count ) {
235
235
  'postId' => (int) $post_id,
236
236
  'resourceKey' => (string) $resource_key,
237
237
  'count' => (int) $count,
238
- 'storage' => '{{dataStorageMode}}',
238
+ 'storage' => {{phpPrefixUpper}}_DATA_STORAGE_MODE,
239
239
  );
240
240
  }
241
241
 
@@ -87,7 +87,7 @@ function {{phpPrefix}}_with_counter_lock( $post_id, $resource_key, $callback ) {
87
87
  }
88
88
 
89
89
  function {{phpPrefix}}_maybe_install_storage() {
90
- if ( 'custom-table' !== '{{dataStorageMode}}' ) {
90
+ if ( 'custom-table' !== {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
91
91
  return;
92
92
  }
93
93
 
@@ -118,7 +118,7 @@ function {{phpPrefix}}_maybe_install_storage() {
118
118
  }
119
119
 
120
120
  function {{phpPrefix}}_ensure_storage_installed() {
121
- if ( 'custom-table' === '{{dataStorageMode}}' && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
121
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
122
122
  {{phpPrefix}}_maybe_install_storage();
123
123
  }
124
124
  }
@@ -130,7 +130,7 @@ function {{phpPrefix}}_get_rest_build_dir() {
130
130
  function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
131
131
  global $wpdb;
132
132
 
133
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
133
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
134
134
  $table_name = {{phpPrefix}}_get_counter_table_name();
135
135
  $count = $wpdb->get_var(
136
136
  $wpdb->prepare(
@@ -152,7 +152,7 @@ function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
152
152
  function {{phpPrefix}}_increment_counter( $post_id, $resource_key, $delta ) {
153
153
  global $wpdb;
154
154
 
155
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
155
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
156
156
  $table_name = {{phpPrefix}}_get_counter_table_name();
157
157
  $delta_value = (int) $delta;
158
158
  $initial_count = max( 0, $delta_value );
@@ -196,7 +196,7 @@ function {{phpPrefix}}_build_state_response( $post_id, $resource_key, $count ) {
196
196
  'postId' => (int) $post_id,
197
197
  'resourceKey' => (string) $resource_key,
198
198
  'count' => (int) $count,
199
- 'storage' => '{{dataStorageMode}}',
199
+ 'storage' => {{phpPrefixUpper}}_DATA_STORAGE_MODE,
200
200
  );
201
201
  }
202
202
 
@@ -7,6 +7,8 @@ if ( ! defined( 'ABSPATH' ) ) {
7
7
  require_once __DIR__ . '/inc/rest-shared.php';
8
8
  require_once __DIR__ . '/inc/rest-auth.php';
9
9
 
10
+ define( '{{phpPrefixUpper}}_DATA_STORAGE_MODE', '{{dataStorageMode}}' );
11
+
10
12
  function {{phpPrefix}}_get_rest_build_dir() {
11
13
  return dirname( __DIR__, 3 ) . '/build/blocks/{{slugKebabCase}}';
12
14
  }
@@ -50,7 +52,7 @@ function {{phpPrefix}}_with_counter_lock( $post_id, $resource_key, $callback ) {
50
52
  }
51
53
 
52
54
  function {{phpPrefix}}_maybe_install_storage() {
53
- if ( 'custom-table' !== '{{dataStorageMode}}' ) {
55
+ if ( 'custom-table' !== {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
54
56
  return;
55
57
  }
56
58
 
@@ -81,7 +83,7 @@ function {{phpPrefix}}_maybe_install_storage() {
81
83
  }
82
84
 
83
85
  function {{phpPrefix}}_ensure_storage_installed() {
84
- if ( 'custom-table' === '{{dataStorageMode}}' && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
86
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
85
87
  {{phpPrefix}}_maybe_install_storage();
86
88
  }
87
89
  }
@@ -89,7 +91,7 @@ function {{phpPrefix}}_ensure_storage_installed() {
89
91
  function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
90
92
  global $wpdb;
91
93
 
92
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
94
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
93
95
  $table_name = {{phpPrefix}}_get_counter_table_name();
94
96
  $count = $wpdb->get_var(
95
97
  $wpdb->prepare(
@@ -110,7 +112,7 @@ function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
110
112
  function {{phpPrefix}}_increment_counter( $post_id, $resource_key, $delta ) {
111
113
  global $wpdb;
112
114
 
113
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
115
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
114
116
  $table_name = {{phpPrefix}}_get_counter_table_name();
115
117
  $delta_value = (int) $delta;
116
118
  $initial_count = max( 0, $delta_value );
@@ -154,7 +156,7 @@ function {{phpPrefix}}_build_state_response( $post_id, $resource_key, $count ) {
154
156
  'postId' => (int) $post_id,
155
157
  'resourceKey' => (string) $resource_key,
156
158
  'count' => (int) $count,
157
- 'storage' => '{{dataStorageMode}}',
159
+ 'storage' => {{phpPrefixUpper}}_DATA_STORAGE_MODE,
158
160
  );
159
161
  }
160
162
 
@@ -7,6 +7,8 @@ if ( ! defined( 'ABSPATH' ) ) {
7
7
  require_once __DIR__ . '/inc/rest-shared.php';
8
8
  require_once __DIR__ . '/inc/rest-public.php';
9
9
 
10
+ define( '{{phpPrefixUpper}}_DATA_STORAGE_MODE', '{{dataStorageMode}}' );
11
+
10
12
  function {{phpPrefix}}_get_rest_build_dir() {
11
13
  return dirname( __DIR__, 3 ) . '/build/blocks/{{slugKebabCase}}';
12
14
  }
@@ -50,7 +52,7 @@ function {{phpPrefix}}_with_counter_lock( $post_id, $resource_key, $callback ) {
50
52
  }
51
53
 
52
54
  function {{phpPrefix}}_maybe_install_storage() {
53
- if ( 'custom-table' !== '{{dataStorageMode}}' ) {
55
+ if ( 'custom-table' !== {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
54
56
  return;
55
57
  }
56
58
 
@@ -81,7 +83,7 @@ function {{phpPrefix}}_maybe_install_storage() {
81
83
  }
82
84
 
83
85
  function {{phpPrefix}}_ensure_storage_installed() {
84
- if ( 'custom-table' === '{{dataStorageMode}}' && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
86
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE && '1.0.0' !== get_option( '{{phpPrefix}}_storage_version', '' ) ) {
85
87
  {{phpPrefix}}_maybe_install_storage();
86
88
  }
87
89
  }
@@ -89,7 +91,7 @@ function {{phpPrefix}}_ensure_storage_installed() {
89
91
  function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
90
92
  global $wpdb;
91
93
 
92
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
94
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
93
95
  $table_name = {{phpPrefix}}_get_counter_table_name();
94
96
  $count = $wpdb->get_var(
95
97
  $wpdb->prepare(
@@ -110,7 +112,7 @@ function {{phpPrefix}}_get_counter( $post_id, $resource_key ) {
110
112
  function {{phpPrefix}}_increment_counter( $post_id, $resource_key, $delta ) {
111
113
  global $wpdb;
112
114
 
113
- if ( 'custom-table' === '{{dataStorageMode}}' ) {
115
+ if ( 'custom-table' === {{phpPrefixUpper}}_DATA_STORAGE_MODE ) {
114
116
  $table_name = {{phpPrefix}}_get_counter_table_name();
115
117
  $delta_value = (int) $delta;
116
118
  $initial_count = max( 0, $delta_value );
@@ -154,7 +156,7 @@ function {{phpPrefix}}_build_state_response( $post_id, $resource_key, $count ) {
154
156
  'postId' => (int) $post_id,
155
157
  'resourceKey' => (string) $resource_key,
156
158
  'count' => (int) $count,
157
- 'storage' => '{{dataStorageMode}}',
159
+ 'storage' => {{phpPrefixUpper}}_DATA_STORAGE_MODE,
158
160
  );
159
161
  }
160
162
 
@@ -1,5 +1,8 @@
1
+ import type { ValidationResult } from '@wp-typia/block-runtime/validation';
1
2
  import { tags } from 'typia';
2
3
 
4
+ export type { ValidationResult } from '@wp-typia/block-runtime/validation';
5
+
3
6
  export interface {{pascalCase}}Attributes {
4
7
  heading: string &
5
8
  tags.MinLength< 1 > &
@@ -11,3 +14,5 @@ export interface {{pascalCase}}Attributes {
11
14
  tags.Default< 'Add and reorder internal items inside this compound block.' >;
12
15
  showDividers?: boolean & tags.Default< true >;
13
16
  }
17
+
18
+ export type {{pascalCase}}ValidationResult = ValidationResult< {{pascalCase}}Attributes >;
@@ -1,6 +1,9 @@
1
1
  import typia from 'typia';
2
2
  import currentManifest from './typia.manifest.json';
3
- import type { {{pascalCase}}Attributes } from './types';
3
+ import type {
4
+ {{pascalCase}}Attributes,
5
+ {{pascalCase}}ValidationResult,
6
+ } from './types';
4
7
  import { createTemplateValidatorToolkit } from '../../validator-toolkit';
5
8
 
6
9
  const scaffoldValidators = createTemplateValidatorToolkit< {{pascalCase}}Attributes >( {
@@ -18,11 +21,15 @@ const scaffoldValidators = createTemplateValidatorToolkit< {{pascalCase}}Attribu
18
21
  } );
19
22
 
20
23
  export const validate{{pascalCase}}Attributes =
21
- scaffoldValidators.validateAttributes;
24
+ scaffoldValidators.validateAttributes as (
25
+ attributes: unknown
26
+ ) => {{pascalCase}}ValidationResult;
22
27
 
23
28
  export const validators = scaffoldValidators.validators;
24
29
 
25
30
  export const sanitize{{pascalCase}}Attributes =
26
- scaffoldValidators.sanitizeAttributes;
31
+ scaffoldValidators.sanitizeAttributes as (
32
+ attributes: Partial< {{pascalCase}}Attributes >
33
+ ) => {{pascalCase}}Attributes;
27
34
 
28
35
  export const createAttributeUpdater = scaffoldValidators.createAttributeUpdater;
@@ -1,5 +1,8 @@
1
+ import type { ValidationResult } from '@wp-typia/block-runtime/validation';
1
2
  import { tags } from 'typia';
2
3
 
4
+ export type { ValidationResult } from '@wp-typia/block-runtime/validation';
5
+
3
6
  export interface {{pascalCase}}ItemAttributes {
4
7
  title: string &
5
8
  tags.MinLength< 1 > &
@@ -10,3 +13,5 @@ export interface {{pascalCase}}ItemAttributes {
10
13
  tags.MaxLength< 280 > &
11
14
  tags.Default< 'Add supporting details for this internal item.' >;
12
15
  }
16
+
17
+ export type {{pascalCase}}ItemValidationResult = ValidationResult< {{pascalCase}}ItemAttributes >;
@@ -1,6 +1,9 @@
1
1
  import typia from 'typia';
2
2
  import currentManifest from './typia.manifest.json';
3
- import type { {{pascalCase}}ItemAttributes } from './types';
3
+ import type {
4
+ {{pascalCase}}ItemAttributes,
5
+ {{pascalCase}}ItemValidationResult,
6
+ } from './types';
4
7
  import { createTemplateValidatorToolkit } from '../../validator-toolkit';
5
8
 
6
9
  const scaffoldValidators = createTemplateValidatorToolkit< {{pascalCase}}ItemAttributes >( {
@@ -18,11 +21,15 @@ const scaffoldValidators = createTemplateValidatorToolkit< {{pascalCase}}ItemAtt
18
21
  } );
19
22
 
20
23
  export const validate{{pascalCase}}ItemAttributes =
21
- scaffoldValidators.validateAttributes;
24
+ scaffoldValidators.validateAttributes as (
25
+ attributes: unknown
26
+ ) => {{pascalCase}}ItemValidationResult;
22
27
 
23
28
  export const validators = scaffoldValidators.validators;
24
29
 
25
30
  export const sanitize{{pascalCase}}ItemAttributes =
26
- scaffoldValidators.sanitizeAttributes;
31
+ scaffoldValidators.sanitizeAttributes as (
32
+ attributes: Partial< {{pascalCase}}ItemAttributes >
33
+ ) => {{pascalCase}}ItemAttributes;
27
34
 
28
35
  export const createAttributeUpdater = scaffoldValidators.createAttributeUpdater;
@@ -258,7 +258,7 @@ export default function Edit({ attributes, setAttributes, isSelected }: {
258
258
  {animation !== 'none' && (
259
259
  <div
260
260
  className={`{{cssClassName}}__animation ${attributes.isAnimating ? 'is-active' : ''}`}
261
- data-wp-class="is-active"
261
+ data-wp-class--is-active="state.isAnimating"
262
262
  >
263
263
  {animation}
264
264
  </div>
@@ -70,7 +70,7 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
70
70
  <div
71
71
  className={`{{cssClassName}}__animation ${attributes.animation}`}
72
72
  aria-hidden="true"
73
- data-wp-class="is-active"
73
+ data-wp-class--is-active="state.isAnimating"
74
74
  />
75
75
 
76
76
  {attributes.maxClicks > 0 && (
@@ -66,7 +66,7 @@ export default function Edit( {
66
66
  validateEditorUpdate
67
67
  );
68
68
  const alignmentValue = editorFields.getStringValue(
69
- attributes as unknown as Record< string, unknown >,
69
+ attributes,
70
70
  'alignment',
71
71
  'left'
72
72
  );
@@ -91,7 +91,7 @@ export default function Edit( {
91
91
  </BlockControls>
92
92
  <InspectorControls>
93
93
  <InspectorFromManifest
94
- attributes={ attributes as unknown as Record< string, unknown > }
94
+ attributes={ attributes }
95
95
  fieldLookup={ editorFields }
96
96
  onChange={ updateField }
97
97
  paths={ [ 'alignment', 'isVisible', 'showCount', 'buttonLabel' ] }