wp-typia 0.20.5 → 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/README.md CHANGED
@@ -13,10 +13,15 @@ Use this package for new projects:
13
13
  Extend an existing workspace with:
14
14
 
15
15
  - `wp-typia add block counter-card --template basic`
16
+ - `wp-typia add style callout-emphasis --block counter-card`
17
+ - `wp-typia add transform quote-to-counter --from core/quote --to counter-card`
16
18
  - `wp-typia add binding-source hero-data`
19
+ - `wp-typia add binding-source hero-data --block counter-card --attribute headline`
17
20
  - `wp-typia add rest-resource snapshots --namespace my-plugin/v1 --methods list,read,create`
18
21
  - `wp-typia add ability review-workflow`
19
22
  - `wp-typia add ai-feature brief-suggestions --namespace my-plugin/v1`
23
+ - `wp-typia add editor-plugin review-workflow --slot sidebar`
24
+ - `wp-typia add editor-plugin seo-notes --slot document-setting-panel`
20
25
  - `wp-typia add hooked-block counter-card --anchor core/post-content --position after`
21
26
 
22
27
  `wp-typia <project-dir>` remains available as a backward-compatible alias to
@@ -0,0 +1,19 @@
1
+ export type ArgvWalkerMetadata = {
2
+ longValueOptions: Iterable<string>;
3
+ shortValueOptions: Iterable<string>;
4
+ };
5
+
6
+ export declare function collectPositionalIndexes(
7
+ argv: string[],
8
+ metadata: ArgvWalkerMetadata,
9
+ ): number[];
10
+
11
+ export declare function findFirstPositionalIndex(
12
+ argv: string[],
13
+ metadata: ArgvWalkerMetadata,
14
+ ): number;
15
+
16
+ export declare function findFirstPositional(
17
+ argv: string[],
18
+ metadata: ArgvWalkerMetadata,
19
+ ): string | undefined;
@@ -0,0 +1,53 @@
1
+ function normalizeOptionSet(values) {
2
+ return values instanceof Set ? values : new Set(values);
3
+ }
4
+
5
+ export function collectPositionalIndexes(argv, metadata) {
6
+ const longValueOptionSet = normalizeOptionSet(metadata.longValueOptions);
7
+ const shortValueOptionSet = normalizeOptionSet(metadata.shortValueOptions);
8
+ const positionalIndexes = [];
9
+
10
+ for (let index = 0; index < argv.length; index += 1) {
11
+ const arg = argv[index];
12
+ if (arg === '--') {
13
+ for (let restIndex = index + 1; restIndex < argv.length; restIndex += 1) {
14
+ positionalIndexes.push(restIndex);
15
+ }
16
+ break;
17
+ }
18
+ if (!arg.startsWith('-') || arg === '-') {
19
+ positionalIndexes.push(index);
20
+ continue;
21
+ }
22
+ if (arg.startsWith('--')) {
23
+ if (arg.includes('=')) {
24
+ continue;
25
+ }
26
+ const next = argv[index + 1];
27
+ if (longValueOptionSet.has(arg) && next && !next.startsWith('-')) {
28
+ index += 1;
29
+ }
30
+ continue;
31
+ }
32
+ if (
33
+ arg.length === 2 &&
34
+ shortValueOptionSet.has(arg) &&
35
+ argv[index + 1] &&
36
+ !argv[index + 1].startsWith('-')
37
+ ) {
38
+ index += 1;
39
+ }
40
+ }
41
+
42
+ return positionalIndexes;
43
+ }
44
+
45
+ export function findFirstPositionalIndex(argv, metadata) {
46
+ const positionalIndexes = collectPositionalIndexes(argv, metadata);
47
+ return positionalIndexes[0] ?? -1;
48
+ }
49
+
50
+ export function findFirstPositional(argv, metadata) {
51
+ const firstPositionalIndex = findFirstPositionalIndex(argv, metadata);
52
+ return firstPositionalIndex === -1 ? undefined : argv[firstPositionalIndex];
53
+ }
@@ -1,6 +1,8 @@
1
- // This file was automatically generated by `bun run generate`.
1
+ // This file was automatically generated by `node scripts/generate-routing-metadata.mjs`.
2
2
  // Do not edit directly.
