wp-typia 0.16.14 → 0.17.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.
Files changed (31) hide show
  1. package/README.md +2 -2
  2. package/dist-bunli/.bunli/commands.gen.js +553 -271
  3. package/dist-bunli/.bunli/commands.gen.js.map +24 -20
  4. package/dist-bunli/{chunk-nmj243dx.js → chunk-1tddsdm7.js} +7 -5
  5. package/dist-bunli/chunk-1tddsdm7.js.map +10 -0
  6. package/dist-bunli/{chunk-qcjj2zqb.js → chunk-91jbnjnj.js} +19 -2
  7. package/dist-bunli/{chunk-qcjj2zqb.js.map → chunk-91jbnjnj.js.map} +4 -4
  8. package/dist-bunli/{chunk-kea2qcrw.js → chunk-gnmssg42.js} +1 -1
  9. package/dist-bunli/chunk-jn4gd4zr.js +117 -0
  10. package/dist-bunli/chunk-jn4gd4zr.js.map +10 -0
  11. package/dist-bunli/{chunk-3smrp421.js → chunk-m58h1nfr.js} +2 -2
  12. package/dist-bunli/{chunk-9czekkce.js → chunk-nsp30swa.js} +1 -1
  13. package/dist-bunli/{chunk-ktyee9zx.js → chunk-p4rzap95.js} +596 -418
  14. package/dist-bunli/{chunk-ktyee9zx.js.map → chunk-p4rzap95.js.map} +17 -13
  15. package/dist-bunli/{chunk-3qpwa1ph.js → chunk-t6jqe0e9.js} +4 -4
  16. package/dist-bunli/{chunk-gye66gne.js → chunk-t8507ce9.js} +1 -1
  17. package/dist-bunli/{chunk-2ecxfs2m.js → chunk-w0r7wa4s.js} +1 -1
  18. package/dist-bunli/cli.js +17 -10
  19. package/dist-bunli/cli.js.map +6 -6
  20. package/dist-bunli/node-cli.js +7 -6
  21. package/dist-bunli/node-cli.js.map +6 -6
  22. package/package.json +2 -2
  23. package/dist-bunli/chunk-nmj243dx.js.map +0 -10
  24. package/dist-bunli/chunk-s5y2xb3g.js +0 -60
  25. package/dist-bunli/chunk-s5y2xb3g.js.map +0 -10
  26. /package/dist-bunli/{chunk-kea2qcrw.js.map → chunk-gnmssg42.js.map} +0 -0
  27. /package/dist-bunli/{chunk-3smrp421.js.map → chunk-m58h1nfr.js.map} +0 -0
  28. /package/dist-bunli/{chunk-9czekkce.js.map → chunk-nsp30swa.js.map} +0 -0
  29. /package/dist-bunli/{chunk-3qpwa1ph.js.map → chunk-t6jqe0e9.js.map} +0 -0
  30. /package/dist-bunli/{chunk-gye66gne.js.map → chunk-t8507ce9.js.map} +0 -0
  31. /package/dist-bunli/{chunk-2ecxfs2m.js.map → chunk-w0r7wa4s.js.map} +0 -0
@@ -37188,18 +37188,17 @@ function createReadlinePrompt() {
37188
37188
  return createReadlinePromptWithInterface(rl);
37189
37189
  }
