@wp-typia/project-tools 0.16.4 → 0.16.6

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
@@ -8,7 +8,8 @@ Package roles:
8
8
  - `@wp-typia/project-tools` owns scaffold, add-block, migrate, template, doctor, and schema project helpers.
9
9
  It also owns the typed generator boundary via `BlockSpec` and `BlockGeneratorService`,
10
10
  plus the emitter-owned built-in structural/code path where built-in
11
- templates no longer ship structural or TS/TSX Mustache files.
11
+ templates no longer ship structural, TS/TSX, style, or block-local `render.php`
12
+ Mustache files.
12
13
  - `@wp-typia/block-runtime/*` owns generated-project runtime helpers.
13
14
  - `@wp-typia/create` is the deprecated legacy package shell.
14
15
 
@@ -40,10 +41,11 @@ import { normalizeEndpointAuthDefinition } from "@wp-typia/project-tools/schema-
40
41
  ```
41
42
 
42
43
  `BlockGeneratorService` is the additive typed orchestration boundary for built-in
43
- block scaffolds. Built-in templates no longer ship structural or TS/TSX
44
- Mustache files for built-in `types.ts`, `block.json`, or generated scaffold
45
- bodies; those files and starter `typia.manifest.json` now come from the emitter
46
- path, while styles, PHP, and the remaining non-TS scaffold files still come
47
- from Mustache-backed template copy.
44
+ block scaffolds. Built-in templates no longer ship structural, TS/TSX, style,
45
+ or block-local `render.php` Mustache files for built-in `types.ts`,
46
+ `block.json`, generated scaffold bodies, or block-local non-TS assets; those
47
+ files and starter `typia.manifest.json` now come from the emitter path, while
48
+ project bootstrap/package-manager files, sync scripts, shared REST helpers, and
49
+ the remaining non-block assets still come from Mustache-backed template copy.
48
50
 
49
51
  If you need metadata sync, editor helpers, validation helpers, or other generated-project runtime utilities, import them directly from `@wp-typia/block-runtime/*`.
@@ -1,11 +1,12 @@
1
1
  import type { ScaffoldTemplateVariables } from "./scaffold.js";
2
2
  import type { BuiltInTemplateId } from "./template-registry.js";
3
3
  /**
4
- * Emits built-in TS/TSX scaffold sources from typed block generation inputs.
4
+ * Emits built-in scaffold source files from typed block generation inputs.
5
5
  *
6
6
  * This module is intentionally internal to the runtime boundary: built-in
7
- * scaffold bodies are now derived from `ScaffoldTemplateVariables`, but the
8
- * emitter helpers themselves are not part of the public root export surface.
7
+ * scaffold bodies and adjacent emitted source files are now derived from
8
+ * `ScaffoldTemplateVariables`, but the emitter helpers themselves are not part
9
+ * of the public root export surface.
9
10
  */