3
3
 
4
4
  export declare const fullRuntimeCommands: readonly string[];
5
+ export declare const interactiveRuntimeCommands: readonly string[];
5
6
  export declare const longValueOptions: readonly string[];
7
+ export declare const reservedCommands: readonly string[];
6
8
  export declare const shortValueOptions: readonly string[];
@@ -1,44 +1,64 @@
1
- // This file was automatically generated by `bun run generate`.
1
+ // This file was automatically generated by `node scripts/generate-routing-metadata.mjs`.
2
2
  // Do not edit directly.
3
3
 
4
4
  export const fullRuntimeCommands = Object.freeze([
5
- "mcp",
6
- "skills",
7
- "completions",
8
- "complete"
5
+ 'mcp',
6
+ 'skills',
7
+ 'completions',
8
+ 'complete',
9
+ ]);
10
+ export const interactiveRuntimeCommands = Object.freeze([
11
+ 'create',
12
+ 'add',
13
+ 'migrate',
9
14
  ]);
10
15
  export const longValueOptions = Object.freeze([
11
- "--alternate-render-targets",
12
- "--anchor",
13
- "--block",
14
- "--config",
15
- "--current-migration-version",
16
- "--data-storage",
17
- "--external-layer-id",
18
- "--external-layer-source",
19
- "--format",
20
- "--from-migration-version",
21
- "--id",
22
- "--inner-blocks-preset",
23
- "--iterations",
24
- "--methods",
25
- "--migration-version",
26
- "--namespace",
27
- "--output-dir",
28
- "--package-manager",
29
- "--persistence-policy",
30
- "--php-prefix",
31
- "--position",
32
- "--query-post-type",
33
- "--seed",
34
- "--slot",
35
- "--template",
36
- "--text-domain",
37
- "--to-migration-version",
38
- "--variant"
16
+ '--alternate-render-targets',
17
+ '--anchor',
18
+ '--attribute',
19
+ '--block',
20
+ '--config',
21
+ '--current-migration-version',
22
+ '--data-storage',
23
+ '--external-layer-id',
24
+ '--external-layer-source',
25
+ '--format',
26
+ '--from',
27
+ '--from-migration-version',
28
+ '--id',
29
+ '--inner-blocks-preset',
30
+ '--iterations',
31
+ '--methods',
32
+ '--migration-version',
33
+ '--namespace',
34
+ '--output-dir',
35
+ '--package-manager',
36
+ '--persistence-policy',
37
+ '--php-prefix',
38
+ '--position',
39
+ '--query-post-type',
40
+ '--seed',
41
+ '--slot',
42
+ '--source',
43
+ '--template',
44
+ '--text-domain',
45
+ '--to',
46
+ '--to-migration-version',
47
+ '--variant',
39
48
  ]);