37190
37190
  function createReadlinePromptWithInterface(rl) {
37191
+ const askQuestion = (query) => new Promise((resolve4) => {
37192
+ rl.question(query, resolve4);
37193
+ });
37191
37194
  return {
37192
37195
  async text(message, defaultValue, validate) {
37193
- const suffix = defaultValue ? ` (${defaultValue})` : "";
37194
37196
  while (true) {
37195
- const answer = await new Promise((resolve4) => {
37196
- rl.question(`${message}${suffix}: `, resolve4);
37197
- });
37198
- const value2 = String(answer).trim() || defaultValue;
37197
+ const value2 = normalizePromptAnswer(await askQuestion(formatTextPrompt(message, defaultValue))) || defaultValue;
37199
37198
  if (validate) {
37200
37199
  const result = validate(value2);
37201
37200
  if (result !== true) {
37202
- console.error(`\u274C ${typeof result === "string" ? result : "Invalid input"}`);
37201
+ console.error(formatValidationError(message, result, defaultValue));
37203
37202
  continue;
37204
37203
  }
37205
37204
  }
@@ -37210,22 +37209,22 @@ function createReadlinePromptWithInterface(rl) {
37210
37209
  if (options.length === 0) {
37211
37210
  throw new Error(`select() requires at least one option for prompt: ${message}`);
37212
37211
  }
37213
- console.log(message);
37214
- options.forEach((option3, index) => {
37215
- const hint = option3.hint ? ` - ${option3.hint}` : "";
37216
- console.log(` ${index + 1}. ${option3.label}${hint}`);
37217
- });
37212
+ const resolvedDefaultIndex = getResolvedDefaultIndex(options, defaultValue);
37213
+ renderSelectPrompt(message, options, resolvedDefaultIndex);
37218
37214
  while (true) {
37219
- const answer = await this.text("Choice", String(defaultValue));
37220
- const numericChoice = Number(answer);
37221
- if (!Number.isNaN(numericChoice) && options[numericChoice - 1]) {
37222
- return options[numericChoice - 1].value;
37215
+ const answer = normalizePromptAnswer(await askQuestion(formatChoicePrompt(resolvedDefaultIndex)));
37216
+ if (answer.length === 0) {
37217
+ return options[resolvedDefaultIndex].value;
37218
+ }
37219
+ const selection = resolvePromptSelection(options, answer);
37220
+ if (selection) {
37221
+ return selection.value;
37223
37222
  }
37224
- const directChoice = options.find((option3) => option3.value === answer);
37225
- if (directChoice) {
37226
- return directChoice.value;
37223
+ if (isPromptHelpToken(answer)) {
37224
+ renderSelectPrompt(message, options, resolvedDefaultIndex);
37225
+ continue;
37227
37226
  }
37228
- console.error(`\u274C Invalid selection: ${answer}`);
37227
+ console.error(formatInvalidSelectionError(answer, options, resolvedDefaultIndex));
37229
37228
  }
37230
37229
  },
37231
37230
  close() {
@@ -37233,6 +37232,64 @@ function createReadlinePromptWithInterface(rl) {
37233
37232
  }
37234
37233
  };
37235
37234
  }
37235
+ function normalizePromptAnswer(value2) {
37236
+ return String(value2).trim();
37237
+ }
37238
+ function normalizePromptToken(value2) {
37239
+ return value2.trim().toLowerCase();
37240
+ }
37241
+ function getResolvedDefaultIndex(options, defaultValue) {
37242
+ const candidateIndex = Number.isInteger(defaultValue) ? defaultValue - 1 : -1;
37243
+ return options[candidateIndex] ? candidateIndex : 0;
37244
+ }
37245
+ function formatTextPrompt(message, defaultValue) {
37246
+ const suffix = defaultValue.length > 0 ? ` [default: ${defaultValue}]` : "";
37247
+ return `${message}${suffix}: `;
37248
+ }
37249
+ function formatValidationError(message, result, defaultValue) {
37250
+ const detail = typeof result === "string" ? result : "Invalid input";
37251
+ const retryHint = defaultValue.length > 0 ? ` Press Enter to keep "${defaultValue}".` : "";
37252
+ return `\u274C ${message}: ${detail}.${retryHint}`;
37253
+ }
37254
+ function formatChoicePrompt(defaultIndex) {
37255
+ return `Choice [default: ${defaultIndex + 1}, ? for options]: `;
37256
+ }
37257
+ function renderSelectPrompt(message, options, defaultIndex) {
37258
+ console.log(message);
37259
+ console.log(" Enter a number, option label, or option value. Press Enter to keep the default, or type ? to list choices again.");
37260
+ options.forEach((option3, index) => {
37261
+ const defaultMarker = index === defaultIndex ? " (default)" : "";
37262
+ const valueHint = normalizePromptToken(option3.label) === normalizePromptToken(option3.value) ? "" : ` [${option3.value}]`;
37263
+ console.log(` ${index + 1}. ${option3.label}${valueHint}${defaultMarker}`);
37264
+ if (option3.hint) {
37265
+ console.log(` ${option3.hint}`);
37266
+ }
37267
+ });
37268
+ }
37269
+ function isPromptHelpToken(answer) {
37270
+ const normalized = normalizePromptToken(answer);
37271
+ return normalized === "?" || normalized === "help" || normalized === "list";
37272
+ }
37273
+ function resolvePromptSelection(options, answer) {
37274
+ const numericChoice = Number(answer);
37275
+ if (!Number.isNaN(numericChoice) && options[numericChoice - 1]) {
37276
+ return options[numericChoice - 1];
37277
+ }
37278
+ const normalizedAnswer = normalizePromptToken(answer);
37279
+ return options.find((option3) => {
37280
+ const normalizedLabel = normalizePromptToken(option3.label);
37281
+ const normalizedValue = normalizePromptToken(option3.value);
37282
+ return normalizedAnswer === normalizedLabel || normalizedAnswer === normalizedValue;
37283
+ });
37284
+ }
37285
+ function formatInvalidSelectionError(answer, options, defaultIndex) {
37286
+ const optionValues = options.map((option3) => option3.value).join(", ");
37287
+ return [
37288
+ `\u274C Invalid selection: ${answer}.`,
37289
+ `Enter 1-${options.length}, one of: ${optionValues},`,
37290
+ `or press Enter for "${options[defaultIndex].label}".`
37291
+ ].join(" ");
37292
+ }
37236
37293
  var init_cli_prompt = () => {};
37237
37294
 
37238
37295
  // ../wp-typia-project-tools/src/runtime/migration-command-surface.ts
@@ -211064,6 +211121,10 @@ var init_template_defaults = __esm(() => {
211064
211121
  compound: Object.freeze({
211065
211122
  category: "widgets",
211066
211123
  icon: "screenoptions"
211124
+ }),
211125
+ "query-loop": Object.freeze({
211126
+ category: "widgets",
211127
+ icon: "query-pagination"
211067
211128
  })
211068
211129
  });
211069
211130
  COMPOUND_CHILD_BLOCK_METADATA_DEFAULTS = Object.freeze({
@@ -211135,7 +211196,13 @@ var init_template_registry = __esm(() => {
211135
211196
  SHARED_WORKSPACE_TEMPLATE_ROOT = path25.join(SHARED_TEMPLATE_ROOT, "workspace");
211136
211197
  SHARED_TEST_PRESET_TEMPLATE_ROOT = path25.join(SHARED_PRESET_TEMPLATE_ROOT, "test-preset");
211137
211198
  SHARED_WP_ENV_PRESET_TEMPLATE_ROOT = path25.join(SHARED_PRESET_TEMPLATE_ROOT, "wp-env");
211138
- BUILTIN_TEMPLATE_IDS = ["basic", "interactivity", "persistence", "compound"];
211199
+ BUILTIN_TEMPLATE_IDS = [
211200
+ "basic",
211201
+ "interactivity",
211202
+ "persistence",
211203
+ "compound",
211204
+ "query-loop"
211205
+ ];
211139
211206
  TEMPLATE_REGISTRY = Object.freeze([
211140
211207
  {
211141
211208
  id: "basic",
@@ -211165,6 +211232,13 @@ var init_template_registry = __esm(() => {
211165
211232
  features: ["InnerBlocks", "Hidden child blocks", "Optional persistence layer"],
211166
211233
  templateDir: path25.join(TEMPLATE_ROOT, "compound")
211167
211234
  },
211235
+ {
211236
+ id: "query-loop",
211237
+ description: "A Query Loop block variation scaffold with stable namespace-based identity, inline starter layout, connected pattern presets, custom query seams, and runtime parity hooks",
211238
+ defaultCategory: getBuiltInTemplateMetadataDefaults("query-loop").category,
211239
+ features: ["core/query variation", "Default innerBlocks", "Connected patterns", "Custom query hooks", "Runtime parity hooks", "Allowed controls"],
211240
+ templateDir: path25.join(TEMPLATE_ROOT, "query-loop")
211241
+ },
211168
211242
  {
211169
211243
  id: OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE,
211170
211244
  description: "The official empty workspace template that powers `wp-typia add ...` workflows",
@@ -211810,6 +211884,9 @@ import path27 from "path";
211810
211884
  function templateHasPersistenceSync(templateId, compoundPersistenceEnabled) {
211811
211885
  return templateId === "persistence" || templateId === "compound" && compoundPersistenceEnabled;
211812
211886
  }
211887
+ function templateSupportsGeneratedSyncWatchers(templateId) {
211888
+ return templateId === "basic" || templateId === "interactivity" || templateId === "persistence" || templateId === "compound";
211889
+ }
211813
211890
  function getWatchSyncTypesScript(packageManager, templateId) {
211814
211891
  if (templateId === "compound") {
211815
211892
  return `chokidar "src/blocks/**/types.ts" "scripts/block-config.ts" --debounce 200 -c "${formatRunScript2(packageManager, "sync-types")}"`;
@@ -211886,11 +211963,14 @@ async function applyGeneratedProjectDxPackageJson({
211886
211963
  withWpEnv = false
211887
211964
  }) {
211888
211965
  const hasPersistenceSync = templateHasPersistenceSync(templateId, compoundPersistenceEnabled);
211966
+ const supportsGeneratedSyncWatchers = templateSupportsGeneratedSyncWatchers(templateId);
211889
211967
  await mutatePackageJson(projectDir, (packageJson) => {
211890
211968
  packageJson.devDependencies = {
211891
211969
  ...packageJson.devDependencies ?? {},
211892
- "chokidar-cli": "^3.0.0",
211893
- concurrently: "^9.0.1"
211970
+ ...supportsGeneratedSyncWatchers ? {
211971
+ "chokidar-cli": "^3.0.0",
211972
+ concurrently: "^9.0.1"
211973
+ } : {}
211894
211974
  };
211895
211975
  if (withWpEnv || withTestPreset) {
211896
211976
  packageJson.devDependencies["@wordpress/env"] = "^11.2.0";
@@ -211901,12 +211981,16 @@ async function applyGeneratedProjectDxPackageJson({
211901
211981
  const scripts = {
211902
211982
  ...packageJson.scripts ?? {}
211903
211983
  };
211904
- scripts["start:editor"] = "wp-scripts start --experimental-modules";
211905
- scripts["watch:sync-types"] = getWatchSyncTypesScript(packageManager, templateId);
211984
+ if (supportsGeneratedSyncWatchers) {
211985
+ scripts["start:editor"] = "wp-scripts start --experimental-modules";
211986
+ scripts["watch:sync-types"] = getWatchSyncTypesScript(packageManager, templateId);
211987
+ }
211906
211988
  if (hasPersistenceSync) {
211907
211989
  scripts["watch:sync-rest"] = getWatchSyncRestScript(packageManager, templateId);
211908
211990
  }
211909
- scripts.dev = getDevScript(packageManager, compoundPersistenceEnabled, templateId);
211991
+ if (supportsGeneratedSyncWatchers) {
211992
+ scripts.dev = getDevScript(packageManager, compoundPersistenceEnabled, templateId);
211993
+ }
211910
211994
  if (withWpEnv) {
211911
211995
  scripts["wp-env:start"] = "wp-env start";
211912
211996
  scripts["wp-env:stop"] = "wp-env stop";
@@ -211923,7 +212007,7 @@ async function applyGeneratedProjectDxPackageJson({
211923
212007
  });
211924
212008
  }
211925
212009
  function getPrimaryDevelopmentScript(templateId) {
211926
- return templateId === "basic" || templateId === "interactivity" || templateId === "persistence" || templateId === "compound" ? "dev" : "start";
212010
+ return templateSupportsGeneratedSyncWatchers(templateId) ? "dev" : "start";
211927
212011
  }
211928
212012
  var init_local_dev_presets = __esm(() => {
211929
212013
  init_package_managers();
@@ -212208,6 +212292,9 @@ function templateHasPersistenceSync2(templateId, { compoundPersistenceEnabled =
212208
212292
  return templateId === "persistence" || templateId === "compound" && compoundPersistenceEnabled;
212209
212293
  }
212210
212294
  function getOptionalSyncScriptNames(templateId, options = {}) {
212295
+ if (templateId === "query-loop") {
212296
+ return [];
212297
+ }
212211
212298
  const availableScripts = new Set(options.availableScripts ?? []);
212212
212299
  if (availableScripts.has("sync")) {
212213
212300
  return ["sync"];
@@ -212225,6 +212312,9 @@ function getOptionalOnboardingSteps(packageManager, templateId, options = {}) {
212225
212312
  return getOptionalSyncScriptNames(templateId, options).map((scriptName) => formatRunScript2(packageManager, scriptName));
212226
212313
  }
212227
212314
  function getQuickStartWorkflowNote(packageManager, templateId = "basic", options = {}) {
212315
+ if (templateId === "query-loop") {
212316
+ return `${formatRunScript2(packageManager, "start")} runs the editor build/watch loop that registers your Query Loop variation in the block editor. This scaffold is editor-facing by design: update \`src/index.ts\` when you want to change the variation namespace, default query, allowed controls, or the minimal inline starter layout, update \`src/patterns/*.php\` when you want richer connected layout presets in the inserter, use \`src/query-extension.ts\` when the variation needs custom query params or optional editor-side hooks, and mirror frontend/editor preview query mapping in \`inc/query-runtime.php\`.`;
212317
+ }
212228
212318
  const developmentScript = getPrimaryDevelopmentScript(templateId);
212229
212319
  const devCommand = formatRunScript2(packageManager, developmentScript);
212230
212320
  const startCommand = formatRunScript2(packageManager, "start");
@@ -212240,6 +212330,9 @@ function getQuickStartWorkflowNote(packageManager, templateId = "basic", options
212240
212330
  return `${devCommand} keeps the editor and type-derived artifacts moving together during local development. Use ${startCommand} when you want a one-shot sync plus editor startup without the long-running watch loop.`;
212241
212331
  }
212242
212332
  function getOptionalOnboardingNote(packageManager, templateId = "basic", options = {}) {
212333
+ if (templateId === "query-loop") {
212334
+ return `This scaffold does not generate \`block.json\` or Typia manifests. Edit \`src/index.ts\` to change the variation contract, edit \`src/patterns/*.php\` when you want richer connected layouts beyond the inline fallback, edit \`src/query-extension.ts\` when you need variation-specific query params or custom editor hooks, and edit \`inc/query-runtime.php\` when those params need frontend or editor preview parity. Then rerun ${formatRunScript2(packageManager, "build")}, ${formatRunScript2(packageManager, "start")}, or ${formatRunScript2(packageManager, "typecheck")} as needed.`;
212335
+ }
212243
212336
  const optionalSyncScripts = getOptionalSyncScriptNames(templateId, options);
212244
212337
  const hasUnifiedSync = optionalSyncScripts.includes("sync");
212245
212338
  const syncSteps = optionalSyncScripts.map((scriptName) => formatRunScript2(packageManager, scriptName));
@@ -212269,6 +212362,9 @@ function getInitialCommitNote() {
212269
212362
  return "Skip `git init` if this directory already lives inside an existing repository. If you want generated artifacts refreshed before the first checkpoint, run your manual sync step first and then create the commit.";
212270
212363
  }
212271
212364
  function getTemplateSourceOfTruthNote(templateId, { compoundPersistenceEnabled = false } = {}) {
212365
+ if (templateId === "query-loop") {
212366
+ return "`src/index.ts` remains the source of truth for the Query Loop variation name, default query attributes, `allowedControls`, and the minimal inline starter `innerBlocks`. Use `src/patterns/*.php` for richer connected layout presets that stay tied to the same variation namespace, use `src/query-extension.ts` for custom query seed values or optional editor-only hook registration, and use `inc/query-runtime.php` to keep frontend and editor preview query mapping aligned for those custom keys. The generated plugin bootstrap should stay focused on script registration, pattern loading, and explicit runtime glue for the variation.";
212367
+ }
212272
212368
  if (templateId === "compound") {
212273
212369
  const compoundBase = "`src/blocks/*/types.ts` files remain the source of truth for each block's `block.json`, `typia.manifest.json`, and `typia-validator.php`. Fresh scaffolds include starter `typia.manifest.json` files so editor imports resolve before the first sync.";
212274
212370
  if (compoundPersistenceEnabled) {
@@ -212351,6 +212447,176 @@ var init_scaffold_onboarding = __esm(() => {
212351
212447
  ];
212352
212448
  });
212353
212449
 
212450
+ // ../wp-typia-project-tools/src/runtime/scaffold-documents.ts
212451
+ function buildReadme(templateId, variables, packageManager, {
212452
+ withMigrationUi = false,
212453
+ withTestPreset = false,
212454
+ withWpEnv = false
212455
+ } = {}) {
212456
+ const optionalOnboardingSteps = getOptionalOnboardingSteps(packageManager, templateId, {
212457
+ compoundPersistenceEnabled: variables.compoundPersistenceEnabled === "true"
212458
+ });
212459
+ const initialCommitCommands = getInitialCommitCommands();
212460
+ const sourceOfTruthNote = getTemplateSourceOfTruthNote(templateId, {
212461
+ compoundPersistenceEnabled: variables.compoundPersistenceEnabled === "true"
212462
+ });
212463
+ const compoundPersistenceEnabled = variables.compoundPersistenceEnabled === "true";
212464
+ const publicPersistencePolicyNote = variables.isPublicPersistencePolicy === "true" ? "Public persistence writes use signed short-lived tokens, per-request ids, and coarse rate limiting by default. Add application-specific abuse controls before using the same pattern for high-value metrics or experiments." : null;
212465
+ const compoundExtensionWorkflowSection = getCompoundExtensionWorkflowSection(packageManager, templateId);
212466
+ const phpRestExtensionPointsSection = getPhpRestExtensionPointsSection(templateId, {
212467
+ compoundPersistenceEnabled,
212468
+ slug: variables.slug
212469
+ });
212470
+ const developmentScript = getPrimaryDevelopmentScript(templateId);
212471
+ const wpEnvSection = withWpEnv ? `## Local WordPress
212472
+
212473
+ \`\`\`bash
212474
+ ${formatRunScript2(packageManager, "wp-env:start")}
212475
+ ${formatRunScript2(packageManager, "wp-env:stop")}
212476
+ ${formatRunScript2(packageManager, "wp-env:reset")}
212477
+ \`\`\`` : "";
212478
+ const testPresetSection = withTestPreset ? `## Local Test Preset
212479
+
212480
+ \`\`\`bash
212481
+ ${formatRunScript2(packageManager, "wp-env:start:test")}
212482
+ ${formatRunScript2(packageManager, "wp-env:wait:test")}
212483
+ ${formatRunScript2(packageManager, "test:e2e")}
212484
+ \`\`\`
212485
+
212486
+ The generated smoke test uses \`.wp-env.test.json\` and verifies that the scaffolded block registers in the WordPress editor.` : "";
212487
+ const migrationSection = withMigrationUi ? `## Migration UI
212488
+
212489
+ This scaffold already includes an initialized migration workspace at \`v1\`, generated deprecated/runtime artifacts, and an editor-embedded migration dashboard. Migration versions are schema lineage labels and are separate from your package or plugin release version. Use the existing CLI commands to snapshot, diff, scaffold, verify, and fuzz future schema changes.
212490
+
212491
+ \`\`\`bash
212492
+ ${formatRunScript2(packageManager, "migration:doctor")}
212493
+ ${formatRunScript2(packageManager, "migration:verify")}
212494
+ ${formatRunScript2(packageManager, "migration:fuzz")}
212495
+ \`\`\`
212496
+
212497
+ Run \`migration:init\` only when retrofitting migration support into an older project that was not scaffolded with \`--with-migration-ui\`.` : "";
212498
+ const advancedSyncSection = optionalOnboardingSteps.length > 0 ? `## Advanced Sync
212499
+
212500
+ \`\`\`bash
212501
+ ${optionalOnboardingSteps.join(`
212502
+ `)}
212503
+ \`\`\`
212504
+
212505
+ ${getOptionalOnboardingNote(packageManager, templateId, {
212506
+ compoundPersistenceEnabled
212507
+ })}` : `## Artifact Refresh
212508
+
212509
+ ${getOptionalOnboardingNote(packageManager, templateId, {
212510
+ compoundPersistenceEnabled
212511
+ })}`;
212512
+ return `# ${variables.title}
212513
+
212514
+ ${variables.description}
212515
+
212516
+ ## Template
212517
+
212518
+ ${templateId}
212519
+
212520
+ ## Quick Start
212521
+
212522
+ \`\`\`bash
212523
+ ${formatInstallCommand(packageManager)}
212524
+ ${formatRunScript2(packageManager, developmentScript)}
212525
+ \`\`\`
212526
+
212527
+ ${getQuickStartWorkflowNote(packageManager, templateId, {
212528
+ compoundPersistenceEnabled
212529
+ })}
212530
+
212531
+ ## Build and Verify
212532
+
212533
+ \`\`\`bash
212534
+ ${formatRunScript2(packageManager, "build")}
212535
+ ${formatRunScript2(packageManager, "typecheck")}
212536
+ \`\`\`
212537
+
212538
+ ${advancedSyncSection}
212539
+
212540
+ ## Before First Commit
212541
+
212542
+ \`\`\`bash
212543
+ ${initialCommitCommands.join(`
212544
+ `)}
212545
+ \`\`\`
212546
+
212547
+ ${getInitialCommitNote()}
212548
+
212549
+ ${sourceOfTruthNote}${publicPersistencePolicyNote ? `
212550
+
212551
+ ${publicPersistencePolicyNote}` : ""}${migrationSection ? `
212552
+
212553
+ ${migrationSection}` : ""}${compoundExtensionWorkflowSection ? `
212554
+
212555
+ ${compoundExtensionWorkflowSection}` : ""}${wpEnvSection ? `
212556
+
212557
+ ${wpEnvSection}` : ""}${testPresetSection ? `
212558
+
212559
+ ${testPresetSection}` : ""}${phpRestExtensionPointsSection ? `
212560
+
212561
+ ${phpRestExtensionPointsSection}` : ""}
212562
+ `;
212563
+ }
212564
+ function buildGitignore() {
212565
+ return `# Dependencies
212566
+ node_modules/
212567
+ .yarn/
212568
+ .pnp.*
212569
+
212570
+ # Build
212571
+ build/
212572
+ dist/
212573
+
212574
+ # Editor
212575
+ .vscode/
212576
+ .idea/
212577
+
212578
+ # OS
212579
+ .DS_Store
212580
+ Thumbs.db
212581
+
212582
+ # WordPress
212583
+ *.log
212584
+ .wp-env/
212585
+ `;
212586
+ }
212587
+ function mergeTextLines(primaryContent, existingContent) {
212588
+ const normalizedPrimary = primaryContent.replace(/\r\n/g, `
212589
+ `).trimEnd();
212590
+ const normalizedExisting = existingContent.replace(/\r\n/g, `
212591
+ `).trimEnd();
212592
+ const mergedLines = [];
212593
+ const seen = new Set;
212594
+ for (const line of [...normalizedPrimary.split(`
212595
+ `), ...normalizedExisting.split(`
212596
+ `)]) {
212597
+ if (line.length === 0 && mergedLines[mergedLines.length - 1] === "") {
212598
+ continue;
212599
+ }
212600
+ if (line.length > 0 && seen.has(line)) {
212601
+ continue;
212602
+ }
212603
+ if (line.length > 0) {
212604
+ seen.add(line);
212605
+ }
212606
+ mergedLines.push(line);
212607
+ }
212608
+ return `${mergedLines.join(`
212609
+ `).replace(/\n{3,}/g, `
212610
+
212611
+ `)}
212612
+ `;
212613
+ }
212614
+ var init_scaffold_documents = __esm(() => {
212615
+ init_local_dev_presets();
212616
+ init_scaffold_onboarding();
212617
+ init_package_managers();
212618
+ });
212619
+
212354
212620
  // ../wp-typia-project-tools/src/runtime/built-in-block-attribute-emitters.ts
212355
212621
  function createConstraints(overrides = {}) {
212356
212622
  return {
@@ -213488,164 +213754,6 @@ async function ensureDirectory(targetDir, allowExisting = false) {
213488
213754
  throw new Error(`Target directory is not empty: ${targetDir}`);
213489
213755
  }
213490
213756
  }
213491
- function buildReadme(templateId, variables, packageManager, {
213492
- withMigrationUi = false,
213493
- withTestPreset = false,
213494
- withWpEnv = false
213495
- } = {}) {
213496
- const optionalOnboardingSteps = getOptionalOnboardingSteps(packageManager, templateId, {
213497
- compoundPersistenceEnabled: variables.compoundPersistenceEnabled === "true"
213498
- });
213499
- const initialCommitCommands = getInitialCommitCommands();
213500
- const sourceOfTruthNote = getTemplateSourceOfTruthNote(templateId, {
213501
- compoundPersistenceEnabled: variables.compoundPersistenceEnabled === "true"
213502
- });
213503
- const compoundPersistenceEnabled = variables.compoundPersistenceEnabled === "true";
213504
- const publicPersistencePolicyNote = variables.isPublicPersistencePolicy === "true" ? "Public persistence writes use signed short-lived tokens, per-request ids, and coarse rate limiting by default. Add application-specific abuse controls before using the same pattern for high-value metrics or experiments." : null;
213505
- const compoundExtensionWorkflowSection = getCompoundExtensionWorkflowSection(packageManager, templateId);
213506
- const phpRestExtensionPointsSection = getPhpRestExtensionPointsSection(templateId, {
213507
- compoundPersistenceEnabled,
213508
- slug: variables.slug
213509
- });
213510
- const developmentScript = getPrimaryDevelopmentScript(templateId);
213511
- const wpEnvSection = withWpEnv ? `## Local WordPress
213512
-
213513
- \`\`\`bash
213514
- ${formatRunScript2(packageManager, "wp-env:start")}
213515
- ${formatRunScript2(packageManager, "wp-env:stop")}
213516
- ${formatRunScript2(packageManager, "wp-env:reset")}
213517
- \`\`\`` : "";
213518
- const testPresetSection = withTestPreset ? `## Local Test Preset
213519
-
213520
- \`\`\`bash
213521
- ${formatRunScript2(packageManager, "wp-env:start:test")}
213522
- ${formatRunScript2(packageManager, "wp-env:wait:test")}
213523
- ${formatRunScript2(packageManager, "test:e2e")}
213524
- \`\`\`
213525
-
213526
- The generated smoke test uses \`.wp-env.test.json\` and verifies that the scaffolded block registers in the WordPress editor.` : "";
213527
- const migrationSection = withMigrationUi ? `## Migration UI
213528
-
213529
- This scaffold already includes an initialized migration workspace at \`v1\`, generated deprecated/runtime artifacts, and an editor-embedded migration dashboard. Migration versions are schema lineage labels and are separate from your package or plugin release version. Use the existing CLI commands to snapshot, diff, scaffold, verify, and fuzz future schema changes.
213530
-
213531
- \`\`\`bash
213532
- ${formatRunScript2(packageManager, "migration:doctor")}
213533
- ${formatRunScript2(packageManager, "migration:verify")}
213534
- ${formatRunScript2(packageManager, "migration:fuzz")}
213535
- \`\`\`
213536
-
213537
- Run \`migration:init\` only when retrofitting migration support into an older project that was not scaffolded with \`--with-migration-ui\`.` : "";
213538
- return `# ${variables.title}
213539
-
213540
- ${variables.description}
213541
-
213542
- ## Template
213543
-
213544
- ${templateId}
213545
-
213546
- ## Quick Start
213547
-
213548
- \`\`\`bash
213549
- ${formatInstallCommand(packageManager)}
213550
- ${formatRunScript2(packageManager, developmentScript)}
213551
- \`\`\`
213552
-
213553
- ${getQuickStartWorkflowNote(packageManager, templateId, {
213554
- compoundPersistenceEnabled
213555
- })}
213556
-
213557
- ## Build and Verify
213558
-
213559
- \`\`\`bash
213560
- ${formatRunScript2(packageManager, "build")}
213561
- ${formatRunScript2(packageManager, "typecheck")}
213562
- \`\`\`
213563
-
213564
- ## Advanced Sync
213565
-
213566
- \`\`\`bash
213567
- ${optionalOnboardingSteps.join(`
213568
- `)}
213569
- \`\`\`
213570
-
213571
- ${getOptionalOnboardingNote(packageManager, templateId, {
213572
- compoundPersistenceEnabled
213573
- })}
213574
-
213575
- ## Before First Commit
213576
-
213577
- \`\`\`bash
213578
- ${initialCommitCommands.join(`
213579
- `)}
213580
- \`\`\`
213581
-
213582
- ${getInitialCommitNote()}
213583
-
213584
- ${sourceOfTruthNote}${publicPersistencePolicyNote ? `
213585
-
213586
- ${publicPersistencePolicyNote}` : ""}${migrationSection ? `
213587
-
213588
- ${migrationSection}` : ""}${compoundExtensionWorkflowSection ? `
213589
-
213590
- ${compoundExtensionWorkflowSection}` : ""}${wpEnvSection ? `
213591
-
213592
- ${wpEnvSection}` : ""}${testPresetSection ? `
213593
-
213594
- ${testPresetSection}` : ""}${phpRestExtensionPointsSection ? `
213595
-
213596
- ${phpRestExtensionPointsSection}` : ""}
213597
- `;
213598
- }
213599
- function buildGitignore() {
213600
- return `# Dependencies
213601
- node_modules/
213602
- .yarn/
213603
- .pnp.*
213604
-
213605
- # Build
213606
- build/
213607
- dist/
213608
-
213609
- # Editor
213610
- .vscode/
213611
- .idea/
213612
-
213613
- # OS
213614
- .DS_Store
213615
- Thumbs.db
213616
-
213617
- # WordPress
213618
- *.log
213619
- .wp-env/
213620
- `;
213621
- }
213622
- function mergeTextLines(primaryContent, existingContent) {
213623
- const normalizedPrimary = primaryContent.replace(/\r\n/g, `
213624
- `).trimEnd();
213625
- const normalizedExisting = existingContent.replace(/\r\n/g, `
213626
- `).trimEnd();
213627
- const mergedLines = [];
213628
- const seen = new Set;
213629
- for (const line of [...normalizedPrimary.split(`
213630
- `), ...normalizedExisting.split(`
213631
- `)]) {
213632
- if (line.length === 0 && mergedLines[mergedLines.length - 1] === "") {
213633
- continue;
213634
- }
213635
- if (line.length > 0 && seen.has(line)) {
213636
- continue;
213637
- }
213638
- if (line.length > 0) {
213639
- seen.add(line);
213640
- }
213641
- mergedLines.push(line);
213642
- }
213643
- return `${mergedLines.join(`
213644
- `).replace(/\n{3,}/g, `
213645
-
213646
- `)}
213647
- `;
213648
- }
213649
213757
  async function writeStarterManifestFiles(targetDir, templateId, variables, artifacts) {
213650
213758
  const manifests = artifacts ? artifacts.map((artifact) => ({
213651
213759
  document: artifact.manifestDocument,
@@ -213898,13 +214006,14 @@ var init_scaffold_apply_utils = __esm(() => {
213898
214006
  init_package_versions();
213899
214007
  init_migration_project();
213900
214008
  init_persistence_rest_artifacts();
213901
- init_scaffold_onboarding();
214009
+ init_scaffold_documents();
213902
214010
  init_starter_manifests();
213903
214011
  init_built_in_block_artifacts();
213904
214012
  init_template_registry();
213905
214013
  init_template_render();
213906
214014
  init_package_managers();
213907
214015
  init_scaffold_repository_reference();
214016
+ init_scaffold_documents();
213908
214017
  EPHEMERAL_NODE_MODULES_LINK_TYPE = process.platform === "win32" ? "junction" : "dir";
213909
214018
  __dirname4 = path31.dirname(fileURLToPath4(import.meta.url));
213910
214019
  LOCKFILES = {
@@ -213915,76 +214024,6 @@ var init_scaffold_apply_utils = __esm(() => {
213915
214024
  };
213916
214025
  });
213917
214026
 
213918
- // ../wp-typia-project-tools/src/runtime/scaffold-identifiers.ts
213919
- function validateBlockSlug(input) {
213920
- return BLOCK_SLUG_PATTERN.test(input) || "Use lowercase letters, numbers, and hyphens only";
213921
- }
213922
- function validateNamespace(input) {
213923
- return BLOCK_SLUG_PATTERN.test(toKebabCase(input)) ? true : "Use lowercase letters, numbers, and hyphens only";
213924
- }
213925
- function validateTextDomain(input) {
213926
- return BLOCK_SLUG_PATTERN.test(toKebabCase(input)) ? true : "Use lowercase letters, numbers, and hyphens only";
213927
- }
213928
- function validatePhpPrefix(input) {
213929
- const normalizedPrefix = toSnakeCase(input);
213930
- if (normalizedPrefix.length > PHP_PREFIX_MAX_LENGTH) {
213931
- return `Use ${PHP_PREFIX_MAX_LENGTH} characters or fewer to keep generated database identifiers within MySQL limits`;
213932
- }
213933
- return PHP_PREFIX_PATTERN.test(normalizedPrefix) ? true : "Use letters, numbers, and underscores only, starting with a letter";
213934
- }
213935
- function assertValidIdentifier(label, value2, validate) {
213936
- const result = validate(value2);
213937
- if (result !== true) {
213938
- throw new Error(typeof result === "string" ? `${label}: ${result}` : `${label} is invalid`);
213939
- }
213940
- return value2;
213941
- }
213942
- function normalizeBlockSlug2(input) {
213943
- return toKebabCase(input);
213944
- }
213945
- function resolveValidatedBlockSlug(value2) {
213946
- return assertValidIdentifier("Block slug", normalizeBlockSlug2(value2), validateBlockSlug);
213947
- }
213948
- function resolveValidatedNamespace(value2) {
213949
- return assertValidIdentifier("Namespace", toKebabCase(value2), validateNamespace);
213950
- }
213951
- function resolveValidatedTextDomain(value2) {
213952
- return assertValidIdentifier("Text domain", toKebabCase(value2), validateTextDomain);
213953
- }
213954
- function resolveValidatedPhpPrefix(value2) {
213955
- return assertValidIdentifier("PHP prefix", toSnakeCase(value2), validatePhpPrefix);
213956
- }
213957
- function buildBlockCssClassName(namespace, slug) {
213958
- const normalizedSlug = resolveValidatedBlockSlug(slug);
213959
- const normalizedNamespace = typeof namespace === "string" && namespace.trim().length > 0 ? resolveValidatedNamespace(namespace) : "";
213960
- if (normalizedNamespace === normalizedSlug) {
213961
- return `wp-block-${normalizedSlug}-block`;
213962
- }
213963
- return normalizedNamespace.length > 0 ? `wp-block-${normalizedNamespace}-${normalizedSlug}` : `wp-block-${normalizedSlug}`;
213964
- }
213965
- function buildFrontendCssClassName(blockCssClassName) {
213966
- return `${blockCssClassName}-frontend`;
213967
- }
213968
- function resolveScaffoldIdentifiers({
213969
- namespace,
213970
- phpPrefix,
213971
- slug,
213972
- textDomain
213973
- }) {
213974
- const normalizedSlug = resolveValidatedBlockSlug(slug);
213975
- return {
213976
- namespace: resolveValidatedNamespace(namespace),
213977
- phpPrefix: resolveValidatedPhpPrefix(phpPrefix ?? normalizedSlug),
213978
- slug: normalizedSlug,
213979
- textDomain: resolveValidatedTextDomain(textDomain ?? normalizedSlug)
213980
- };
213981
- }
213982
- var BLOCK_SLUG_PATTERN, PHP_PREFIX_PATTERN, PHP_PREFIX_MAX_LENGTH = 50;
213983
- var init_scaffold_identifiers = __esm(() => {
213984
- BLOCK_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/;
213985
- PHP_PREFIX_PATTERN = /^[a-z_][a-z0-9_]*$/;
213986
- });
213987
-
213988
214027
  // ../wp-typia-project-tools/src/runtime/scaffold-bootstrap.ts
213989
214028
  import fs24 from "fs";
213990
214029
  import { promises as fsp6 } from "fs";
@@ -221994,6 +222033,76 @@ var init_template_source = __esm(() => {
221994
222033
  init_template_source_seeds();
221995
222034
  });
221996
222035
 
222036
+ // ../wp-typia-project-tools/src/runtime/scaffold-identifiers.ts
222037
+ function validateBlockSlug(input) {
222038
+ return BLOCK_SLUG_PATTERN.test(input) || "Use lowercase letters, numbers, and hyphens only";
222039
+ }
222040
+ function validateNamespace(input) {
222041
+ return BLOCK_SLUG_PATTERN.test(toKebabCase(input)) ? true : "Use lowercase letters, numbers, and hyphens only";
222042
+ }
222043
+ function validateTextDomain(input) {
222044
+ return BLOCK_SLUG_PATTERN.test(toKebabCase(input)) ? true : "Use lowercase letters, numbers, and hyphens only";
222045
+ }
222046
+ function validatePhpPrefix(input) {
222047
+ const normalizedPrefix = toSnakeCase(input);
222048
+ if (normalizedPrefix.length > PHP_PREFIX_MAX_LENGTH) {
222049
+ return `Use ${PHP_PREFIX_MAX_LENGTH} characters or fewer to keep generated database identifiers within MySQL limits`;
222050
+ }
222051
+ return PHP_PREFIX_PATTERN.test(normalizedPrefix) ? true : "Use letters, numbers, and underscores only, starting with a letter";
222052
+ }
222053
+ function assertValidIdentifier(label, value2, validate) {
222054
+ const result = validate(value2);
222055
+ if (result !== true) {
222056
+ throw new Error(typeof result === "string" ? `${label}: ${result}` : `${label} is invalid`);
222057
+ }
222058
+ return value2;
222059
+ }
222060
+ function normalizeBlockSlug2(input) {
222061
+ return toKebabCase(input);
222062
+ }
222063
+ function resolveValidatedBlockSlug(value2) {
222064
+ return assertValidIdentifier("Block slug", normalizeBlockSlug2(value2), validateBlockSlug);
222065
+ }
222066
+ function resolveValidatedNamespace(value2) {
222067
+ return assertValidIdentifier("Namespace", toKebabCase(value2), validateNamespace);
222068
+ }
222069
+ function resolveValidatedTextDomain(value2) {
222070
+ return assertValidIdentifier("Text domain", toKebabCase(value2), validateTextDomain);
222071
+ }
222072
+ function resolveValidatedPhpPrefix(value2) {
222073
+ return assertValidIdentifier("PHP prefix", toSnakeCase(value2), validatePhpPrefix);
222074
+ }
222075
+ function buildBlockCssClassName(namespace, slug) {
222076
+ const normalizedSlug = resolveValidatedBlockSlug(slug);
222077
+ const normalizedNamespace = typeof namespace === "string" && namespace.trim().length > 0 ? resolveValidatedNamespace(namespace) : "";
222078
+ if (normalizedNamespace === normalizedSlug) {
222079
+ return `wp-block-${normalizedSlug}-block`;
222080
+ }
222081
+ return normalizedNamespace.length > 0 ? `wp-block-${normalizedNamespace}-${normalizedSlug}` : `wp-block-${normalizedSlug}`;
222082
+ }
222083
+ function buildFrontendCssClassName(blockCssClassName) {
222084
+ return `${blockCssClassName}-frontend`;
222085
+ }
222086
+ function resolveScaffoldIdentifiers({
222087
+ namespace,
222088
+ phpPrefix,
222089
+ slug,
222090
+ textDomain
222091
+ }) {
222092
+ const normalizedSlug = resolveValidatedBlockSlug(slug);
222093
+ return {
222094
+ namespace: resolveValidatedNamespace(namespace),
222095
+ phpPrefix: resolveValidatedPhpPrefix(phpPrefix ?? normalizedSlug),
222096
+ slug: normalizedSlug,
222097
+ textDomain: resolveValidatedTextDomain(textDomain ?? normalizedSlug)
222098
+ };
222099
+ }
222100
+ var BLOCK_SLUG_PATTERN, PHP_PREFIX_PATTERN, PHP_PREFIX_MAX_LENGTH = 50;
222101
+ var init_scaffold_identifiers = __esm(() => {
222102
+ BLOCK_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/;
222103
+ PHP_PREFIX_PATTERN = /^[a-z_][a-z0-9_]*$/;
222104
+ });
222105
+
221997
222106
  // ../wp-typia-project-tools/src/runtime/block-generator-service-spec.ts
221998
222107
  function getBuiltInPersistenceSpec({
221999
222108
  templateId,
@@ -222056,6 +222165,15 @@ function createBuiltInBlockSpec({
222056
222165
  project: {
222057
222166
  author: answers.author.trim()
222058
222167
  },
222168
+ queryLoop: templateId === "query-loop" ? {
222169
+ allowedControls: DEFAULT_QUERY_LOOP_ALLOWED_CONTROLS,
222170
+ enabled: true,
222171
+ postType: (answers.queryPostType ?? "post").trim() || "post"
222172
+ } : {
222173
+ allowedControls: [],
222174
+ enabled: false,
222175
+ postType: "post"
222176
+ },
222059
222177
  runtime: {
222060
222178
  withMigrationUi,
222061
222179
  withTestPreset,
@@ -222090,6 +222208,7 @@ function buildTemplateVariablesFromBlockSpec(spec) {
222090
222208
  const persistenceEnabled = spec.persistence.enabled;
222091
222209
  const dataStorageMode = persistenceEnabled ? spec.persistence.dataStorageMode : "custom-table";
222092
222210
  const persistencePolicy = persistenceEnabled ? spec.persistence.persistencePolicy : "authenticated";
222211
+ const queryVariationNamespace = `${namespace}/${slug}`;
222093
222212
  return {
222094
222213
  apiClientPackageVersion,
222095
222214
  author: spec.project.author,
@@ -222109,7 +222228,13 @@ function buildTemplateVariablesFromBlockSpec(spec) {
222109
222228
  dashCase: slug,
222110
222229
  dataStorageMode,
222111
222230
  description: spec.metadata.description,
222231
+ descriptionJson: JSON.stringify(spec.metadata.description),
222112
222232
  frontendCssClassName: buildFrontendCssClassName(cssClassName),
222233
+ queryAllowedControlsJson: JSON.stringify(spec.queryLoop.enabled ? spec.queryLoop.allowedControls : [], null, 2),
222234
+ queryPostType: spec.queryLoop.enabled ? spec.queryLoop.postType : "post",
222235
+ queryPostTypeJson: JSON.stringify(spec.queryLoop.enabled ? spec.queryLoop.postType : "post"),
222236
+ queryVariationNamespace,
222237
+ queryVariationNamespaceJson: JSON.stringify(queryVariationNamespace),
222113
222238
  isAuthenticatedPersistencePolicy: persistencePolicy === "authenticated" ? "true" : "false",
222114
222239
  isPublicPersistencePolicy: persistencePolicy === "public" ? "true" : "false",
222115
222240
  bootstrapCredentialDeclarations: persistencePolicy === "public" ? `publicWriteExpiresAt?: number & tags.Type< 'uint32' >;
@@ -222138,11 +222263,21 @@ function buildTemplateVariablesFromBlockSpec(spec) {
222138
222263
  persistencePolicy
222139
222264
  };
222140
222265
  }
222266
+ var DEFAULT_QUERY_LOOP_ALLOWED_CONTROLS;
222141
222267
  var init_block_generator_service_spec = __esm(() => {
222142
222268
  init_package_versions();
222143
222269
  init_template_defaults();
222144
222270
  init_template_registry();
222145
222271
  init_scaffold_identifiers();
222272
+ DEFAULT_QUERY_LOOP_ALLOWED_CONTROLS = [
222273
+ "inherit",
222274
+ "postType",
222275
+ "order",
222276
+ "sticky",
222277
+ "taxQuery",
222278
+ "author",
222279
+ "search"
222280
+ ];
222146
222281
  });
222147
222282
 
222148
222283
  // ../wp-typia-project-tools/src/runtime/built-in-block-non-ts-artifacts.ts
@@ -222356,6 +222491,8 @@ function buildBuiltInNonTsArtifacts({
222356
222491
  return buildPersistenceArtifacts(variables);
222357
222492
  case "compound":
222358
222493
  return buildCompoundArtifacts(variables);
222494
+ case "query-loop":
222495
+ return [];
222359
222496
  default: {
222360
222497
  const unhandledTemplateId = templateId;
222361
222498
  throw new Error(`Unhandled built-in template id: ${unhandledTemplateId}`);
@@ -224080,6 +224217,78 @@ const { actions, state } = store( '{{slugKebabCase}}', {
224080
224217
  } );
224081
224218
  `;
224082
224219
 
224220
+ // ../wp-typia-project-tools/src/runtime/built-in-block-code-templates/query-loop.ts
224221
+ var QUERY_LOOP_INDEX_TEMPLATE = `import { registerBlockVariation } from '@wordpress/blocks';
224222
+ import type { BlockVariation } from '@wp-typia/block-types/blocks/registration';
224223
+ import { __ } from '@wordpress/i18n';
224224
+ import {
224225
+ getQueryLoopCustomAllowedControls,
224226
+ getQueryLoopCustomQuerySeed,
224227
+ registerQueryLoopEditorExtensions,
224228
+ } from './query-extension';
224229
+
224230
+ type QueryLoopVariationAttributes = {
224231
+ namespace?: string;
224232
+ query?: {
224233
+ inherit?: boolean;
224234
+ order?: 'asc' | 'desc';
224235
+ orderBy?: string;
224236
+ perPage?: number;
224237
+ postType?: string;
224238
+ wpTypiaVariation?: string;
224239
+ [key: string]: unknown;
224240
+ };
224241
+ };
224242
+
224243
+ type QueryLoopVariation = BlockVariation<QueryLoopVariationAttributes> & {
224244
+ allowedControls: string[];
224245
+ };
224246
+
224247
+ const VARIATION_NAME = {{queryVariationNamespaceJson}};
224248
+ const DEFAULT_ALLOWED_CONTROLS = {{queryAllowedControlsJson}};
224249
+ const customQuerySeed = getQueryLoopCustomQuerySeed();
224250
+ const allowedControls = Array.from(
224251
+ new Set([...DEFAULT_ALLOWED_CONTROLS, ...getQueryLoopCustomAllowedControls()]),
224252
+ );
224253
+
224254
+ const queryLoopVariation = {
224255
+ name: VARIATION_NAME,
224256
+ title: __({{titleJson}}, '{{textDomain}}'),
224257
+ description: __({{descriptionJson}}, '{{textDomain}}'),
224258
+ scope: ['inserter'],
224259
+ isActive: ['namespace'],
224260
+ attributes: {
224261
+ namespace: VARIATION_NAME,
224262
+ query: {
224263
+ inherit: false,
224264
+ order: 'desc',
224265
+ orderBy: 'date',
224266
+ perPage: 6,
224267
+ postType: {{queryPostTypeJson}},
224268
+ ...customQuerySeed,
224269
+ wpTypiaVariation: VARIATION_NAME,
224270
+ },
224271
+ },
224272
+ allowedControls,
224273
+ innerBlocks: [
224274
+ [
224275
+ 'core/post-template',
224276
+ {},
224277
+ [
224278
+ ['core/post-featured-image'],
224279
+ ['core/post-title', { isLink: true }],
224280
+ ['core/post-excerpt'],
224281
+ ],
224282
+ ],
224283
+ ['core/query-pagination'],
224284
+ ['core/query-no-results'],
224285
+ ],
224286
+ } satisfies QueryLoopVariation;
224287
+
224288
+ registerBlockVariation('core/query', queryLoopVariation);
224289
+ registerQueryLoopEditorExtensions({ variationName: VARIATION_NAME });
224290
+ `;
224291
+
224083
224292
  // ../wp-typia-project-tools/src/runtime/built-in-block-code-templates/compound-parent.ts
224084
224293
  var COMPOUND_PARENT_EDIT_TEMPLATE = `import type { BlockEditProps } from '@wp-typia/block-types/blocks/registration';
224085
224294
  import { __ } from '@wordpress/i18n';
@@ -225082,6 +225291,17 @@ function buildPersistenceCodeArtifacts(variables) {
225082
225291
  ...buildBuiltInNonTsArtifacts({ templateId: "persistence", variables })
225083
225292
  ]);
225084
225293
  }
225294
+ function buildQueryLoopCodeArtifacts(variables) {
225295
+ return ensureUniqueArtifactPaths([
225296
+ ...createCodeArtifacts([
225297
+ {
225298
+ relativePath: "src/index.ts",
225299
+ template: QUERY_LOOP_INDEX_TEMPLATE
225300
+ }
225301
+ ], variables),
225302
+ ...buildBuiltInNonTsArtifacts({ templateId: "query-loop", variables })
225303
+ ]);
225304
+ }
225085
225305
  function buildBuiltInCodeArtifacts({
225086
225306
  templateId,
225087
225307
  variables
@@ -225095,6 +225315,8 @@ function buildBuiltInCodeArtifacts({
225095
225315
  return buildPersistenceCodeArtifacts(variables);
225096
225316
  case "compound":
225097
225317
  return buildCompoundCodeArtifacts(variables);
225318
+ case "query-loop":
225319
+ return buildQueryLoopCodeArtifacts(variables);
225098
225320
  default: {
225099
225321
  const unhandledTemplateId = templateId;
225100
225322
  throw new Error(`Unhandled built-in template id: ${unhandledTemplateId}`);
@@ -225407,17 +225629,8 @@ var init_block_generator_service = __esm(() => {
225407
225629
  init_block_generator_service_core();
225408
225630
  });
225409
225631
 
225410
- // ../wp-typia-project-tools/src/runtime/scaffold.ts
225411
- import fs33 from "fs";
225412
- import { promises as fsp13 } from "fs";
225413
- import path41 from "path";
225632
+ // ../wp-typia-project-tools/src/runtime/scaffold-answer-resolution.ts
225414
225633
  import { execSync as execSync4 } from "child_process";
225415
- function isDataStorageMode(value2) {
225416
- return DATA_STORAGE_MODES.includes(value2);
225417
- }
225418
- function isPersistencePolicy(value2) {
225419
- return PERSISTENCE_POLICIES.includes(value2);
225420
- }
225421
225634
  function detectAuthor() {
225422
225635
  try {
225423
225636
  return execSync4("git config user.name", {
@@ -225438,11 +225651,32 @@ function getDefaultAnswers(projectName, templateId) {
225438
225651
  namespace: slugDefault,
225439
225652
  persistencePolicy: templateId === "persistence" ? "authenticated" : undefined,
225440
225653
  phpPrefix: toSnakeCase(slugDefault),
225654
+ queryPostType: templateId === "query-loop" ? "post" : undefined,
225441
225655
  slug: slugDefault,
225442
225656
  textDomain: slugDefault,
225443
225657
  title: toTitleCase(slugDefault)
225444
225658
  };
225445
225659
  }
225660
+ function validateQueryPostType(value2) {
225661
+ const normalizedValue = value2.trim().toLowerCase();
225662
+ if (normalizedValue.length === 0) {
225663
+ return "Query post type is required.";
225664
+ }
225665
+ if (!/^[a-z0-9_-]{1,20}$/u.test(normalizedValue)) {
225666
+ return 'Query post type must be lowercase, 1-20 chars, and only a-z, 0-9, "_" or "-".';
225667
+ }
225668
+ return true;
225669
+ }
225670
+ function normalizeQueryPostType(value2) {
225671
+ if (typeof value2 !== "string") {
225672
+ return;
225673
+ }
225674
+ const normalizedValue = value2.trim().toLowerCase();
225675
+ if (validateQueryPostType(normalizedValue) !== true) {
225676
+ throw new Error('Query post type must be lowercase, 1-20 chars, and only a-z, 0-9, "_" or "-".');
225677
+ }
225678
+ return normalizedValue;
225679
+ }
225446
225680
  function normalizeTemplateSelection(templateId) {
225447
225681
  return templateId === WORKSPACE_TEMPLATE_ALIAS ? OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE : templateId;
225448
225682
  }
@@ -225496,6 +225730,7 @@ async function collectScaffoldAnswers({
225496
225730
  persistencePolicy,
225497
225731
  phpPrefix,
225498
225732
  promptText,
225733
+ queryPostType,
225499
225734
  textDomain
225500
225735
  }) {
225501
225736
  const defaults = getDefaultAnswers(projectName, templateId);
@@ -225512,6 +225747,7 @@ async function collectScaffoldAnswers({
225512
225747
  namespace: identifiers2.namespace,
225513
225748
  persistencePolicy: persistencePolicy ?? defaults.persistencePolicy,
225514
225749
  phpPrefix: identifiers2.phpPrefix,
225750
+ queryPostType: normalizeQueryPostType(queryPostType ?? defaults.queryPostType),
225515
225751
  textDomain: identifiers2.textDomain
225516
225752
  };
225517
225753
  }
@@ -225531,11 +225767,21 @@ async function collectScaffoldAnswers({
225531
225767
  namespace: identifiers.namespace,
225532
225768
  persistencePolicy: persistencePolicy ?? defaults.persistencePolicy,
225533
225769
  phpPrefix: identifiers.phpPrefix,
225770
+ queryPostType: templateId === "query-loop" ? normalizeQueryPostType(await promptText("Query post type", queryPostType ?? defaults.queryPostType ?? "post", validateQueryPostType)) : normalizeQueryPostType(queryPostType ?? defaults.queryPostType),
225534
225771
  slug: identifiers.slug,
225535
225772
  textDomain: identifiers.textDomain,
225536
225773
  title: await promptText("Block title", toTitleCase(identifiers.slug))
225537
225774
  };
225538
225775
  }
225776
+ var WORKSPACE_TEMPLATE_ALIAS = "workspace";
225777
+ var init_scaffold_answer_resolution = __esm(() => {
225778
+ init_package_managers();
225779
+ init_scaffold_identifiers();
225780
+ init_template_registry();
225781
+ init_template_defaults();
225782
+ });
225783
+
225784
+ // ../wp-typia-project-tools/src/runtime/scaffold-template-variables.ts
225539
225785
  function getTemplateVariables(templateId, answers) {
225540
225786
  if (isBuiltInTemplateId(templateId)) {
225541
225787
  return buildTemplateVariablesFromBlockSpec(createBuiltInBlockSpec({
@@ -225594,7 +225840,13 @@ function getTemplateVariables(templateId, answers) {
225594
225840
  dataStorageMode,
225595
225841
  dashCase: slug,
225596
225842
  description,
225843
+ descriptionJson: JSON.stringify(description),
225597
225844
  frontendCssClassName: buildFrontendCssClassName(cssClassName),
225845
+ queryAllowedControlsJson: JSON.stringify([], null, 2),
225846
+ queryPostType: answers.queryPostType?.trim() || "post",
225847
+ queryPostTypeJson: JSON.stringify(answers.queryPostType?.trim() || "post"),
225848
+ queryVariationNamespace: `${namespace}/${slug}`,
225849
+ queryVariationNamespaceJson: JSON.stringify(`${namespace}/${slug}`),
225598
225850
  isAuthenticatedPersistencePolicy: persistencePolicy === "authenticated" ? "true" : "false",
225599
225851
  isPublicPersistencePolicy: persistencePolicy === "public" ? "true" : "false",
225600
225852
  bootstrapCredentialDeclarations: persistencePolicy === "public" ? `publicWriteExpiresAt?: number & tags.Type< 'uint32' >;
@@ -225623,6 +225875,27 @@ function getTemplateVariables(templateId, answers) {
225623
225875
  persistencePolicy
225624
225876
  };
225625
225877
  }
225878
+ var init_scaffold_template_variables = __esm(() => {
225879
+ init_block_generator_service();
225880
+ init_package_versions();
225881
+ init_scaffold_identifiers();
225882
+ init_template_defaults();
225883
+ init_template_registry();
225884
+ });
225885
+
225886
+ // ../wp-typia-project-tools/src/runtime/scaffold.ts
225887
+ import fs33 from "fs";
225888
+ import { promises as fsp13 } from "fs";
225889
+ import path41 from "path";
225890
+ function isDataStorageMode(value2) {
225891
+ return DATA_STORAGE_MODES.includes(value2);
225892
+ }
225893
+ function isPersistencePolicy(value2) {
225894
+ return PERSISTENCE_POLICIES.includes(value2);
225895
+ }
225896
+ function normalizeTemplateSelection2(templateId) {
225897
+ return templateId === WORKSPACE_TEMPLATE_ALIAS2 ? OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE : templateId;
225898
+ }
225626
225899
  async function scaffoldProject({
225627
225900
  projectDir,
225628
225901
  templateId,
@@ -225643,7 +225916,7 @@ async function scaffoldProject({
225643
225916
  withTestPreset = false,
225644
225917
  withWpEnv = false
225645
225918
  }) {
225646
- const resolvedTemplateId = normalizeTemplateSelection(templateId);
225919
+ const resolvedTemplateId = normalizeTemplateSelection2(templateId);
225647
225920
  const resolvedPackageManager = getPackageManager(packageManager).id;
225648
225921
  const isBuiltInTemplate = isBuiltInTemplateId(resolvedTemplateId);
225649
225922
  if (externalLayerId && !externalLayerSource) {
@@ -225763,22 +226036,23 @@ async function scaffoldProject({
225763
226036
  warnings: templateSource.warnings ?? []
225764
226037
  };
225765
226038
  }
225766
- var WORKSPACE_TEMPLATE_ALIAS = "workspace", DATA_STORAGE_MODES, PERSISTENCE_POLICIES;
226039
+ var WORKSPACE_TEMPLATE_ALIAS2 = "workspace", DATA_STORAGE_MODES, PERSISTENCE_POLICIES;
225767
226040
  var init_scaffold = __esm(() => {
225768
226041
  init_package_managers();
225769
226042
  init_scaffold_apply_utils();
225770
- init_scaffold_identifiers();
225771
226043
  init_local_dev_presets();
225772
226044
  init_migration_ui_capability();
225773
- init_package_versions();
225774
226045
  init_scaffold_bootstrap();
225775
226046
  init_scaffold_package_manager_files();
225776
- init_template_defaults();
225777
226047
  init_template_render();
225778
226048
  init_template_registry();
225779
226049
  init_template_source();
225780
226050
  init_block_generator_service();
226051
+ init_scaffold_answer_resolution();
226052
+ init_scaffold_template_variables();
225781
226053
  init_scaffold_identifiers();
226054
+ init_scaffold_answer_resolution();
226055
+ init_scaffold_template_variables();
225782
226056
  DATA_STORAGE_MODES = ["post-meta", "custom-table"];
225783
226057
  PERSISTENCE_POLICIES = ["authenticated", "public"];
225784
226058
  });
@@ -227811,6 +228085,7 @@ async function runScaffoldFlow({
227811
228085
  namespace,
227812
228086
  textDomain,
227813
228087
  phpPrefix,
228088
+ queryPostType,
227814
228089
  yes = false,
227815
228090
  noInstall = false,
227816
228091
  isInteractive = false,
@@ -227914,6 +228189,7 @@ async function runScaffoldFlow({
227914
228189
  persistencePolicy: resolvedPersistencePolicy,
227915
228190
  phpPrefix,
227916
228191
  projectName,
228192
+ queryPostType,
227917
228193
  templateId: resolvedTemplateId,
227918
228194
  textDomain,
227919
228195
  yes,
@@ -280898,6 +281174,7 @@ async function executeCreateCommand({
280898
281174
  phpPrefix: readOptionalLooseStringFlag(flags2, "php-prefix"),
280899
281175
  projectInput: projectDir,
280900
281176
  promptText: activePrompt ? (message, defaultValue, validate) => activePrompt.text(message, defaultValue, validate) : undefined,
281177
+ queryPostType: readOptionalLooseStringFlag(flags2, "query-post-type"),
280901
281178
  selectDataStorage: activePrompt ? () => activePrompt.select("Select a data storage mode", [...DATA_STORAGE_PROMPT_OPTIONS], 1) : undefined,
280902
281179
  selectExternalLayerId: shouldPromptForExternalLayerSelection && activePrompt ? (options) => activePrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
280903
281180
  selectPackageManager: activePrompt ? () => activePrompt.select("Select a package manager", [...PACKAGE_MANAGER_PROMPT_OPTIONS], 1) : undefined,
@@ -281737,6 +282014,10 @@ var createOptions = {
281737
282014
  description: "Custom PHP symbol prefix.",
281738
282015
  schema: exports_external.string().optional()
281739
282016
  },
282017
+ "query-post-type": {
282018
+ description: "Default post type assigned to Query Loop variation scaffolds.",
282019
+ schema: exports_external.string().optional()
282020
+ },
281740
282021
  template: {
281741
282022
  description: "Template id or external template package.",
281742
282023
  schema: exports_external.string().optional(),
@@ -281808,6 +282089,7 @@ var createCommand = defineCommand({
281808
282089
  "package-manager": args.flags["package-manager"] ?? config2["package-manager"],
281809
282090
  "persistence-policy": args.flags["persistence-policy"] ?? config2["persistence-policy"],
281810
282091
  "php-prefix": args.flags["php-prefix"] ?? config2["php-prefix"],
282092
+ "query-post-type": args.flags["query-post-type"] ?? config2["query-post-type"],
281811
282093
  "project-dir": args.positional[0] ?? "",
281812
282094
  template: args.flags.template ?? config2.template,
281813
282095
  "text-domain": args.flags["text-domain"] ?? config2["text-domain"],
@@ -282713,4 +282995,4 @@ export {
282713
282995
  cli
282714
282996
  };
282715
282997
 
282716
- //# debugId=C2559875A211266F64756E2164756E21
282998
+ //# debugId=9E22CBAFF8C72AF964756E2164756E21