10
11
  export interface BuiltInCodeArtifact {
11
12
  /**
@@ -18,11 +19,11 @@ export interface BuiltInCodeArtifact {
18
19
  source: string;
19
20
  }
20
21
  /**
21
- * Build the emitter-owned TS/TSX scaffold files for a built-in template family.
22
+ * Build the emitter-owned scaffold files for a built-in template family.
22
23
  *
23
- * These artifacts are written after template copy so built-in structural and
24
- * code files always come from the typed generator boundary rather than stale
25
- * Mustache sources.
24
+ * These artifacts are written after template copy so built-in structural,
25
+ * source, and adjacent generated files always come from the typed generator
26
+ * boundary rather than stale Mustache sources.
26
27
  */
27
28
  export declare function buildBuiltInCodeArtifacts({ templateId, variables, }: {
28
29
  templateId: BuiltInTemplateId;
@@ -1,3 +1,4 @@
1
+ import { buildBuiltInNonTsArtifacts } from "./built-in-block-non-ts-artifacts.js";
1
2
  import { renderMustacheTemplateString } from "./template-render.js";
2
3
  const SHARED_HOOKS_TEMPLATE = "import { useMemo } from '@wordpress/element';\n\nimport {\n\tcreateUseTypiaValidationHook,\n\tformatValidationError,\n\tformatValidationErrors,\n} from '@wp-typia/block-runtime/validation';\n\nexport {\n\tformatValidationError,\n\tformatValidationErrors,\n\ttype TypiaValidationError,\n\ttype ValidationResult,\n\ttype ValidationState,\n} from '@wp-typia/block-runtime/validation';\n\nexport const useTypiaValidation = createUseTypiaValidationHook( {\n\tuseMemo,\n} );\n";
3
4
  const BASIC_EDIT_TEMPLATE = "/**\n * Editor component for {{title}} Block\n */\n\nimport { BlockEditProps } from '@wordpress/blocks';\nimport {\n InspectorControls,\n RichText,\n useBlockProps,\n} from '@wordpress/block-editor';\nimport { Notice, PanelBody, TextControl } from '@wordpress/components';\nimport { __ } from '@wordpress/i18n';\nimport currentManifest from './typia.manifest.json';\nimport {\n InspectorFromManifest,\n type ManifestDocument,\n useEditorFields,\n useTypedAttributeUpdater,\n} from '@wp-typia/block-runtime/inspector';\nimport { {{pascalCase}}Attributes } from './types';\nimport {\n sanitize{{pascalCase}}Attributes,\n validate{{pascalCase}}Attributes,\n} from './validators';\nimport { useTypiaValidation } from './hooks';\n\ntype EditProps = BlockEditProps<{{pascalCase}}Attributes>;\n\nconst validationErrorItemStyle = { color: '#cc1818', fontSize: '12px' };\nconst validationListStyle = { margin: 0, paddingLeft: '1em' };\n\nfunction Edit({ attributes, setAttributes }: EditProps) {\n const isVisible = attributes.isVisible !== false;\n const blockProps = useBlockProps({\n className: `{{cssClassName}}${isVisible ? '' : ' is-hidden'}`,\n });\n const editorFields = useEditorFields(currentManifest as ManifestDocument, {\n hidden: ['id', 'schemaVersion'],\n manual: ['content'],\n labels: {\n alignment: __('Alignment', '{{textDomain}}'),\n className: __('CSS Class', '{{textDomain}}'),\n content: __('Content', '{{textDomain}}'),\n isVisible: __('Visible', '{{textDomain}}'),\n },\n });\n const classNameField = editorFields.getField('className');\n const { errorMessages, isValid } = useTypiaValidation(\n attributes,\n validate{{pascalCase}}Attributes\n );\n const validateEditorUpdate = (nextAttributes: {{pascalCase}}Attributes) => {\n try {\n return {\n data: sanitize{{pascalCase}}Attributes(nextAttributes),\n errors: [],\n isValid: true as const,\n };\n } catch {\n return validate{{pascalCase}}Attributes(nextAttributes);\n }\n };\n const { updateField } = useTypedAttributeUpdater(\n attributes,\n setAttributes,\n validateEditorUpdate\n );\n\n return (\n <>\n <InspectorControls>\n <InspectorFromManifest\n attributes={attributes}\n fieldLookup={editorFields}\n onChange={updateField}\n paths={['alignment', 'isVisible']}\n title={__('Settings', '{{textDomain}}')}\n >\n <TextControl\n label={__('Content', '{{textDomain}}')}\n value={attributes.content || ''}\n onChange={(value) => updateField('content', value)}\n help={__('Mirrors the main block content.', '{{textDomain}}')}\n />\n\n <TextControl\n label={classNameField?.label || __('CSS Class', '{{textDomain}}')}\n value={attributes.className || ''}\n onChange={(value) => updateField('className', value)}\n help={__('Add an optional CSS class name.', '{{textDomain}}')}\n />\n </InspectorFromManifest>\n\n {!isValid && (\n <PanelBody title={__('Validation Errors', '{{textDomain}}')} initialOpen>\n {errorMessages.map((error, index) => (\n <div key={index} style={validationErrorItemStyle}>\n • {error}\n </div>\n ))}\n </PanelBody>\n )}\n </InspectorControls>\n\n <div {...blockProps}>\n <div className=\"{{cssClassName}}__content\">\n <RichText\n tagName=\"p\"\n value={attributes.content || ''}\n onChange={(value) => updateField('content', value)}\n placeholder={__('Add your content...', '{{textDomain}}')}\n />\n </div>\n {!isValid && (\n <Notice status=\"error\" isDismissible={false}>\n <p>\n <strong>{__('Validation Errors', '{{textDomain}}')}</strong>\n </p>\n <ul style={validationListStyle}>\n {errorMessages.map((error, index) => (\n <li key={index}>{error}</li>\n ))}\n </ul>\n </Notice>\n )}\n </div>\n </>\n );\n}\n\nexport default Edit;\n";
@@ -38,30 +39,42 @@ function createCodeArtifact(relativePath, template, variables) {
38
39
  source: renderCodeTemplate(template, variables),
39
40
  };
40
41
  }
42
+ function ensureUniqueArtifactPaths(artifacts) {
43
+ const seenPaths = new Set();
44
+ for (const artifact of artifacts) {
45
+ if (seenPaths.has(artifact.relativePath)) {
46
+ throw new Error(`Duplicate built-in artifact path emitted: ${artifact.relativePath}`);
47
+ }
48
+ seenPaths.add(artifact.relativePath);
49
+ }
50
+ return artifacts;
51
+ }
41
52
  function buildBasicCodeArtifacts(variables) {
42
- return [
53
+ return ensureUniqueArtifactPaths([
43
54
  createCodeArtifact("src/hooks.ts", SHARED_HOOKS_TEMPLATE, variables),
44
55
  createCodeArtifact("src/edit.tsx", BASIC_EDIT_TEMPLATE, variables),
45
56
  createCodeArtifact("src/save.tsx", BASIC_SAVE_TEMPLATE, variables),
46
57
  createCodeArtifact("src/index.tsx", BASIC_INDEX_TEMPLATE, variables),
47
58
  createCodeArtifact("src/validators.ts", BASIC_VALIDATORS_TEMPLATE, variables),
48
- ];
59
+ ...buildBuiltInNonTsArtifacts({ templateId: "basic", variables }),
60
+ ]);
49
61
  }
50
62
  function buildInteractivityCodeArtifacts(variables) {
51
- return [
63
+ return ensureUniqueArtifactPaths([
52
64
  createCodeArtifact("src/hooks.ts", SHARED_HOOKS_TEMPLATE, variables),
53
65
  createCodeArtifact("src/edit.tsx", INTERACTIVITY_EDIT_TEMPLATE, variables),
54
66
  createCodeArtifact("src/save.tsx", INTERACTIVITY_SAVE_TEMPLATE, variables),
55
67
  createCodeArtifact("src/index.tsx", INTERACTIVITY_INDEX_TEMPLATE, variables),
56
68
  createCodeArtifact("src/interactivity.ts", INTERACTIVITY_SCRIPT_TEMPLATE, variables),
57
69
  createCodeArtifact("src/validators.ts", INTERACTIVITY_VALIDATORS_TEMPLATE, variables),
58
- ];
70
+ ...buildBuiltInNonTsArtifacts({ templateId: "interactivity", variables }),
71
+ ]);
59
72
  }
60
73
  function buildCompoundCodeArtifacts(variables) {
61
74
  const parentBasePath = `src/blocks/${variables.slugKebabCase}`;
62
75
  const childBasePath = `src/blocks/${variables.slugKebabCase}-item`;
63
76
  const compoundPersistenceEnabled = variables.compoundPersistenceEnabled === "true";
64
- return [
77
+ return ensureUniqueArtifactPaths([
65
78
  createCodeArtifact("src/hooks.ts", SHARED_HOOKS_TEMPLATE, variables),
66
79
  createCodeArtifact(`${parentBasePath}/edit.tsx`, compoundPersistenceEnabled
67
80
  ? COMPOUND_PERSISTENCE_PARENT_EDIT_TEMPLATE
@@ -85,24 +98,26 @@ function buildCompoundCodeArtifacts(variables) {
85
98
  createCodeArtifact(`${childBasePath}/index.tsx`, COMPOUND_CHILD_INDEX_TEMPLATE, variables),
86
99
  createCodeArtifact(`${childBasePath}/hooks.ts`, COMPOUND_LOCAL_HOOKS_TEMPLATE, variables),
87
100
  createCodeArtifact(`${childBasePath}/validators.ts`, COMPOUND_CHILD_VALIDATORS_TEMPLATE, variables),
88
- ];
101
+ ...buildBuiltInNonTsArtifacts({ templateId: "compound", variables }),
102
+ ]);
89
103
  }
90
104
  function buildPersistenceCodeArtifacts(variables) {
91
- return [
105
+ return ensureUniqueArtifactPaths([
92
106
  createCodeArtifact("src/hooks.ts", SHARED_HOOKS_TEMPLATE, variables),
93
107
  createCodeArtifact("src/edit.tsx", PERSISTENCE_EDIT_TEMPLATE, variables),
94
108
  createCodeArtifact("src/save.tsx", PERSISTENCE_SAVE_TEMPLATE, variables),
95
109
  createCodeArtifact("src/index.tsx", PERSISTENCE_INDEX_TEMPLATE, variables),
96
110
  createCodeArtifact("src/interactivity.ts", PERSISTENCE_INTERACTIVITY_TEMPLATE, variables),
97
111
  createCodeArtifact("src/validators.ts", PERSISTENCE_VALIDATORS_TEMPLATE, variables),
98
- ];
112
+ ...buildBuiltInNonTsArtifacts({ templateId: "persistence", variables }),
113
+ ]);
99
114
  }
100
115
  /**
101
- * Build the emitter-owned TS/TSX scaffold files for a built-in template family.
116
+ * Build the emitter-owned scaffold files for a built-in template family.
102
117
  *
103
- * These artifacts are written after template copy so built-in structural and
104
- * code files always come from the typed generator boundary rather than stale
105
- * Mustache sources.
118
+ * These artifacts are written after template copy so built-in structural,
119
+ * source, and adjacent generated files always come from the typed generator
120
+ * boundary rather than stale Mustache sources.
106
121
  */
107
122
  export function buildBuiltInCodeArtifacts({ templateId, variables, }) {
108
123
  switch (templateId) {
@@ -0,0 +1,18 @@
1
+ import type { BuiltInCodeArtifact } from "./built-in-block-code-artifacts.js";
2
+ import type { ScaffoldTemplateVariables } from "./scaffold.js";
3
+ import type { BuiltInTemplateId } from "./template-registry.js";
4
+ /**
5
+ * Builds non-TypeScript scaffold artifacts for built-in block templates.
6
+ *
7
+ * @param options Build options for the selected built-in template family.
8
+ * @param options.templateId Built-in template identifier that controls which
9
+ * non-TS files should be emitted.
10
+ * @param options.variables Scaffold template variables used to render the
11
+ * generated sources.
12
+ * @returns An array of emitter-owned SCSS and PHP artifacts for the selected
13
+ * built-in template family.
14
+ */
15
+ export declare function buildBuiltInNonTsArtifacts({ templateId, variables, }: {
16
+ templateId: BuiltInTemplateId;
17
+ variables: ScaffoldTemplateVariables;
18
+ }): BuiltInCodeArtifact[];