40
- export const shortValueOptions = Object.freeze([
41
- "-c",
42
- "-p",
43
- "-t"
49
+ export const reservedCommands = Object.freeze([
50
+ 'create',
51
+ 'init',
52
+ 'sync',
53
+ 'add',
54
+ 'migrate',
55
+ 'templates',
56
+ 'doctor',
57
+ 'mcp',
58
+ 'help',
59
+ 'version',
60
+ 'skills',
61
+ 'completions',
62
+ 'complete',
44
63
  ]);
64
+ export const shortValueOptions = Object.freeze(['-c', '-p', '-t']);
@@ -0,0 +1,34 @@
1
+ type RuntimeRoutingValues = readonly string[] | ReadonlySet<string>;
2
+
3
+ type RuntimeRoutingMetadata = {
4
+ longValueOptions: RuntimeRoutingValues;
5
+ reservedCommands: RuntimeRoutingValues;
6
+ shortValueOptions: RuntimeRoutingValues;
7
+ };
8
+
9
+ type RuntimeRoutingStream = {
10
+ isTTY?: boolean;
11
+ };
12
+
13
+ export declare function getRuntimeRoutingInvocation(
14
+ argv: readonly string[],
15
+ metadata: RuntimeRoutingMetadata,
16
+ ): {
17
+ command: string | undefined;
18
+ isSinglePositionalAlias: boolean;
19
+ positionals: string[];
20
+ };
21
+
22
+ export declare function shouldRouteToFullRuntime(options: {
23
+ argv: readonly string[];
24
+ fullRuntimeCommands: RuntimeRoutingValues;
25
+ hasBuiltRuntime: boolean;
26
+ hasWorkingBun: boolean;
27
+ interactiveRuntimeCommands: RuntimeRoutingValues;
28
+ longValueOptions: RuntimeRoutingValues;
29
+ reservedCommands: RuntimeRoutingValues;
30
+ shortValueOptions: RuntimeRoutingValues;
31
+ stdin?: RuntimeRoutingStream;
32
+ stdout?: RuntimeRoutingStream;
33
+ term?: string;
34
+ }): boolean;
@@ -0,0 +1,124 @@
1
+ import { collectPositionalIndexes } from './argv-walker.js';
2
+
3
+ function normalizeSet(values) {
4
+ return values instanceof Set ? values : new Set(values);
5
+ }
6
+
7
+ function hasBooleanFlagBeforeTerminator(argv, longFlag, shortFlag) {
8
+ let matched = false;
9
+ for (const arg of argv) {
10
+ if (arg === '--') {
11
+ break;
12
+ }
13
+ if (arg === longFlag || (shortFlag && arg === shortFlag)) {
14
+ matched = true;
15
+ continue;
16
+ }
17
+ if (arg.startsWith(`${longFlag}=`)) {
18
+ const value = arg.slice(longFlag.length + 1).toLowerCase();
19
+ matched = value !== 'false' && value !== '0' && value !== 'no';
20
+ }
21
+ }
22
+
23
+ return matched;
24
+ }
25
+
26
+ function hasLongOptionBeforeTerminator(argv, optionName) {
27
+ for (let index = 0; index < argv.length; index += 1) {
28
+ const arg = argv[index];
29
+ if (arg === '--') {
30
+ return false;
31
+ }
32
+ if (arg === optionName || arg.startsWith(`${optionName}=`)) {
33
+ return true;
34
+ }
35
+ }
36
+
37
+ return false;
38
+ }
39
+
40
+ function isInteractiveTerminal({ stdin, stdout, term }) {
41
+ return Boolean(stdin?.isTTY) && Boolean(stdout?.isTTY) && term !== 'dumb';
42
+ }
43
+
44
+ export function getRuntimeRoutingInvocation(argv, metadata) {
45
+ const positionalIndexes = collectPositionalIndexes(argv, metadata);
46
+ const positionals = positionalIndexes
47
+ .map((index) => argv[index])
48
+ .filter((value) => typeof value === 'string' && value.length > 0);
49
+ const command = positionals[0];
50
+ const reservedCommandSet = normalizeSet(metadata.reservedCommands);
51
+ const isSinglePositionalAlias =
52
+ Boolean(command) &&
53
+ positionals.length === 1 &&
54
+ !reservedCommandSet.has(command);
55
+
56
+ return {
57
+ command,
58
+ isSinglePositionalAlias,
59
+ positionals,
60
+ };
61
+ }
62
+
63
+ export function shouldRouteToFullRuntime({
64
+ argv,
65
+ fullRuntimeCommands,
66
+ hasBuiltRuntime,
67
+ hasWorkingBun,
68
+ interactiveRuntimeCommands,
69
+ longValueOptions,
70
+ reservedCommands,
71
+ shortValueOptions,
72
+ stdin = process.stdin,
73
+ stdout = process.stdout,
74
+ term = process.env.TERM,
75
+ }) {
76
+ if (!hasWorkingBun || !hasBuiltRuntime) {
77
+ return false;
78
+ }
79
+
80
+ const fullRuntimeCommandSet = normalizeSet(fullRuntimeCommands);
81
+ const interactiveRuntimeCommandSet = normalizeSet(interactiveRuntimeCommands);
82
+ const invocation = getRuntimeRoutingInvocation(argv, {
83
+ longValueOptions,
84
+ reservedCommands,
85
+ shortValueOptions,
86
+ });
87
+
88
+ if (invocation.command && fullRuntimeCommandSet.has(invocation.command)) {
89
+ return true;
90
+ }
91
+
92
+ if (
93
+ !isInteractiveTerminal({
94
+ stdin,
95
+ stdout,
96
+ term,
97
+ })
98
+ ) {
99
+ return false;
100
+ }
101
+
102
+ if (
103
+ invocation.command === 'help' ||
104
+ invocation.command === 'version' ||
105
+ hasBooleanFlagBeforeTerminator(argv, '--help', '-h') ||
106
+ hasBooleanFlagBeforeTerminator(argv, '--version', '-v') ||
107
+ hasLongOptionBeforeTerminator(argv, '--format') ||
108
+ hasBooleanFlagBeforeTerminator(argv, '--yes', '-y')
109
+ ) {
110
+ return false;
111
+ }
112
+
113
+ if (
114
+ invocation.command &&
115
+ interactiveRuntimeCommandSet.has(invocation.command)
116
+ ) {
117
+ return true;
118
+ }
119
+
120
+ return (
121
+ invocation.isSinglePositionalAlias &&
122
+ interactiveRuntimeCommandSet.has('create')
123
+ );
124
+ }
package/bin/wp-typia.js CHANGED
@@ -1,125 +1,132 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import fs from "node:fs";
4
- import { spawnSync } from "node:child_process";
5
- import path from "node:path";
6
- import { fileURLToPath, pathToFileURL } from "node:url";
3
+ import fs from 'node:fs';
4
+ import { spawnSync } from 'node:child_process';
5
+ import path from 'node:path';
6
+ import { fileURLToPath, pathToFileURL } from 'node:url';
7
7
 
8
8
  import {
9
- fullRuntimeCommands,
10
- longValueOptions,
11
- shortValueOptions,
12
- } from "./routing-metadata.generated.js";
13
-
14
- const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
15
- const cliEntrypoint = path.join(packageRoot, "dist-bunli", "cli.js");
16
- const nodeCliEntrypoint = path.join(packageRoot, "dist-bunli", "node-cli.js");
17
- const bunBinary = process.env.BUN_BIN || "bun";
9
+ fullRuntimeCommands,
10
+ interactiveRuntimeCommands,
11
+ longValueOptions,
12
+ reservedCommands,
13
+ shortValueOptions,
14
+ } from './routing-metadata.generated.js';
15
+ import {
16
+ getRuntimeRoutingInvocation,
17
+ shouldRouteToFullRuntime,
18
+ } from './runtime-routing.js';
19
+
20
+ const packageRoot = path.resolve(
21
+ path.dirname(fileURLToPath(import.meta.url)),
22
+ '..',
23
+ );
24
+ const cliEntrypoint = path.join(packageRoot, 'dist-bunli', 'cli.js');
25
+ const nodeCliEntrypoint = path.join(packageRoot, 'dist-bunli', 'node-cli.js');
26
+ const bunBinary = process.env.BUN_BIN || 'bun';
18
27
  const fullRuntimeCommandSet = new Set(fullRuntimeCommands);
28
+ const interactiveRuntimeCommandSet = new Set(interactiveRuntimeCommands);
19
29
  const longValueOptionSet = new Set(longValueOptions);
30
+ const reservedCommandSet = new Set(reservedCommands);
20
31
  const shortValueOptionSet = new Set(shortValueOptions);
21
- const buildScriptEntrypoint = path.join(packageRoot, "scripts", "build-bunli-runtime.ts");
22
- const sourceCliEntrypoint = path.join(packageRoot, "src", "cli.ts");
32
+ const buildScriptEntrypoint = path.join(
33
+ packageRoot,
34
+ 'scripts',
35
+ 'build-bunli-runtime.ts',
36
+ );
37
+ const sourceCliEntrypoint = path.join(packageRoot, 'src', 'cli.ts');
23
38
  const standaloneGuidance =
24
- "Prefer not to install Bun? Use the standalone wp-typia binary from the GitHub release assets.";
25
-
26
- function firstPositional(argv) {
27
- for (let index = 0; index < argv.length; index += 1) {
28
- const arg = argv[index];
29
- if (!arg || arg === "--") {
30
- break;
31
- }
32
- if (shortValueOptionSet.has(arg) || longValueOptionSet.has(arg)) {
33
- index += 1;
34
- continue;
35
- }
36
- if (arg.startsWith("--")) {
37
- const separatorIndex = arg.indexOf("=");
38
- if (
39
- separatorIndex > 0 &&
40
- longValueOptionSet.has(arg.slice(0, separatorIndex))
41
- ) {
42
- continue;
43
- }
44
- }
45
- if (arg.startsWith("-") && arg !== "-") {
46
- continue;
47
- }
48
- return arg;
49
- }
50
- return undefined;
51
- }
39
+ 'Prefer not to install Bun? Use the standalone wp-typia binary from the GitHub release assets.';
52
40
 
53
41
  function isWorkingBunBinary() {
54
- const bunCheck = spawnSync(bunBinary, ["--version"], {
55
- env: process.env,
56
- stdio: "ignore",
57
- });
42
+ const bunCheck = spawnSync(bunBinary, ['--version'], {
43
+ env: process.env,
44
+ stdio: 'ignore',
45
+ });
58
46
 
59
- return !bunCheck.error && bunCheck.status === 0;
47
+ return !bunCheck.error && bunCheck.status === 0;
60
48
  }
61
49
 
62
50
  function canAutobuildSourceCheckout() {
63
- return fs.existsSync(buildScriptEntrypoint) && fs.existsSync(sourceCliEntrypoint);
51
+ return (
52
+ fs.existsSync(buildScriptEntrypoint) && fs.existsSync(sourceCliEntrypoint)
53
+ );
64
54
  }
65
55
 
66
56
  function ensureBuiltRuntime() {
67
- if (fs.existsSync(cliEntrypoint) && fs.existsSync(nodeCliEntrypoint)) {
68
- return true;
69
- }
57
+ if (fs.existsSync(cliEntrypoint) && fs.existsSync(nodeCliEntrypoint)) {
58
+ return true;
59
+ }
70
60
 
71
- if (!canAutobuildSourceCheckout() || !isWorkingBunBinary()) {
72
- return false;
73
- }
61
+ if (!canAutobuildSourceCheckout() || !isWorkingBunBinary()) {
62
+ return false;
63
+ }
74
64
 
75
- const buildResult = spawnSync(bunBinary, ["run", "build"], {
76
- cwd: packageRoot,
77
- env: process.env,
78
- stdio: "inherit",
79
- });
65
+ const buildResult = spawnSync(bunBinary, ['run', 'build'], {
66
+ cwd: packageRoot,
67
+ env: process.env,
68
+ stdio: 'inherit',
69
+ });
80
70
 
81
- if (buildResult.status !== 0) {
82
- process.exit(buildResult.status ?? 1);
83
- }
71
+ if (buildResult.status !== 0) {
72
+ process.exit(buildResult.status ?? 1);
73
+ }
84
74
 
85
- return fs.existsSync(cliEntrypoint) && fs.existsSync(nodeCliEntrypoint);
75
+ return fs.existsSync(cliEntrypoint) && fs.existsSync(nodeCliEntrypoint);
86
76
  }
87
77
 
88
78
  const argv = process.argv.slice(2);
89
- const command = firstPositional(argv);
90
- const shouldUseFullRuntime = command ? fullRuntimeCommandSet.has(command) : false;
79
+ const { command } = getRuntimeRoutingInvocation(argv, {
80
+ longValueOptions: longValueOptionSet,
81
+ reservedCommands: reservedCommandSet,
82
+ shortValueOptions: shortValueOptionSet,
83
+ });
84
+ const commandRequiresFullRuntime = command
85
+ ? fullRuntimeCommandSet.has(command)
86
+ : false;
91
87
  const hasBuiltRuntime = ensureBuiltRuntime();
92
88
  const hasWorkingBun = isWorkingBunBinary();
93
-
94
- // Keep common help on the human-readable Node fallback even when Bun is present.
89
+ const shouldUseFullRuntime = shouldRouteToFullRuntime({
90
+ argv,
91
+ fullRuntimeCommands: fullRuntimeCommandSet,
92
+ hasBuiltRuntime,
93
+ hasWorkingBun,
94
+ interactiveRuntimeCommands: interactiveRuntimeCommandSet,
95
+ longValueOptions: longValueOptionSet,
96
+ reservedCommands: reservedCommandSet,
97
+ shortValueOptions: shortValueOptionSet,
98
+ });
99
+
100
+ // Keep common help and explicit non-TUI calls on the human-readable Node fallback
101
+ // even when Bun is present.
95
102
  if (hasWorkingBun && hasBuiltRuntime && shouldUseFullRuntime) {
96
- const result = spawnSync(bunBinary, [cliEntrypoint, ...argv], {
97
- cwd: process.cwd(),
98
- env: process.env,
99
- stdio: "inherit",
100
- });
101
- process.exit(result.status ?? 1);
103
+ const result = spawnSync(bunBinary, [cliEntrypoint, ...argv], {
104
+ cwd: process.cwd(),
105
+ env: process.env,
106
+ stdio: 'inherit',
107
+ });
108
+ process.exit(result.status ?? 1);
102
109
  }
103
110
 
104
- if (shouldUseFullRuntime) {
105
- if (!hasBuiltRuntime) {
106
- console.error(
107
- "Error: wp-typia could not locate its built CLI runtime. Reinstall the published package, or run `bun run build` when using a source checkout.",
108
- );
109
- process.exit(1);
110
- }
111
-
112
- console.error(
113
- `Error: wp-typia ${command} requires Bun. Install Bun locally, run with bunx, or set BUN_BIN to a working Bun executable. ${standaloneGuidance}`,
114
- );
115
- process.exit(1);
111
+ if (commandRequiresFullRuntime) {
112
+ if (!hasBuiltRuntime) {
113
+ console.error(
114
+ 'Error: wp-typia could not locate its built CLI runtime. Reinstall the published package, or run `bun run build` when using a source checkout.',
115
+ );
116
+ process.exit(1);
117
+ }
118
+
119
+ console.error(
120
+ `Error: wp-typia ${command} requires Bun. Install Bun locally, run with bunx, or set BUN_BIN to a working Bun executable. ${standaloneGuidance}`,
121
+ );
122
+ process.exit(1);
116
123
  }
117
124
 
118
125
  if (!hasBuiltRuntime || !fs.existsSync(nodeCliEntrypoint)) {
119
- console.error(
120
- "Error: wp-typia could not locate its Node fallback runtime. Reinstall the published package, or run `bun run build` when using a source checkout.",
121
- );
122
- process.exit(1);
126
+ console.error(
127
+ 'Error: wp-typia could not locate its Node fallback runtime. Reinstall the published package, or run `bun run build` when using a source checkout.',
128
+ );
129
+ process.exit(1);
123
130
  }
124
131
 
125
132
  const cliModule = await import(pathToFileURL(nodeCliEntrypoint).href);