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 +5 -0
- package/bin/argv-walker.d.ts +19 -0
- package/bin/argv-walker.js +53 -0
- package/bin/routing-metadata.generated.d.ts +3 -1
- package/bin/routing-metadata.generated.js +57 -37
- package/bin/runtime-routing.d.ts +34 -0
- package/bin/runtime-routing.js +124 -0
- package/bin/wp-typia.js +97 -90
- package/dist-bunli/.bunli/commands.gen.js +5705 -1385
- package/dist-bunli/{cli-j1tyw390.js → cli-1w5vkye4.js} +989 -266
- package/dist-bunli/{cli-tesygdnr.js → cli-39er8888.js} +29 -2
- package/dist-bunli/{cli-add-6byyahb8.js → cli-add-kjhghdqq.js} +2488 -479
- package/dist-bunli/{cli-diagnostics-zecc6w1f.js → cli-diagnostics-5dvztm7q.js} +8 -2
- package/dist-bunli/{cli-doctor-2bc4sq7v.js → cli-doctor-p3jxvn0k.js} +493 -20
- package/dist-bunli/{cli-2rev5hqm.js → cli-e623rs7g.js} +1 -1
- package/dist-bunli/cli-init-djhwr245.js +844 -0
- package/dist-bunli/{cli-3w3qxq9w.js → cli-j180bk07.js} +260 -25
- package/dist-bunli/{cli-xnh2s5kz.js → cli-ktp869eh.js} +350 -41
- package/dist-bunli/{cli-xxzpb58s.js → cli-p95wr1q8.js} +72 -4
- package/dist-bunli/{cli-scaffold-19gyvxxt.js → cli-scaffold-376yw891.js} +6 -5
- package/dist-bunli/cli.js +31 -117
- package/dist-bunli/{command-list-pztcgga5.js → command-list-jt1a1w7r.js} +587 -320
- package/dist-bunli/{migrations-1p6mbkyw.js → migrations-nwas5bwt.js} +2 -2
- package/dist-bunli/node-cli.js +1063 -556
- package/package.json +5 -3
- package/dist-bunli/cli-init-gdyp9enw.js +0 -341
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
getPackageVersions
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-39er8888.js";
|
|
5
5
|
import {
|
|
6
6
|
seedProjectMigrations
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-e623rs7g.js";
|
|
8
8
|
import {
|
|
9
9
|
ensureMigrationDirectories,
|
|
10
10
|
isPlainObject,
|
|
@@ -59,10 +59,14 @@ import {
|
|
|
59
59
|
toTitleCase,
|
|
60
60
|
validateBlockSlug,
|
|
61
61
|
validateNamespace
|
|
62
|
-
} from "./cli-
|
|
62
|
+
} from "./cli-j180bk07.js";
|
|
63
63
|
import {
|
|
64
64
|
createManagedTempRoot
|
|
65
65
|
} from "./cli-t73q5aqz.js";
|
|
66
|
+
import {
|
|
67
|
+
CLI_DIAGNOSTIC_CODES,
|
|
68
|
+
createCliDiagnosticCodeError
|
|
69
|
+
} from "./cli-p95wr1q8.js";
|
|
66
70
|
import {
|
|
67
71
|
__commonJS,
|
|
68
72
|
__require,
|
|
@@ -5274,6 +5278,17 @@ function buildInteractivityTypesSource(variables, attributes) {
|
|
|
5274
5278
|
{ name: "maxClicks", typeExpression: "number" }
|
|
5275
5279
|
],
|
|
5276
5280
|
name: `${variables.pascalCase}Context`
|
|
5281
|
+
},
|
|
5282
|
+
{
|
|
5283
|
+
members: [
|
|
5284
|
+
{ name: "clicks", typeExpression: "number" },
|
|
5285
|
+
{ name: "isAnimating", typeExpression: "boolean" },
|
|
5286
|
+
{ name: "isVisible", typeExpression: "boolean" },
|
|
5287
|
+
{ name: "progress", typeExpression: "number" },
|
|
5288
|
+
{ name: "clampedClicks", typeExpression: "number" },
|
|
5289
|
+
{ name: "isComplete", typeExpression: "boolean" }
|
|
5290
|
+
],
|
|
5291
|
+
name: `${variables.pascalCase}State`
|
|
5277
5292
|
}
|
|
5278
5293
|
],
|
|
5279
5294
|
typeAliases: [
|
|
@@ -5803,13 +5818,13 @@ function resolveLocalCliPathOption(options) {
|
|
|
5803
5818
|
}
|
|
5804
5819
|
const resolvedPath = path5.resolve(options.cwd, normalizedValue);
|
|
5805
5820
|
if (!fs3.existsSync(resolvedPath)) {
|
|
5806
|
-
throw
|
|
5821
|
+
throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `\`${options.label}\` path does not exist: ${resolvedPath}. Check the path relative to ${options.cwd}.`);
|
|
5807
5822
|
}
|
|
5808
5823
|
return resolvedPath;
|
|
5809
5824
|
}
|
|
5810
5825
|
function assertExternalLayerCompositionOptions(options) {
|
|
5811
5826
|
if (options.externalLayerId && !options.externalLayerSource) {
|
|
5812
|
-
throw
|
|
5827
|
+
throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, "externalLayerId requires externalLayerSource when composing built-in template layers.");
|
|
5813
5828
|
}
|
|
5814
5829
|
}
|
|
5815
5830
|
function createBuiltInVariantErrorMessage(options) {
|
|
@@ -5819,7 +5834,7 @@ function assertBuiltInTemplateVariantAllowed(options) {
|
|
|
5819
5834
|
if (!options.variant) {
|
|
5820
5835
|
return;
|
|
5821
5836
|
}
|
|
5822
|
-
throw
|
|
5837
|
+
throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, createBuiltInVariantErrorMessage({
|
|
5823
5838
|
templateId: options.templateId,
|
|
5824
5839
|
variant: options.variant
|
|
5825
5840
|
}));
|
|
@@ -6036,7 +6051,7 @@ function normalizeQueryPostType(value) {
|
|
|
6036
6051
|
}
|
|
6037
6052
|
const validationResult = validateQueryPostType(value);
|
|
6038
6053
|
if (validationResult !== true) {
|
|
6039
|
-
throw
|
|
6054
|
+
throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, validationResult);
|
|
6040
6055
|
}
|
|
6041
6056
|
return value.trim().toLowerCase();
|
|
6042
6057
|
}
|
|
@@ -6108,7 +6123,7 @@ async function resolveTemplateId({
|
|
|
6108
6123
|
if (templateId) {
|
|
6109
6124
|
const normalizedTemplateId = normalizeTemplateSelection(templateId);
|
|
6110
6125
|
if (isRemovedBuiltInTemplateId(templateId)) {
|
|
6111
|
-
throw
|
|
6126
|
+
throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, getRemovedBuiltInTemplateMessage(templateId));
|
|
6112
6127
|
}
|
|
6113
6128
|
if (normalizedTemplateId === OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE) {
|
|
6114
6129
|
return normalizedTemplateId;
|
|
@@ -6118,10 +6133,10 @@ async function resolveTemplateId({
|
|
|
6118
6133
|
}
|
|
6119
6134
|
const mistypedBuiltInTemplateMessage = getMistypedBuiltInTemplateMessage(templateId);
|
|
6120
6135
|
if (mistypedBuiltInTemplateMessage) {
|
|
6121
|
-
throw
|
|
6136
|
+
throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, mistypedBuiltInTemplateMessage);
|
|
6122
6137
|
}
|
|
6123
6138
|
if (!looksLikeExplicitExternalTemplateLocator(normalizedTemplateId)) {
|
|
6124
|
-
throw
|
|
6139
|
+
throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, getUnknownTemplateMessage(templateId));
|
|
6125
6140
|
}
|
|
6126
6141
|
return normalizedTemplateId;
|
|
6127
6142
|
}
|
|
@@ -6129,7 +6144,7 @@ async function resolveTemplateId({
|
|
|
6129
6144
|
return "basic";
|
|
6130
6145
|
}
|
|
6131
6146
|
if (!isInteractive || !selectTemplate) {
|
|
6132
|
-
throw
|
|
6147
|
+
throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `Template is required in non-interactive mode. Use ${TEMPLATE_SELECTION_HINT}.`);
|
|
6133
6148
|
}
|
|
6134
6149
|
return normalizeTemplateSelection(await selectTemplate());
|
|
6135
6150
|
}
|
|
@@ -6146,7 +6161,7 @@ async function resolvePackageManagerId({
|
|
|
6146
6161
|
return "npm";
|
|
6147
6162
|
}
|
|
6148
6163
|
if (!isInteractive || !selectPackageManager) {
|
|
6149
|
-
throw
|
|
6164
|
+
throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `Package manager is required in non-interactive mode. Use --package-manager <${PACKAGE_MANAGER_IDS.join("|")}>.`);
|
|
6150
6165
|
}
|
|
6151
6166
|
return selectPackageManager();
|
|
6152
6167
|
}
|
|
@@ -6204,9 +6219,9 @@ async function collectScaffoldAnswers({
|
|
|
6204
6219
|
}
|
|
6205
6220
|
|
|
6206
6221
|
// ../wp-typia-project-tools/src/runtime/scaffold.ts
|
|
6207
|
-
import
|
|
6208
|
-
import { promises as
|
|
6209
|
-
import
|
|
6222
|
+
import fs15 from "fs";
|
|
6223
|
+
import { promises as fsp11 } from "fs";
|
|
6224
|
+
import path18 from "path";
|
|
6210
6225
|
|
|
6211
6226
|
// ../wp-typia-project-tools/src/runtime/scaffold-apply-utils.ts
|
|
6212
6227
|
import fs6 from "fs";
|
|
@@ -6692,7 +6707,6 @@ async function defaultInstallDependencies({
|
|
|
6692
6707
|
stdio: "inherit"
|
|
6693
6708
|
});
|
|
6694
6709
|
}
|
|
6695
|
-
|
|
6696
6710
|
// ../wp-typia-project-tools/src/runtime/scaffold-repository-reference.ts
|
|
6697
6711
|
import fs5 from "fs";
|
|
6698
6712
|
import { createRequire } from "module";
|
|
@@ -7961,10 +7975,10 @@ async function detectTemplateSourceFormat(sourceDir) {
|
|
|
7961
7975
|
|
|
7962
7976
|
// ../wp-typia-project-tools/src/runtime/template-source-seeds.ts
|
|
7963
7977
|
var import_semver = __toESM(require_semver2(), 1);
|
|
7964
|
-
import
|
|
7965
|
-
import { promises as
|
|
7978
|
+
import fs14 from "fs";
|
|
7979
|
+
import { promises as fsp10 } from "fs";
|
|
7966
7980
|
import { createRequire as createRequire2 } from "module";
|
|
7967
|
-
import
|
|
7981
|
+
import path17 from "path";
|
|
7968
7982
|
import { spawnSync } from "child_process";
|
|
7969
7983
|
|
|
7970
7984
|
// ../../node_modules/.bun/tar@7.5.13/node_modules/tar/dist/esm/index.min.js
|
|
@@ -11114,11 +11128,342 @@ var So = (s3) => {
|
|
|
11114
11128
|
s3.mtimeCache || (s3.mtimeCache = new Map), s3.filter = t ? (e, i) => t(e, i) && !((s3.mtimeCache?.get(e) ?? i.mtime ?? 0) > (i.mtime ?? 0)) : (e, i) => !((s3.mtimeCache?.get(e) ?? i.mtime ?? 0) > (i.mtime ?? 0));
|
|
11115
11129
|
};
|
|
11116
11130
|
|
|
11131
|
+
// ../wp-typia-project-tools/src/runtime/template-source-cache.ts
|
|
11132
|
+
import { createHash } from "crypto";
|
|
11133
|
+
import fs13 from "fs";
|
|
11134
|
+
import { promises as fsp9 } from "fs";
|
|
11135
|
+
import os2 from "os";
|
|
11136
|
+
import path16 from "path";
|
|
11137
|
+
var EXTERNAL_TEMPLATE_CACHE_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE";
|
|
11138
|
+
var EXTERNAL_TEMPLATE_CACHE_DIR_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR";
|
|
11139
|
+
var CACHE_MARKER_FILE = "wp-typia-template-cache.json";
|
|
11140
|
+
var PRIVATE_CACHE_DIRECTORY_MODE = 448;
|
|
11141
|
+
var REDACTED_CACHE_METADATA_VALUE = "[redacted]";
|
|
11142
|
+
var DISABLED_CACHE_VALUES = new Set(["0", "false", "no", "off"]);
|
|
11143
|
+
var CACHE_PUBLISH_RACE_ERROR_CODES = new Set(["EEXIST", "ENOTEMPTY"]);
|
|
11144
|
+
var CACHE_UNAVAILABLE_ERROR_CODES = new Set([
|
|
11145
|
+
"EACCES",
|
|
11146
|
+
"ENOSPC",
|
|
11147
|
+
"ENOTDIR",
|
|
11148
|
+
"EPERM",
|
|
11149
|
+
"EROFS"
|
|
11150
|
+
]);
|
|
11151
|
+
var URL_LIKE_METADATA_KEY = /(url|uri|registry|tarball)/iu;
|
|
11152
|
+
var SAFE_CACHE_NAMESPACE_SEGMENT = /^[A-Za-z0-9_.-]+$/u;
|
|
11153
|
+
function isExternalTemplateCacheEnabled(env = process.env) {
|
|
11154
|
+
const rawValue2 = env[EXTERNAL_TEMPLATE_CACHE_ENV];
|
|
11155
|
+
if (rawValue2 === undefined) {
|
|
11156
|
+
return true;
|
|
11157
|
+
}
|
|
11158
|
+
return !DISABLED_CACHE_VALUES.has(rawValue2.trim().toLowerCase());
|
|
11159
|
+
}
|
|
11160
|
+
function getExternalTemplateCacheRoot(env = process.env) {
|
|
11161
|
+
const configuredCacheDir = env[EXTERNAL_TEMPLATE_CACHE_DIR_ENV]?.trim();
|
|
11162
|
+
if (configuredCacheDir) {
|
|
11163
|
+
return path16.resolve(configuredCacheDir);
|
|
11164
|
+
}
|
|
11165
|
+
return path16.join(os2.tmpdir(), `wp-typia-template-source-cache-${getCurrentUserCacheSegment()}`);
|
|
11166
|
+
}
|
|
11167
|
+
function createExternalTemplateCacheKey(keyParts) {
|
|
11168
|
+
return createHash("sha256").update(JSON.stringify(keyParts)).digest("hex");
|
|
11169
|
+
}
|
|
11170
|
+
async function pathExists(filePath) {
|
|
11171
|
+
try {
|
|
11172
|
+
await fsp9.access(filePath, fs13.constants.F_OK);
|
|
11173
|
+
return true;
|
|
11174
|
+
} catch {
|
|
11175
|
+
return false;
|
|
11176
|
+
}
|
|
11177
|
+
}
|
|
11178
|
+
async function isDirectoryPath(directory) {
|
|
11179
|
+
try {
|
|
11180
|
+
const stats = await fsp9.lstat(directory);
|
|
11181
|
+
return stats.isDirectory() && !stats.isSymbolicLink();
|
|
11182
|
+
} catch {
|
|
11183
|
+
return false;
|
|
11184
|
+
}
|
|
11185
|
+
}
|
|
11186
|
+
function getNodeErrorCode(error) {
|
|
11187
|
+
return typeof error === "object" && error !== null && "code" in error ? String(error.code) : "";
|
|
11188
|
+
}
|
|
11189
|
+
async function removeTemporaryCacheEntry(entryDir) {
|
|
11190
|
+
try {
|
|
11191
|
+
await fsp9.rm(entryDir, { force: true, recursive: true });
|
|
11192
|
+
} catch {}
|
|
11193
|
+
}
|
|
11194
|
+
function getCurrentUserCacheSegment() {
|
|
11195
|
+
if (typeof process.getuid === "function") {
|
|
11196
|
+
return String(process.getuid());
|
|
11197
|
+
}
|
|
11198
|
+
try {
|
|
11199
|
+
const safeUsername = os2.userInfo().username.trim().replace(/[^A-Za-z0-9._-]+/gu, "-");
|
|
11200
|
+
return safeUsername.length > 0 ? safeUsername : "user";
|
|
11201
|
+
} catch {
|
|
11202
|
+
return "user";
|
|
11203
|
+
}
|
|
11204
|
+
}
|
|
11205
|
+
function getCurrentUid() {
|
|
11206
|
+
return typeof process.getuid === "function" ? process.getuid() : null;
|
|
11207
|
+
}
|
|
11208
|
+
async function isPrivateCacheDirectory(directory) {
|
|
11209
|
+
try {
|
|
11210
|
+
const stats = await fsp9.lstat(directory);
|
|
11211
|
+
if (!stats.isDirectory() || stats.isSymbolicLink()) {
|
|
11212
|
+
return false;
|
|
11213
|
+
}
|
|
11214
|
+
const currentUid = getCurrentUid();
|
|
11215
|
+
if (currentUid !== null && stats.uid !== currentUid) {
|
|
11216
|
+
return false;
|
|
11217
|
+
}
|
|
11218
|
+
if (process.platform !== "win32" && (stats.mode & 63) !== 0) {
|
|
11219
|
+
return false;
|
|
11220
|
+
}
|
|
11221
|
+
return true;
|
|
11222
|
+
} catch {
|
|
11223
|
+
return false;
|
|
11224
|
+
}
|
|
11225
|
+
}
|
|
11226
|
+
async function ensurePrivateCacheDirectory(directory) {
|
|
11227
|
+
try {
|
|
11228
|
+
await fsp9.mkdir(directory, {
|
|
11229
|
+
mode: PRIVATE_CACHE_DIRECTORY_MODE,
|
|
11230
|
+
recursive: true
|
|
11231
|
+
});
|
|
11232
|
+
const stats = await fsp9.lstat(directory);
|
|
11233
|
+
if (!stats.isDirectory() || stats.isSymbolicLink()) {
|
|
11234
|
+
return false;
|
|
11235
|
+
}
|
|
11236
|
+
const currentUid = getCurrentUid();
|
|
11237
|
+
if (currentUid !== null && stats.uid !== currentUid) {
|
|
11238
|
+
return false;
|
|
11239
|
+
}
|
|
11240
|
+
if (process.platform !== "win32") {
|
|
11241
|
+
if ((stats.mode & 63) !== 0) {
|
|
11242
|
+
await fsp9.chmod(directory, PRIVATE_CACHE_DIRECTORY_MODE);
|
|
11243
|
+
}
|
|
11244
|
+
}
|
|
11245
|
+
return isPrivateCacheDirectory(directory);
|
|
11246
|
+
} catch {
|
|
11247
|
+
return false;
|
|
11248
|
+
}
|
|
11249
|
+
}
|
|
11250
|
+
function sanitizeCacheMetadataValue(key, value) {
|
|
11251
|
+
if (!URL_LIKE_METADATA_KEY.test(key)) {
|
|
11252
|
+
return value;
|
|
11253
|
+
}
|
|
11254
|
+
try {
|
|
11255
|
+
const url = new URL(value);
|
|
11256
|
+
url.username = "";
|
|
11257
|
+
url.password = "";
|
|
11258
|
+
url.search = "";
|
|
11259
|
+
url.hash = "";
|
|
11260
|
+
return url.toString();
|
|
11261
|
+
} catch {
|
|
11262
|
+
return REDACTED_CACHE_METADATA_VALUE;
|
|
11263
|
+
}
|
|
11264
|
+
}
|
|
11265
|
+
function sanitizeCacheMetadata(metadata) {
|
|
11266
|
+
return Object.fromEntries(Object.entries(metadata).map(([key, value]) => [
|
|
11267
|
+
key,
|
|
11268
|
+
value === null ? null : sanitizeCacheMetadataValue(key, value)
|
|
11269
|
+
]));
|
|
11270
|
+
}
|
|
11271
|
+
function resolveCacheNamespaceDir(cacheRoot, namespace) {
|
|
11272
|
+
if (namespace === "." || namespace === ".." || !SAFE_CACHE_NAMESPACE_SEGMENT.test(namespace)) {
|
|
11273
|
+
return null;
|
|
11274
|
+
}
|
|
11275
|
+
const namespaceDir = path16.join(cacheRoot, namespace);
|
|
11276
|
+
const relativeNamespaceDir = path16.relative(cacheRoot, namespaceDir);
|
|
11277
|
+
if (relativeNamespaceDir.length === 0 || relativeNamespaceDir.startsWith("..") || path16.isAbsolute(relativeNamespaceDir)) {
|
|
11278
|
+
return null;
|
|
11279
|
+
}
|
|
11280
|
+
return namespaceDir;
|
|
11281
|
+
}
|
|
11282
|
+
function getCacheEntryPaths(descriptor) {
|
|
11283
|
+
const cacheKey = createExternalTemplateCacheKey(descriptor.keyParts);
|
|
11284
|
+
const cacheRoot = getExternalTemplateCacheRoot();
|
|
11285
|
+
const namespaceDir = resolveCacheNamespaceDir(cacheRoot, descriptor.namespace);
|
|
11286
|
+
if (!namespaceDir) {
|
|
11287
|
+
return null;
|
|
11288
|
+
}
|
|
11289
|
+
const entryDir = path16.join(namespaceDir, cacheKey);
|
|
11290
|
+
return {
|
|
11291
|
+
cacheKey,
|
|
11292
|
+
cacheRoot,
|
|
11293
|
+
entryDir,
|
|
11294
|
+
markerPath: path16.join(entryDir, CACHE_MARKER_FILE),
|
|
11295
|
+
namespaceDir,
|
|
11296
|
+
sourceDir: path16.join(entryDir, "source")
|
|
11297
|
+
};
|
|
11298
|
+
}
|
|
11299
|
+
async function isReusableCacheEntry(entryDir, markerPath, sourceDir) {
|
|
11300
|
+
return await isPrivateCacheDirectory(entryDir) && await pathExists(markerPath) && await isDirectoryPath(sourceDir);
|
|
11301
|
+
}
|
|
11302
|
+
function parseCacheMarkerMetadata(markerText) {
|
|
11303
|
+
let marker;
|
|
11304
|
+
try {
|
|
11305
|
+
marker = JSON.parse(markerText);
|
|
11306
|
+
} catch {
|
|
11307
|
+
return null;
|
|
11308
|
+
}
|
|
11309
|
+
if (typeof marker !== "object" || marker === null || Array.isArray(marker)) {
|
|
11310
|
+
return null;
|
|
11311
|
+
}
|
|
11312
|
+
const rawMetadata = marker.metadata;
|
|
11313
|
+
if (typeof rawMetadata !== "object" || rawMetadata === null || Array.isArray(rawMetadata)) {
|
|
11314
|
+
return null;
|
|
11315
|
+
}
|
|
11316
|
+
const metadata = {};
|
|
11317
|
+
for (const [key, value] of Object.entries(rawMetadata)) {
|
|
11318
|
+
if (typeof value !== "string" && value !== null) {
|
|
11319
|
+
return null;
|
|
11320
|
+
}
|
|
11321
|
+
metadata[key] = value;
|
|
11322
|
+
}
|
|
11323
|
+
const rawCreatedAt = marker.createdAt;
|
|
11324
|
+
const createdAtMs = typeof rawCreatedAt === "string" ? Date.parse(rawCreatedAt) : 0;
|
|
11325
|
+
return {
|
|
11326
|
+
createdAtMs: Number.isFinite(createdAtMs) ? createdAtMs : 0,
|
|
11327
|
+
metadata
|
|
11328
|
+
};
|
|
11329
|
+
}
|
|
11330
|
+
function cacheMetadataMatches(actual, expected) {
|
|
11331
|
+
return Object.entries(expected).every(([key, value]) => actual[key] === value);
|
|
11332
|
+
}
|
|
11333
|
+
async function findReusableExternalTemplateSourceCache(descriptor) {
|
|
11334
|
+
if (!isExternalTemplateCacheEnabled()) {
|
|
11335
|
+
return null;
|
|
11336
|
+
}
|
|
11337
|
+
const cacheRoot = getExternalTemplateCacheRoot();
|
|
11338
|
+
const namespaceDir = resolveCacheNamespaceDir(cacheRoot, descriptor.namespace);
|
|
11339
|
+
if (!namespaceDir) {
|
|
11340
|
+
return null;
|
|
11341
|
+
}
|
|
11342
|
+
if (!await isPrivateCacheDirectory(cacheRoot) || !await isPrivateCacheDirectory(namespaceDir)) {
|
|
11343
|
+
return null;
|
|
11344
|
+
}
|
|
11345
|
+
let entries;
|
|
11346
|
+
try {
|
|
11347
|
+
entries = await fsp9.readdir(namespaceDir, { withFileTypes: true });
|
|
11348
|
+
} catch {
|
|
11349
|
+
return null;
|
|
11350
|
+
}
|
|
11351
|
+
let bestEntry = null;
|
|
11352
|
+
for (const entry of entries) {
|
|
11353
|
+
if (!entry.isDirectory()) {
|
|
11354
|
+
continue;
|
|
11355
|
+
}
|
|
11356
|
+
const entryDir = path16.join(namespaceDir, entry.name);
|
|
11357
|
+
const markerPath = path16.join(entryDir, CACHE_MARKER_FILE);
|
|
11358
|
+
const sourceDir = path16.join(entryDir, "source");
|
|
11359
|
+
if (!await isReusableCacheEntry(entryDir, markerPath, sourceDir)) {
|
|
11360
|
+
continue;
|
|
11361
|
+
}
|
|
11362
|
+
let markerText;
|
|
11363
|
+
try {
|
|
11364
|
+
markerText = await fsp9.readFile(markerPath, "utf8");
|
|
11365
|
+
} catch {
|
|
11366
|
+
continue;
|
|
11367
|
+
}
|
|
11368
|
+
const marker = parseCacheMarkerMetadata(markerText);
|
|
11369
|
+
if (!marker || !cacheMetadataMatches(marker.metadata, descriptor.metadata)) {
|
|
11370
|
+
continue;
|
|
11371
|
+
}
|
|
11372
|
+
if (!bestEntry || marker.createdAtMs > bestEntry.createdAtMs) {
|
|
11373
|
+
bestEntry = {
|
|
11374
|
+
createdAtMs: marker.createdAtMs,
|
|
11375
|
+
sourceDir
|
|
11376
|
+
};
|
|
11377
|
+
}
|
|
11378
|
+
}
|
|
11379
|
+
return bestEntry ? {
|
|
11380
|
+
cacheHit: true,
|
|
11381
|
+
sourceDir: bestEntry.sourceDir
|
|
11382
|
+
} : null;
|
|
11383
|
+
}
|
|
11384
|
+
async function resolveExternalTemplateSourceCache(descriptor, populateSourceDir) {
|
|
11385
|
+
if (!isExternalTemplateCacheEnabled()) {
|
|
11386
|
+
return null;
|
|
11387
|
+
}
|
|
11388
|
+
const cacheEntryPaths = getCacheEntryPaths(descriptor);
|
|
11389
|
+
if (!cacheEntryPaths) {
|
|
11390
|
+
return null;
|
|
11391
|
+
}
|
|
11392
|
+
const { cacheKey, cacheRoot, entryDir, markerPath, namespaceDir, sourceDir } = cacheEntryPaths;
|
|
11393
|
+
if (!await ensurePrivateCacheDirectory(cacheRoot) || !await ensurePrivateCacheDirectory(namespaceDir)) {
|
|
11394
|
+
return null;
|
|
11395
|
+
}
|
|
11396
|
+
if (await isReusableCacheEntry(entryDir, markerPath, sourceDir)) {
|
|
11397
|
+
return {
|
|
11398
|
+
cacheHit: true,
|
|
11399
|
+
sourceDir
|
|
11400
|
+
};
|
|
11401
|
+
}
|
|
11402
|
+
const temporaryEntryDir = path16.join(namespaceDir, `.tmp-${cacheKey}-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);
|
|
11403
|
+
const temporarySourceDir = path16.join(temporaryEntryDir, "source");
|
|
11404
|
+
let populateFailed = false;
|
|
11405
|
+
try {
|
|
11406
|
+
await fsp9.mkdir(temporarySourceDir, {
|
|
11407
|
+
mode: PRIVATE_CACHE_DIRECTORY_MODE,
|
|
11408
|
+
recursive: true
|
|
11409
|
+
});
|
|
11410
|
+
if (process.platform !== "win32") {
|
|
11411
|
+
await fsp9.chmod(temporaryEntryDir, PRIVATE_CACHE_DIRECTORY_MODE);
|
|
11412
|
+
}
|
|
11413
|
+
try {
|
|
11414
|
+
await populateSourceDir(temporarySourceDir);
|
|
11415
|
+
} catch (error) {
|
|
11416
|
+
populateFailed = true;
|
|
11417
|
+
throw error;
|
|
11418
|
+
}
|
|
11419
|
+
await fsp9.writeFile(path16.join(temporaryEntryDir, CACHE_MARKER_FILE), `${JSON.stringify({
|
|
11420
|
+
createdAt: new Date().toISOString(),
|
|
11421
|
+
key: cacheKey,
|
|
11422
|
+
metadata: sanitizeCacheMetadata(descriptor.metadata),
|
|
11423
|
+
namespace: descriptor.namespace
|
|
11424
|
+
}, null, 2)}
|
|
11425
|
+
`, "utf8");
|
|
11426
|
+
await fsp9.rename(temporaryEntryDir, entryDir);
|
|
11427
|
+
return {
|
|
11428
|
+
cacheHit: false,
|
|
11429
|
+
sourceDir
|
|
11430
|
+
};
|
|
11431
|
+
} catch (error) {
|
|
11432
|
+
await removeTemporaryCacheEntry(temporaryEntryDir);
|
|
11433
|
+
if (populateFailed) {
|
|
11434
|
+
if (CACHE_UNAVAILABLE_ERROR_CODES.has(getNodeErrorCode(error))) {
|
|
11435
|
+
return null;
|
|
11436
|
+
}
|
|
11437
|
+
throw error;
|
|
11438
|
+
}
|
|
11439
|
+
const errorCode = getNodeErrorCode(error);
|
|
11440
|
+
if (CACHE_PUBLISH_RACE_ERROR_CODES.has(errorCode) && await isReusableCacheEntry(entryDir, markerPath, sourceDir)) {
|
|
11441
|
+
return {
|
|
11442
|
+
cacheHit: true,
|
|
11443
|
+
sourceDir
|
|
11444
|
+
};
|
|
11445
|
+
}
|
|
11446
|
+
if (CACHE_PUBLISH_RACE_ERROR_CODES.has(errorCode) || CACHE_UNAVAILABLE_ERROR_CODES.has(errorCode)) {
|
|
11447
|
+
return null;
|
|
11448
|
+
}
|
|
11449
|
+
throw error;
|
|
11450
|
+
}
|
|
11451
|
+
}
|
|
11452
|
+
|
|
11117
11453
|
// ../wp-typia-project-tools/src/runtime/template-source-seeds.ts
|
|
11118
11454
|
var USER_FACING_TEMPLATE_IDS2 = [
|
|
11119
11455
|
...TEMPLATE_IDS,
|
|
11120
11456
|
OFFICIAL_WORKSPACE_TEMPLATE_ALIAS
|
|
11121
11457
|
];
|
|
11458
|
+
var GITHUB_TEMPLATE_CACHE_REVISION_RACE_CODE = "github-template-cache-revision-race";
|
|
11459
|
+
function createGitHubTemplateCacheRevisionRaceError(message) {
|
|
11460
|
+
const error = new Error(message);
|
|
11461
|
+
error.code = GITHUB_TEMPLATE_CACHE_REVISION_RACE_CODE;
|
|
11462
|
+
return error;
|
|
11463
|
+
}
|
|
11464
|
+
function isGitHubTemplateCacheRevisionRaceError(error) {
|
|
11465
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === GITHUB_TEMPLATE_CACHE_REVISION_RACE_CODE;
|
|
11466
|
+
}
|
|
11122
11467
|
function getUnknownNpmTemplateMessage(templateId) {
|
|
11123
11468
|
return [
|
|
11124
11469
|
`Unknown template "${templateId}". Expected one of: ${USER_FACING_TEMPLATE_IDS2.join(", ")}.`,
|
|
@@ -11126,6 +11471,43 @@ function getUnknownNpmTemplateMessage(templateId) {
|
|
|
11126
11471
|
"If you meant an npm template package, verify the package name and configured npm registry."
|
|
11127
11472
|
].join(" ");
|
|
11128
11473
|
}
|
|
11474
|
+
function readOptionalDistString(dist, key) {
|
|
11475
|
+
const value = dist[key];
|
|
11476
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
11477
|
+
}
|
|
11478
|
+
function normalizeNpmRegistryCacheKey(registryBase) {
|
|
11479
|
+
try {
|
|
11480
|
+
const url = new URL(registryBase);
|
|
11481
|
+
url.username = "";
|
|
11482
|
+
url.password = "";
|
|
11483
|
+
url.search = "";
|
|
11484
|
+
url.hash = "";
|
|
11485
|
+
return url.toString().replace(/\/$/u, "");
|
|
11486
|
+
} catch {
|
|
11487
|
+
return registryBase;
|
|
11488
|
+
}
|
|
11489
|
+
}
|
|
11490
|
+
async function downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl, unpackDir) {
|
|
11491
|
+
const tarballResponse = await fetchWithExternalTemplateTimeout(tarballUrl, {
|
|
11492
|
+
label: `downloading npm template tarball for ${locator.raw}@${resolvedVersion}`
|
|
11493
|
+
});
|
|
11494
|
+
if (!tarballResponse.ok) {
|
|
11495
|
+
throw new Error(`Failed to download npm template tarball for ${locator.raw}: ${tarballResponse.status}`);
|
|
11496
|
+
}
|
|
11497
|
+
const tarballPath = path17.join(path17.dirname(unpackDir), "template.tgz");
|
|
11498
|
+
await fsp10.mkdir(unpackDir, { recursive: true });
|
|
11499
|
+
await fsp10.writeFile(tarballPath, await readBufferResponseWithLimit(tarballResponse, {
|
|
11500
|
+
label: `npm template tarball for ${locator.raw}@${resolvedVersion}`,
|
|
11501
|
+
maxBytes: getExternalTemplateTarballMaxBytes()
|
|
11502
|
+
}));
|
|
11503
|
+
await co({
|
|
11504
|
+
cwd: unpackDir,
|
|
11505
|
+
file: tarballPath,
|
|
11506
|
+
strip: 1
|
|
11507
|
+
});
|
|
11508
|
+
await fsp10.rm(tarballPath, { force: true });
|
|
11509
|
+
await assertNoSymlinks2(unpackDir);
|
|
11510
|
+
}
|
|
11129
11511
|
function selectRegistryVersion(metadata, locator) {
|
|
11130
11512
|
const distTags = isPlainObject(metadata["dist-tags"]) ? metadata["dist-tags"] : {};
|
|
11131
11513
|
const versions = isPlainObject(metadata.versions) ? metadata.versions : {};
|
|
@@ -11165,7 +11547,7 @@ async function fetchNpmTemplateSource(locator) {
|
|
|
11165
11547
|
});
|
|
11166
11548
|
if (!metadataResponse.ok) {
|
|
11167
11549
|
if (metadataResponse.status === 404) {
|
|
11168
|
-
throw
|
|
11550
|
+
throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, getUnknownNpmTemplateMessage(locator.raw));
|
|
11169
11551
|
}
|
|
11170
11552
|
throw new Error(`Failed to fetch npm template metadata for ${locator.raw}: ${metadataResponse.status}`);
|
|
11171
11553
|
}
|
|
@@ -11183,27 +11565,43 @@ async function fetchNpmTemplateSource(locator) {
|
|
|
11183
11565
|
if (typeof tarballUrl !== "string" || tarballUrl.length === 0) {
|
|
11184
11566
|
throw new Error(`npm template metadata is missing tarball URL for ${locator.raw}@${resolvedVersion}.`);
|
|
11185
11567
|
}
|
|
11568
|
+
const tarballIntegrity = readOptionalDistString(versionMetadata.dist, "integrity");
|
|
11569
|
+
const tarballShasum = readOptionalDistString(versionMetadata.dist, "shasum");
|
|
11570
|
+
if (tarballIntegrity || tarballShasum) {
|
|
11571
|
+
const registryCacheKey = normalizeNpmRegistryCacheKey(registryBase);
|
|
11572
|
+
const cachedSource = await resolveExternalTemplateSourceCache({
|
|
11573
|
+
keyParts: [
|
|
11574
|
+
"npm",
|
|
11575
|
+
registryCacheKey,
|
|
11576
|
+
locator.name,
|
|
11577
|
+
locator.raw,
|
|
11578
|
+
resolvedVersion,
|
|
11579
|
+
tarballIntegrity ?? "",
|
|
11580
|
+
tarballShasum ?? ""
|
|
11581
|
+
],
|
|
11582
|
+
metadata: {
|
|
11583
|
+
integrity: tarballIntegrity,
|
|
11584
|
+
package: locator.name,
|
|
11585
|
+
raw: locator.raw,
|
|
11586
|
+
registry: registryBase,
|
|
11587
|
+
shasum: tarballShasum,
|
|
11588
|
+
tarball: tarballUrl,
|
|
11589
|
+
version: resolvedVersion
|
|
11590
|
+
},
|
|
11591
|
+
namespace: "npm"
|
|
11592
|
+
}, (unpackDir) => downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl, unpackDir));
|
|
11593
|
+
if (cachedSource) {
|
|
11594
|
+
await assertNoSymlinks2(cachedSource.sourceDir);
|
|
11595
|
+
return {
|
|
11596
|
+
blockDir: cachedSource.sourceDir,
|
|
11597
|
+
rootDir: cachedSource.sourceDir
|
|
11598
|
+
};
|
|
11599
|
+
}
|
|
11600
|
+
}
|
|
11186
11601
|
const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
|
|
11187
11602
|
try {
|
|
11188
|
-
const
|
|
11189
|
-
|
|
11190
|
-
});
|
|
11191
|
-
if (!tarballResponse.ok) {
|
|
11192
|
-
throw new Error(`Failed to download npm template tarball for ${locator.raw}: ${tarballResponse.status}`);
|
|
11193
|
-
}
|
|
11194
|
-
const tarballPath = path16.join(tempRoot, "template.tgz");
|
|
11195
|
-
const unpackDir = path16.join(tempRoot, "source");
|
|
11196
|
-
await fsp9.mkdir(unpackDir, { recursive: true });
|
|
11197
|
-
await fsp9.writeFile(tarballPath, await readBufferResponseWithLimit(tarballResponse, {
|
|
11198
|
-
label: `npm template tarball for ${locator.raw}@${resolvedVersion}`,
|
|
11199
|
-
maxBytes: getExternalTemplateTarballMaxBytes()
|
|
11200
|
-
}));
|
|
11201
|
-
await co({
|
|
11202
|
-
cwd: unpackDir,
|
|
11203
|
-
file: tarballPath,
|
|
11204
|
-
strip: 1
|
|
11205
|
-
});
|
|
11206
|
-
await assertNoSymlinks2(unpackDir);
|
|
11603
|
+
const unpackDir = path17.join(tempRoot, "source");
|
|
11604
|
+
await downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl, unpackDir);
|
|
11207
11605
|
return {
|
|
11208
11606
|
blockDir: unpackDir,
|
|
11209
11607
|
cleanup,
|
|
@@ -11218,20 +11616,20 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
|
|
|
11218
11616
|
if (locator.rawSpec !== "" && locator.rawSpec !== "*") {
|
|
11219
11617
|
return null;
|
|
11220
11618
|
}
|
|
11221
|
-
const workspacePackagesRoot =
|
|
11222
|
-
if (
|
|
11223
|
-
for (const entry of
|
|
11619
|
+
const workspacePackagesRoot = path17.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..");
|
|
11620
|
+
if (fs14.existsSync(workspacePackagesRoot)) {
|
|
11621
|
+
for (const entry of fs14.readdirSync(workspacePackagesRoot, {
|
|
11224
11622
|
withFileTypes: true
|
|
11225
11623
|
})) {
|
|
11226
11624
|
if (!entry.isDirectory()) {
|
|
11227
11625
|
continue;
|
|
11228
11626
|
}
|
|
11229
|
-
const packageDir =
|
|
11230
|
-
const packageJsonPath =
|
|
11231
|
-
if (!
|
|
11627
|
+
const packageDir = path17.join(workspacePackagesRoot, entry.name);
|
|
11628
|
+
const packageJsonPath = path17.join(packageDir, "package.json");
|
|
11629
|
+
if (!fs14.existsSync(packageJsonPath)) {
|
|
11232
11630
|
continue;
|
|
11233
11631
|
}
|
|
11234
|
-
const manifest = JSON.parse(
|
|
11632
|
+
const manifest = JSON.parse(fs14.readFileSync(packageJsonPath, "utf8"));
|
|
11235
11633
|
if (manifest.name === locator.name) {
|
|
11236
11634
|
return {
|
|
11237
11635
|
blockDir: packageDir,
|
|
@@ -11240,10 +11638,10 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
|
|
|
11240
11638
|
}
|
|
11241
11639
|
}
|
|
11242
11640
|
}
|
|
11243
|
-
const workspaceRequire = createRequire2(
|
|
11641
|
+
const workspaceRequire = createRequire2(path17.join(path17.resolve(cwd), "__wp_typia_template_resolver__.cjs"));
|
|
11244
11642
|
try {
|
|
11245
|
-
const packageJsonPath =
|
|
11246
|
-
const sourceDir =
|
|
11643
|
+
const packageJsonPath = fs14.realpathSync(workspaceRequire.resolve(`${locator.name}/package.json`));
|
|
11644
|
+
const sourceDir = path17.dirname(packageJsonPath);
|
|
11247
11645
|
return {
|
|
11248
11646
|
blockDir: sourceDir,
|
|
11249
11647
|
rootDir: sourceDir
|
|
@@ -11252,11 +11650,11 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
|
|
|
11252
11650
|
const errorCode = typeof error === "object" && error !== null && "code" in error ? String(error.code) : "";
|
|
11253
11651
|
if (errorCode === "MODULE_NOT_FOUND" || errorCode === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
|
|
11254
11652
|
for (const basePath of workspaceRequire.resolve.paths(locator.name) ?? []) {
|
|
11255
|
-
const packageJsonPath =
|
|
11256
|
-
if (!
|
|
11653
|
+
const packageJsonPath = path17.join(basePath, locator.name, "package.json");
|
|
11654
|
+
if (!fs14.existsSync(packageJsonPath)) {
|
|
11257
11655
|
continue;
|
|
11258
11656
|
}
|
|
11259
|
-
const sourceDir =
|
|
11657
|
+
const sourceDir = path17.dirname(fs14.realpathSync(packageJsonPath));
|
|
11260
11658
|
return {
|
|
11261
11659
|
blockDir: sourceDir,
|
|
11262
11660
|
rootDir: sourceDir
|
|
@@ -11268,64 +11666,250 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
|
|
|
11268
11666
|
}
|
|
11269
11667
|
}
|
|
11270
11668
|
function isOfficialWorkspaceTemplateSeed(seed) {
|
|
11271
|
-
const packageJsonPath =
|
|
11272
|
-
if (!
|
|
11669
|
+
const packageJsonPath = path17.join(seed.rootDir, "package.json");
|
|
11670
|
+
if (!fs14.existsSync(packageJsonPath)) {
|
|
11273
11671
|
return false;
|
|
11274
11672
|
}
|
|
11275
11673
|
try {
|
|
11276
|
-
const packageJson = JSON.parse(
|
|
11674
|
+
const packageJson = JSON.parse(fs14.readFileSync(packageJsonPath, "utf8"));
|
|
11277
11675
|
return packageJson.name === OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE;
|
|
11278
11676
|
} catch {
|
|
11279
11677
|
return false;
|
|
11280
11678
|
}
|
|
11281
11679
|
}
|
|
11282
11680
|
async function assertNoSymlinks2(sourceDir) {
|
|
11283
|
-
const stats = await
|
|
11681
|
+
const stats = await fsp10.lstat(sourceDir);
|
|
11284
11682
|
if (stats.isSymbolicLink()) {
|
|
11285
11683
|
throw new Error(`Template sources may not include symbolic links: ${sourceDir}`);
|
|
11286
11684
|
}
|
|
11287
11685
|
if (!stats.isDirectory()) {
|
|
11288
11686
|
return;
|
|
11289
11687
|
}
|
|
11290
|
-
for (const entry of await
|
|
11291
|
-
await assertNoSymlinks2(
|
|
11688
|
+
for (const entry of await fsp10.readdir(sourceDir)) {
|
|
11689
|
+
await assertNoSymlinks2(path17.join(sourceDir, entry));
|
|
11292
11690
|
}
|
|
11293
11691
|
}
|
|
11294
|
-
|
|
11295
|
-
const
|
|
11296
|
-
const
|
|
11297
|
-
|
|
11298
|
-
|
|
11299
|
-
|
|
11300
|
-
|
|
11301
|
-
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11692
|
+
function runGitTemplateCommand(args, label, options = {}) {
|
|
11693
|
+
const timeoutMs = getExternalTemplateTimeoutMs();
|
|
11694
|
+
const result = options.captureOutput ? spawnSync("git", args, {
|
|
11695
|
+
encoding: "utf8",
|
|
11696
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
11697
|
+
timeout: timeoutMs
|
|
11698
|
+
}) : spawnSync("git", args, {
|
|
11699
|
+
stdio: "ignore",
|
|
11700
|
+
timeout: timeoutMs
|
|
11701
|
+
});
|
|
11702
|
+
if (result.error) {
|
|
11703
|
+
const errorCode = typeof result.error === "object" && result.error !== null && "code" in result.error ? String(result.error.code) : "";
|
|
11704
|
+
if (errorCode === "ETIMEDOUT") {
|
|
11705
|
+
throw createExternalTemplateTimeoutError(label, timeoutMs);
|
|
11706
|
+
}
|
|
11707
|
+
throw result.error;
|
|
11708
|
+
}
|
|
11709
|
+
if (result.signal === "SIGTERM" || result.signal === "SIGKILL") {
|
|
11710
|
+
throw createExternalTemplateTimeoutError(label, timeoutMs);
|
|
11711
|
+
}
|
|
11712
|
+
return result;
|
|
11713
|
+
}
|
|
11714
|
+
function getGitHubTemplateRepositoryUrl(locator) {
|
|
11715
|
+
return `https://github.com/${locator.owner}/${locator.repo}.git`;
|
|
11716
|
+
}
|
|
11717
|
+
function resolveGitHubTemplateDirectory(checkoutDir, locator) {
|
|
11718
|
+
const sourceDir = path17.resolve(checkoutDir, locator.sourcePath);
|
|
11719
|
+
const relativeSourceDir = path17.relative(checkoutDir, sourceDir);
|
|
11720
|
+
if (relativeSourceDir.startsWith("..") || path17.isAbsolute(relativeSourceDir)) {
|
|
11721
|
+
throw new Error("GitHub template path must stay within the cloned repository.");
|
|
11722
|
+
}
|
|
11723
|
+
if (!fs14.existsSync(sourceDir)) {
|
|
11724
|
+
throw new Error(`GitHub template path does not exist: ${locator.sourcePath}`);
|
|
11725
|
+
}
|
|
11726
|
+
return sourceDir;
|
|
11727
|
+
}
|
|
11728
|
+
function cloneGitHubTemplateSource(locator, checkoutDir) {
|
|
11729
|
+
const args = ["clone", "--depth", "1"];
|
|
11730
|
+
if (locator.ref) {
|
|
11731
|
+
args.push("--branch", locator.ref);
|
|
11732
|
+
}
|
|
11733
|
+
args.push(getGitHubTemplateRepositoryUrl(locator), checkoutDir);
|
|
11734
|
+
const cloneResult = runGitTemplateCommand(args, `cloning GitHub template ${locator.owner}/${locator.repo}`);
|
|
11735
|
+
if (cloneResult.status !== 0) {
|
|
11736
|
+
throw new Error(`Failed to clone GitHub template source ${locator.owner}/${locator.repo}.`);
|
|
11737
|
+
}
|
|
11738
|
+
}
|
|
11739
|
+
function readGitHubTemplateHeadRevision(checkoutDir) {
|
|
11740
|
+
const result = runGitTemplateCommand(["-C", checkoutDir, "rev-parse", "HEAD"], "reading GitHub template checkout revision", { captureOutput: true });
|
|
11741
|
+
if (result.status !== 0 || typeof result.stdout !== "string") {
|
|
11742
|
+
return null;
|
|
11743
|
+
}
|
|
11744
|
+
const revision = result.stdout.trim().split(/\s+/u)[0];
|
|
11745
|
+
return /^[0-9a-f]{40}$/iu.test(revision) ? revision.toLowerCase() : null;
|
|
11746
|
+
}
|
|
11747
|
+
function pinGitHubTemplateCacheRevision(locator, checkoutDir, cacheRevision) {
|
|
11748
|
+
const normalizedCacheRevision = cacheRevision.toLowerCase();
|
|
11749
|
+
if (readGitHubTemplateHeadRevision(checkoutDir) === normalizedCacheRevision) {
|
|
11750
|
+
return;
|
|
11751
|
+
}
|
|
11752
|
+
const fetchResult = runGitTemplateCommand(["-C", checkoutDir, "fetch", "--depth", "1", "origin", cacheRevision], `fetching GitHub template revision ${locator.owner}/${locator.repo}`);
|
|
11753
|
+
if (fetchResult.status !== 0) {
|
|
11754
|
+
throw createGitHubTemplateCacheRevisionRaceError(`Failed to fetch GitHub template revision ${cacheRevision} for ${locator.owner}/${locator.repo}.`);
|
|
11755
|
+
}
|
|
11756
|
+
const checkoutResult = runGitTemplateCommand(["-C", checkoutDir, "checkout", "--detach", cacheRevision], `checking out GitHub template revision ${locator.owner}/${locator.repo}`);
|
|
11757
|
+
if (checkoutResult.status !== 0) {
|
|
11758
|
+
throw createGitHubTemplateCacheRevisionRaceError(`Failed to check out GitHub template revision ${cacheRevision} for ${locator.owner}/${locator.repo}.`);
|
|
11759
|
+
}
|
|
11760
|
+
if (readGitHubTemplateHeadRevision(checkoutDir) !== normalizedCacheRevision) {
|
|
11761
|
+
throw createGitHubTemplateCacheRevisionRaceError(`GitHub template checkout did not match resolved revision ${cacheRevision} for ${locator.owner}/${locator.repo}.`);
|
|
11762
|
+
}
|
|
11763
|
+
}
|
|
11764
|
+
function getGitHubTemplateRevisionPatterns(locator) {
|
|
11765
|
+
const ref = locator.ref ?? "HEAD";
|
|
11766
|
+
if (!locator.ref) {
|
|
11767
|
+
return [ref];
|
|
11768
|
+
}
|
|
11769
|
+
if (ref.startsWith("refs/")) {
|
|
11770
|
+
return [ref, `${ref}^{}`];
|
|
11771
|
+
}
|
|
11772
|
+
return [ref, `refs/heads/${ref}`, `refs/tags/${ref}`, `refs/tags/${ref}^{}`];
|
|
11773
|
+
}
|
|
11774
|
+
function pickGitHubTemplateCacheRevision(locator, revisions) {
|
|
11775
|
+
const ref = locator.ref ?? "HEAD";
|
|
11776
|
+
if (!locator.ref) {
|
|
11777
|
+
return revisions[0]?.revision ?? null;
|
|
11778
|
+
}
|
|
11779
|
+
if (!ref.startsWith("refs/")) {
|
|
11780
|
+
const branchRevision = revisions.find((entry) => entry.resolvedRef === `refs/heads/${ref}`);
|
|
11781
|
+
if (branchRevision) {
|
|
11782
|
+
return branchRevision.revision;
|
|
11783
|
+
}
|
|
11784
|
+
const peeledTagRevision = revisions.find((entry) => entry.resolvedRef === `refs/tags/${ref}^{}`);
|
|
11785
|
+
if (peeledTagRevision) {
|
|
11786
|
+
return peeledTagRevision.revision;
|
|
11314
11787
|
}
|
|
11315
|
-
|
|
11316
|
-
|
|
11788
|
+
const tagRevision = revisions.find((entry) => entry.resolvedRef === `refs/tags/${ref}`);
|
|
11789
|
+
if (tagRevision) {
|
|
11790
|
+
return tagRevision.revision;
|
|
11791
|
+
}
|
|
11792
|
+
}
|
|
11793
|
+
if (ref.startsWith("refs/tags/")) {
|
|
11794
|
+
const peeledRevision = revisions.find((entry) => entry.resolvedRef === `${ref}^{}`);
|
|
11795
|
+
if (peeledRevision) {
|
|
11796
|
+
return peeledRevision.revision;
|
|
11797
|
+
}
|
|
11798
|
+
}
|
|
11799
|
+
const exactRevision = revisions.find((entry) => entry.resolvedRef === ref);
|
|
11800
|
+
return (exactRevision ?? revisions[0])?.revision ?? null;
|
|
11801
|
+
}
|
|
11802
|
+
function resolveGitHubTemplateCacheRevision(locator) {
|
|
11803
|
+
const result = runGitTemplateCommand([
|
|
11804
|
+
"ls-remote",
|
|
11805
|
+
getGitHubTemplateRepositoryUrl(locator),
|
|
11806
|
+
...getGitHubTemplateRevisionPatterns(locator)
|
|
11807
|
+
], `checking GitHub template revision ${locator.owner}/${locator.repo}`, { captureOutput: true });
|
|
11808
|
+
if (result.status !== 0 || typeof result.stdout !== "string") {
|
|
11809
|
+
return {
|
|
11810
|
+
lookupUnavailable: true,
|
|
11811
|
+
revision: null
|
|
11812
|
+
};
|
|
11813
|
+
}
|
|
11814
|
+
const revisions = result.stdout.split(`
|
|
11815
|
+
`).map((line) => {
|
|
11816
|
+
const [revision, resolvedRef] = line.trim().split(/\s+/u);
|
|
11817
|
+
if (!/^[0-9a-f]{40}$/iu.test(revision) || !resolvedRef) {
|
|
11818
|
+
return null;
|
|
11317
11819
|
}
|
|
11318
|
-
|
|
11319
|
-
|
|
11820
|
+
return {
|
|
11821
|
+
resolvedRef,
|
|
11822
|
+
revision: revision.toLowerCase()
|
|
11823
|
+
};
|
|
11824
|
+
}).filter((entry) => entry !== null);
|
|
11825
|
+
return {
|
|
11826
|
+
lookupUnavailable: false,
|
|
11827
|
+
revision: pickGitHubTemplateCacheRevision(locator, revisions)
|
|
11828
|
+
};
|
|
11829
|
+
}
|
|
11830
|
+
function getGitHubTemplateCacheMetadata(locator, revision) {
|
|
11831
|
+
return {
|
|
11832
|
+
...revision ? { revision } : {},
|
|
11833
|
+
owner: locator.owner,
|
|
11834
|
+
ref: locator.ref,
|
|
11835
|
+
repo: locator.repo,
|
|
11836
|
+
sourcePath: locator.sourcePath
|
|
11837
|
+
};
|
|
11838
|
+
}
|
|
11839
|
+
async function reuseGitHubTemplateCacheByMetadata(locator) {
|
|
11840
|
+
const cachedSource = await findReusableExternalTemplateSourceCache({
|
|
11841
|
+
metadata: getGitHubTemplateCacheMetadata(locator),
|
|
11842
|
+
namespace: "github"
|
|
11843
|
+
});
|
|
11844
|
+
if (!cachedSource) {
|
|
11845
|
+
return null;
|
|
11846
|
+
}
|
|
11847
|
+
const sourceDir = resolveGitHubTemplateDirectory(cachedSource.sourceDir, locator);
|
|
11848
|
+
await assertNoSymlinks2(sourceDir);
|
|
11849
|
+
return {
|
|
11850
|
+
blockDir: sourceDir,
|
|
11851
|
+
rootDir: sourceDir
|
|
11852
|
+
};
|
|
11853
|
+
}
|
|
11854
|
+
async function resolveGitHubTemplateSource(locator) {
|
|
11855
|
+
const cacheEnabled = isExternalTemplateCacheEnabled();
|
|
11856
|
+
let cacheRevisionLookupUnavailable = false;
|
|
11857
|
+
let cacheRevision = null;
|
|
11858
|
+
if (cacheEnabled) {
|
|
11859
|
+
try {
|
|
11860
|
+
const resolvedRevision = resolveGitHubTemplateCacheRevision(locator);
|
|
11861
|
+
cacheRevision = resolvedRevision.revision;
|
|
11862
|
+
cacheRevisionLookupUnavailable = resolvedRevision.lookupUnavailable;
|
|
11863
|
+
} catch {
|
|
11864
|
+
cacheRevision = null;
|
|
11865
|
+
cacheRevisionLookupUnavailable = true;
|
|
11320
11866
|
}
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11867
|
+
}
|
|
11868
|
+
if (cacheEnabled && !cacheRevision && cacheRevisionLookupUnavailable) {
|
|
11869
|
+
const cachedSource = await reuseGitHubTemplateCacheByMetadata(locator);
|
|
11870
|
+
if (cachedSource) {
|
|
11871
|
+
return cachedSource;
|
|
11325
11872
|
}
|
|
11326
|
-
|
|
11327
|
-
|
|
11873
|
+
}
|
|
11874
|
+
if (cacheRevision) {
|
|
11875
|
+
const resolvedCacheRevision = cacheRevision;
|
|
11876
|
+
try {
|
|
11877
|
+
const cachedSource = await resolveExternalTemplateSourceCache({
|
|
11878
|
+
keyParts: [
|
|
11879
|
+
"github",
|
|
11880
|
+
locator.owner,
|
|
11881
|
+
locator.repo,
|
|
11882
|
+
locator.sourcePath,
|
|
11883
|
+
locator.ref ?? "",
|
|
11884
|
+
resolvedCacheRevision
|
|
11885
|
+
],
|
|
11886
|
+
metadata: getGitHubTemplateCacheMetadata(locator, resolvedCacheRevision),
|
|
11887
|
+
namespace: "github"
|
|
11888
|
+
}, async (checkoutDir2) => {
|
|
11889
|
+
cloneGitHubTemplateSource(locator, checkoutDir2);
|
|
11890
|
+
const sourceDir = resolveGitHubTemplateDirectory(checkoutDir2, locator);
|
|
11891
|
+
await assertNoSymlinks2(sourceDir);
|
|
11892
|
+
pinGitHubTemplateCacheRevision(locator, checkoutDir2, resolvedCacheRevision);
|
|
11893
|
+
});
|
|
11894
|
+
if (cachedSource) {
|
|
11895
|
+
const sourceDir = resolveGitHubTemplateDirectory(cachedSource.sourceDir, locator);
|
|
11896
|
+
await assertNoSymlinks2(sourceDir);
|
|
11897
|
+
return {
|
|
11898
|
+
blockDir: sourceDir,
|
|
11899
|
+
rootDir: sourceDir
|
|
11900
|
+
};
|
|
11901
|
+
}
|
|
11902
|
+
} catch (error) {
|
|
11903
|
+
if (!isGitHubTemplateCacheRevisionRaceError(error)) {
|
|
11904
|
+
throw error;
|
|
11905
|
+
}
|
|
11328
11906
|
}
|
|
11907
|
+
}
|
|
11908
|
+
const { path: remoteRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
|
|
11909
|
+
const checkoutDir = path17.join(remoteRoot, "source");
|
|
11910
|
+
try {
|
|
11911
|
+
cloneGitHubTemplateSource(locator, checkoutDir);
|
|
11912
|
+
const sourceDir = resolveGitHubTemplateDirectory(checkoutDir, locator);
|
|
11329
11913
|
await assertNoSymlinks2(sourceDir);
|
|
11330
11914
|
return {
|
|
11331
11915
|
blockDir: sourceDir,
|
|
@@ -11339,8 +11923,8 @@ async function resolveGitHubTemplateSource(locator) {
|
|
|
11339
11923
|
}
|
|
11340
11924
|
async function resolveTemplateSeed(locator, cwd) {
|
|
11341
11925
|
if (locator.kind === "path") {
|
|
11342
|
-
const sourceDir =
|
|
11343
|
-
if (!
|
|
11926
|
+
const sourceDir = path17.resolve(cwd, locator.templatePath);
|
|
11927
|
+
if (!fs14.existsSync(sourceDir)) {
|
|
11344
11928
|
throw new Error(`Template path does not exist: ${sourceDir}`);
|
|
11345
11929
|
}
|
|
11346
11930
|
await assertNoSymlinks2(sourceDir);
|
|
@@ -11464,6 +12048,41 @@ async function resolveTemplateSource(templateId, cwd, variables, variant) {
|
|
|
11464
12048
|
}
|
|
11465
12049
|
}
|
|
11466
12050
|
|
|
12051
|
+
// ../wp-typia-project-tools/src/runtime/version-floor.ts
|
|
12052
|
+
function parseVersionFloorParts(value) {
|
|
12053
|
+
return value.split(".").map((part, index) => {
|
|
12054
|
+
if (!/^\d+$/u.test(part)) {
|
|
12055
|
+
throw new Error(`parseVersionFloorParts received an invalid version floor "${value}" at segment ${index + 1}.`);
|
|
12056
|
+
}
|
|
12057
|
+
return Number.parseInt(part, 10);
|
|
12058
|
+
});
|
|
12059
|
+
}
|
|
12060
|
+
function compareVersionFloors(left, right) {
|
|
12061
|
+
const leftParts = parseVersionFloorParts(left);
|
|
12062
|
+
const rightParts = parseVersionFloorParts(right);
|
|
12063
|
+
const length = Math.max(leftParts.length, rightParts.length);
|
|
12064
|
+
for (let index = 0;index < length; index += 1) {
|
|
12065
|
+
const leftValue = leftParts[index] ?? 0;
|
|
12066
|
+
const rightValue = rightParts[index] ?? 0;
|
|
12067
|
+
if (leftValue > rightValue) {
|
|
12068
|
+
return 1;
|
|
12069
|
+
}
|
|
12070
|
+
if (leftValue < rightValue) {
|
|
12071
|
+
return -1;
|
|
12072
|
+
}
|
|
12073
|
+
}
|
|
12074
|
+
return 0;
|
|
12075
|
+
}
|
|
12076
|
+
function pickHigherVersionFloor(current, candidate) {
|
|
12077
|
+
if (!candidate) {
|
|
12078
|
+
return current;
|
|
12079
|
+
}
|
|
12080
|
+
if (!current) {
|
|
12081
|
+
return candidate;
|
|
12082
|
+
}
|
|
12083
|
+
return compareVersionFloors(current, candidate) >= 0 ? current : candidate;
|
|
12084
|
+
}
|
|
12085
|
+
|
|
11467
12086
|
// ../wp-typia-project-tools/src/runtime/ai-feature-capability.ts
|
|
11468
12087
|
var AI_FEATURE_DEFINITIONS = {
|
|
11469
12088
|
wordpressAiClient: {
|
|
@@ -11528,39 +12147,6 @@ var DEFAULT_AI_FEATURE_REGISTRY = Object.values(AI_FEATURE_DEFINITIONS).reduce((
|
|
|
11528
12147
|
accumulator[definition.id] = definition;
|
|
11529
12148
|
return accumulator;
|
|
11530
12149
|
}, {});
|
|
11531
|
-
function parseVersionFloorParts(value) {
|
|
11532
|
-
return value.split(".").map((part, index) => {
|
|
11533
|
-
if (!/^\d+$/.test(part)) {
|
|
11534
|
-
throw new Error(`parseVersionFloorParts received an invalid version floor "${value}" at segment ${index + 1}.`);
|
|
11535
|
-
}
|
|
11536
|
-
return Number.parseInt(part, 10);
|
|
11537
|
-
});
|
|
11538
|
-
}
|
|
11539
|
-
function compareVersionFloors(left, right) {
|
|
11540
|
-
const leftParts = parseVersionFloorParts(left);
|
|
11541
|
-
const rightParts = parseVersionFloorParts(right);
|
|
11542
|
-
const length = Math.max(leftParts.length, rightParts.length);
|
|
11543
|
-
for (let index = 0;index < length; index += 1) {
|
|
11544
|
-
const leftValue = leftParts[index] ?? 0;
|
|
11545
|
-
const rightValue = rightParts[index] ?? 0;
|
|
11546
|
-
if (leftValue > rightValue) {
|
|
11547
|
-
return 1;
|
|
11548
|
-
}
|
|
11549
|
-
if (leftValue < rightValue) {
|
|
11550
|
-
return -1;
|
|
11551
|
-
}
|
|
11552
|
-
}
|
|
11553
|
-
return 0;
|
|
11554
|
-
}
|
|
11555
|
-
function pickHigherVersionFloor(current, candidate) {
|
|
11556
|
-
if (!candidate) {
|
|
11557
|
-
return current;
|
|
11558
|
-
}
|
|
11559
|
-
if (!current) {
|
|
11560
|
-
return candidate;
|
|
11561
|
-
}
|
|
11562
|
-
return compareVersionFloors(current, candidate) >= 0 ? current : candidate;
|
|
11563
|
-
}
|
|
11564
12150
|
function normalizeSelections(selections) {
|
|
11565
12151
|
const normalized = new Map;
|
|
11566
12152
|
for (const selection of selections) {
|
|
@@ -11625,35 +12211,8 @@ var REQUIRED_WORKSPACE_ABILITY_COMPATIBILITY = [
|
|
|
11625
12211
|
mode: "required"
|
|
11626
12212
|
}
|
|
11627
12213
|
];
|
|
11628
|
-
function
|
|
11629
|
-
return
|
|
11630
|
-
if (!/^\d+$/u.test(part)) {
|
|
11631
|
-
throw new Error(`parseVersionFloorParts received an invalid version floor "${value}" at segment ${index + 1}.`);
|
|
11632
|
-
}
|
|
11633
|
-
return Number.parseInt(part, 10);
|
|
11634
|
-
});
|
|
11635
|
-
}
|
|
11636
|
-
function compareVersionFloors2(left, right) {
|
|
11637
|
-
const leftParts = parseVersionFloorParts2(left);
|
|
11638
|
-
const rightParts = parseVersionFloorParts2(right);
|
|
11639
|
-
const length = Math.max(leftParts.length, rightParts.length);
|
|
11640
|
-
for (let index = 0;index < length; index += 1) {
|
|
11641
|
-
const leftValue = leftParts[index] ?? 0;
|
|
11642
|
-
const rightValue = rightParts[index] ?? 0;
|
|
11643
|
-
if (leftValue > rightValue) {
|
|
11644
|
-
return 1;
|
|
11645
|
-
}
|
|
11646
|
-
if (leftValue < rightValue) {
|
|
11647
|
-
return -1;
|
|
11648
|
-
}
|
|
11649
|
-
}
|
|
11650
|
-
return 0;
|
|
11651
|
-
}
|
|
11652
|
-
function pickHigherVersionFloor2(current, candidate) {
|
|
11653
|
-
if (!candidate) {
|
|
11654
|
-
return current;
|
|
11655
|
-
}
|
|
11656
|
-
return compareVersionFloors2(current, candidate) >= 0 ? current : candidate;
|
|
12214
|
+
function pickHigherScaffoldVersionFloor(current, candidate) {
|
|
12215
|
+
return pickHigherVersionFloor(current, candidate) ?? current;
|
|
11657
12216
|
}
|
|
11658
12217
|
function pickHigherHeaderVersionFloor(policyValue, currentValue) {
|
|
11659
12218
|
const normalizedCurrentValue = currentValue.trim();
|
|
@@ -11661,7 +12220,7 @@ function pickHigherHeaderVersionFloor(policyValue, currentValue) {
|
|
|
11661
12220
|
return policyValue;
|
|
11662
12221
|
}
|
|
11663
12222
|
try {
|
|
11664
|
-
return
|
|
12223
|
+
return pickHigherScaffoldVersionFloor(policyValue, normalizedCurrentValue);
|
|
11665
12224
|
} catch {
|
|
11666
12225
|
return policyValue;
|
|
11667
12226
|
}
|
|
@@ -11682,9 +12241,9 @@ function resolveScaffoldCompatibilityPolicy(selections, {
|
|
|
11682
12241
|
baseline = DEFAULT_SCAFFOLD_COMPATIBILITY
|
|
11683
12242
|
} = {}) {
|
|
11684
12243
|
const capabilityPlan = resolveAiFeatureCapabilityPlan(selections);
|
|
11685
|
-
const requiresAtLeast =
|
|
11686
|
-
const requiresPhp =
|
|
11687
|
-
const testedUpTo =
|
|
12244
|
+
const requiresAtLeast = pickHigherScaffoldVersionFloor(baseline.requiresAtLeast, capabilityPlan.hardMinimums.wordpress);
|
|
12245
|
+
const requiresPhp = pickHigherScaffoldVersionFloor(baseline.requiresPhp, capabilityPlan.hardMinimums.php);
|
|
12246
|
+
const testedUpTo = pickHigherScaffoldVersionFloor(baseline.testedUpTo, requiresAtLeast);
|
|
11688
12247
|
return {
|
|
11689
12248
|
capabilityPlan,
|
|
11690
12249
|
pluginHeader: {
|
|
@@ -13487,6 +14046,7 @@ import { useBlockProps, InspectorControls, RichText, BlockControls, AlignmentToo
|
|
|
13487
14046
|
import { PanelBody, RangeControl, Button, Notice } from '@wordpress/components';
|
|
13488
14047
|
import { useState } from '@wordpress/element';
|
|
13489
14048
|
import currentManifest from './manifest-document';
|
|
14049
|
+
import { {{slugCamelCase}}Store } from './interactivity-store';
|
|
13490
14050
|
import {
|
|
13491
14051
|
InspectorFromManifest,
|
|
13492
14052
|
useEditorFields,
|
|
@@ -13567,17 +14127,22 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
13567
14127
|
|
|
13568
14128
|
const blockProps = useBlockProps({
|
|
13569
14129
|
className: \`{{cssClassName}} {{cssClassName}}--\${interactiveMode}\`,
|
|
13570
|
-
'data-wp-interactive':
|
|
13571
|
-
'data-wp-context': JSON.stringify(
|
|
13572
|
-
|
|
13573
|
-
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
14130
|
+
'data-wp-interactive': {{slugCamelCase}}Store.directive.interactive,
|
|
14131
|
+
'data-wp-context': JSON.stringify(
|
|
14132
|
+
{{slugCamelCase}}Store.createContext({
|
|
14133
|
+
clicks: clickCount,
|
|
14134
|
+
isAnimating,
|
|
14135
|
+
isVisible,
|
|
14136
|
+
animation,
|
|
14137
|
+
maxClicks,
|
|
14138
|
+
})
|
|
14139
|
+
)
|
|
13578
14140
|
});
|
|
13579
14141
|
const previewContentStyle = { textAlign: alignmentValue };
|
|
13580
14142
|
const progressBarStyle = { width: \`\${(clickCount / maxClicks) * 100}%\` };
|
|
14143
|
+
const clicksDirective = {{slugCamelCase}}Store.directive.state('clicks');
|
|
14144
|
+
const isAnimatingDirective = {{slugCamelCase}}Store.directive.state('isAnimating');
|
|
14145
|
+
const progressDirective = {{slugCamelCase}}Store.directive.state('progress') + " + '%'";
|
|
13581
14146
|
|
|
13582
14147
|
const resetCounter = () => {
|
|
13583
14148
|
updateField('clickCount', 0);
|
|
@@ -13674,9 +14239,9 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
13674
14239
|
<div
|
|
13675
14240
|
className={\`{{cssClassName}}__content \${isAnimating ? 'is-animating' : ''}\`}
|
|
13676
14241
|
style={previewContentStyle}
|
|
13677
|
-
data-wp-on--click={isPreviewing ? '
|
|
13678
|
-
data-wp-on--mouseenter={isPreviewing && interactiveMode === 'hover' ? '
|
|
13679
|
-
data-wp-on--mouseleave={isPreviewing && interactiveMode === 'hover' ? '
|
|
14242
|
+
data-wp-on--click={isPreviewing ? {{slugCamelCase}}Store.directive.action('handleClick') : undefined}
|
|
14243
|
+
data-wp-on--mouseenter={isPreviewing && interactiveMode === 'hover' ? {{slugCamelCase}}Store.directive.action('handleMouseEnter') : undefined}
|
|
14244
|
+
data-wp-on--mouseleave={isPreviewing && interactiveMode === 'hover' ? {{slugCamelCase}}Store.directive.action('handleMouseLeave') : undefined}
|
|
13680
14245
|
>
|
|
13681
14246
|
<RichText
|
|
13682
14247
|
tagName="p"
|
|
@@ -13705,7 +14270,7 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
13705
14270
|
</span>
|
|
13706
14271
|
<span
|
|
13707
14272
|
className="{{cssClassName}}__counter-value"
|
|
13708
|
-
data-wp-text=
|
|
14273
|
+
data-wp-text={clicksDirective}
|
|
13709
14274
|
>
|
|
13710
14275
|
{clickCount}
|
|
13711
14276
|
</span>
|
|
@@ -13717,7 +14282,7 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
13717
14282
|
<div
|
|
13718
14283
|
className="{{cssClassName}}__progress-bar"
|
|
13719
14284
|
style={progressBarStyle}
|
|
13720
|
-
data-wp-style--width=
|
|
14285
|
+
data-wp-style--width={progressDirective}
|
|
13721
14286
|
/>
|
|
13722
14287
|
</div>
|
|
13723
14288
|
)}
|
|
@@ -13725,7 +14290,7 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
13725
14290
|
{animation !== 'none' && (
|
|
13726
14291
|
<div
|
|
13727
14292
|
className={\`{{cssClassName}}__animation \${isAnimating ? 'is-active' : ''}\`}
|
|
13728
|
-
data-wp-class--is-active=
|
|
14293
|
+
data-wp-class--is-active={isAnimatingDirective}
|
|
13729
14294
|
>
|
|
13730
14295
|
{animation}
|
|
13731
14296
|
</div>
|
|
@@ -13738,6 +14303,7 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
13738
14303
|
`;
|
|
13739
14304
|
var INTERACTIVITY_SAVE_TEMPLATE = `import { useBlockProps, RichText } from '@wordpress/block-editor';
|
|
13740
14305
|
import { __ } from '@wordpress/i18n';
|
|
14306
|
+
import { {{slugCamelCase}}Store } from './interactivity-store';
|
|
13741
14307
|
import type { {{pascalCase}}Attributes } from './types';
|
|
13742
14308
|
|
|
13743
14309
|
export default function Save({ attributes }: { attributes: {{pascalCase}}Attributes }) {
|
|
@@ -13749,27 +14315,41 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
13749
14315
|
const maxClicks = attributes.maxClicks ?? 0;
|
|
13750
14316
|
const showCounter = attributes.showCounter ?? true;
|
|
13751
14317
|
const contentStyle = { textAlign: attributes.alignment };
|
|
14318
|
+
const clickActionDirective = {{slugCamelCase}}Store.directive.action('handleClick');
|
|
14319
|
+
const visibilityHiddenDirective = {{slugCamelCase}}Store.directive.negate(
|
|
14320
|
+
{{slugCamelCase}}Store.directive.state('isVisible')
|
|
14321
|
+
);
|
|
14322
|
+
const clicksDirective = {{slugCamelCase}}Store.directive.state('clicks');
|
|
14323
|
+
const clampedClicksDirective = {{slugCamelCase}}Store.directive.state('clampedClicks');
|
|
14324
|
+
const isAnimatingDirective = {{slugCamelCase}}Store.directive.state('isAnimating');
|
|
14325
|
+
const completionHiddenDirective = {{slugCamelCase}}Store.directive.negate(
|
|
14326
|
+
{{slugCamelCase}}Store.directive.state('isComplete')
|
|
14327
|
+
);
|
|
14328
|
+
const resetActionDirective = {{slugCamelCase}}Store.directive.action('reset');
|
|
13752
14329
|
const blockProps = useBlockProps.save({
|
|
13753
14330
|
className: \`{{cssClassName}} {{cssClassName}}--\${interactiveMode}\`,
|
|
13754
|
-
'data-wp-interactive':
|
|
13755
|
-
'data-wp-context': JSON.stringify(
|
|
13756
|
-
|
|
13757
|
-
|
|
13758
|
-
|
|
13759
|
-
|
|
13760
|
-
|
|
13761
|
-
|
|
14331
|
+
'data-wp-interactive': {{slugCamelCase}}Store.directive.interactive,
|
|
14332
|
+
'data-wp-context': JSON.stringify(
|
|
14333
|
+
{{slugCamelCase}}Store.createContext({
|
|
14334
|
+
clicks: clickCount,
|
|
14335
|
+
isAnimating,
|
|
14336
|
+
isVisible,
|
|
14337
|
+
animation,
|
|
14338
|
+
maxClicks,
|
|
14339
|
+
})
|
|
14340
|
+
)
|
|
13762
14341
|
});
|
|
14342
|
+
const progressDirective = {{slugCamelCase}}Store.directive.state('progress') + " + '%'";
|
|
13763
14343
|
|
|
13764
14344
|
return (
|
|
13765
14345
|
<div {...blockProps}>
|
|
13766
14346
|
<div
|
|
13767
14347
|
className={\`{{cssClassName}}__content \${isAnimating ? 'is-animating' : ''}\`}
|
|
13768
14348
|
style={contentStyle}
|
|
13769
|
-
data-wp-on--click=
|
|
13770
|
-
data-wp-on--mouseenter={interactiveMode === 'hover' ? '
|
|
13771
|
-
data-wp-on--mouseleave={interactiveMode === 'hover' ? '
|
|
13772
|
-
data-wp-bind--hidden=
|
|
14349
|
+
data-wp-on--click={clickActionDirective}
|
|
14350
|
+
data-wp-on--mouseenter={interactiveMode === 'hover' ? {{slugCamelCase}}Store.directive.action('handleMouseEnter') : undefined}
|
|
14351
|
+
data-wp-on--mouseleave={interactiveMode === 'hover' ? {{slugCamelCase}}Store.directive.action('handleMouseLeave') : undefined}
|
|
14352
|
+
data-wp-bind--hidden={visibilityHiddenDirective}
|
|
13773
14353
|
>
|
|
13774
14354
|
<RichText.Content
|
|
13775
14355
|
tagName="p"
|
|
@@ -13789,7 +14369,7 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
13789
14369
|
</span>
|
|
13790
14370
|
<span
|
|
13791
14371
|
className="{{cssClassName}}__counter-value"
|
|
13792
|
-
data-wp-text=
|
|
14372
|
+
data-wp-text={clicksDirective}
|
|
13793
14373
|
>
|
|
13794
14374
|
{clickCount}
|
|
13795
14375
|
</span>
|
|
@@ -13805,8 +14385,8 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
13805
14385
|
aria-valuemin={0}
|
|
13806
14386
|
aria-valuemax={maxClicks}
|
|
13807
14387
|
aria-valuenow={Math.min(clickCount, maxClicks)}
|
|
13808
|
-
data-wp-bind--aria-valuenow=
|
|
13809
|
-
data-wp-style--width=
|
|
14388
|
+
data-wp-bind--aria-valuenow={clampedClicksDirective}
|
|
14389
|
+
data-wp-style--width={progressDirective}
|
|
13810
14390
|
/>
|
|
13811
14391
|
</div>
|
|
13812
14392
|
)}
|
|
@@ -13814,7 +14394,7 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
13814
14394
|
<div
|
|
13815
14395
|
className={\`{{cssClassName}}__animation \${animation}\`}
|
|
13816
14396
|
aria-hidden="true"
|
|
13817
|
-
data-wp-class--is-active=
|
|
14397
|
+
data-wp-class--is-active={isAnimatingDirective}
|
|
13818
14398
|
/>
|
|
13819
14399
|
|
|
13820
14400
|
{maxClicks > 0 && (
|
|
@@ -13823,7 +14403,7 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
13823
14403
|
role="status"
|
|
13824
14404
|
aria-live="polite"
|
|
13825
14405
|
aria-atomic="true"
|
|
13826
|
-
data-wp-bind--hidden=
|
|
14406
|
+
data-wp-bind--hidden={completionHiddenDirective}
|
|
13827
14407
|
>
|
|
13828
14408
|
{ __( '\uD83C\uDF89 Complete!', '{{textDomain}}' ) }
|
|
13829
14409
|
</div>
|
|
@@ -13831,7 +14411,7 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
13831
14411
|
|
|
13832
14412
|
<button
|
|
13833
14413
|
className="{{cssClassName}}__reset"
|
|
13834
|
-
data-wp-on--click=
|
|
14414
|
+
data-wp-on--click={resetActionDirective}
|
|
13835
14415
|
aria-label={ __( 'Reset counter', '{{textDomain}}' ) }
|
|
13836
14416
|
>
|
|
13837
14417
|
<span aria-hidden="true">\u21BB</span>
|
|
@@ -13881,20 +14461,214 @@ const registration = buildScaffoldBlockRegistration(
|
|
|
13881
14461
|
|
|
13882
14462
|
registerScaffoldBlockType(registration.name, registration.settings);
|
|
13883
14463
|
`;
|
|
14464
|
+
var INTERACTIVITY_STORE_TEMPLATE = `import type {
|
|
14465
|
+
{{pascalCase}}Context,
|
|
14466
|
+
{{pascalCase}}State,
|
|
14467
|
+
} from './types';
|
|
14468
|
+
|
|
14469
|
+
type InteractivityActionShape = object;
|
|
14470
|
+
type InteractivityCallbackShape = object;
|
|
14471
|
+
type InteractivityContextShape = object;
|
|
14472
|
+
type InteractivityStateShape = object;
|
|
14473
|
+
type InteractivityCallable = Function;
|
|
14474
|
+
type InteractivityKey<T extends object> = Extract<keyof T, string>;
|
|
14475
|
+
type InteractivityMethodKey<T extends object> = {
|
|
14476
|
+
[Key in InteractivityKey<T>]: T[Key] extends InteractivityCallable ? Key : never;
|
|
14477
|
+
}[InteractivityKey<T>];
|
|
14478
|
+
|
|
14479
|
+
type InteractivityDirectivePath<
|
|
14480
|
+
Root extends string,
|
|
14481
|
+
Key extends string,
|
|
14482
|
+
> = \`\${Root}.\${Key}\`;
|
|
14483
|
+
|
|
14484
|
+
type NegatedInteractivityDirectivePath<Path extends string> = \`!\${Path}\`;
|
|
14485
|
+
|
|
14486
|
+
export interface TypedInteractivityDirectiveHelpers<
|
|
14487
|
+
State extends InteractivityStateShape,
|
|
14488
|
+
Context extends InteractivityContextShape,
|
|
14489
|
+
Actions extends InteractivityActionShape,
|
|
14490
|
+
Callbacks extends InteractivityCallbackShape,
|
|
14491
|
+
Namespace extends string,
|
|
14492
|
+
> {
|
|
14493
|
+
readonly interactive: Namespace;
|
|
14494
|
+
action<Key extends InteractivityMethodKey<Actions>>(
|
|
14495
|
+
key: Key,
|
|
14496
|
+
): InteractivityDirectivePath<'actions', Key>;
|
|
14497
|
+
callback<Key extends InteractivityMethodKey<Callbacks>>(
|
|
14498
|
+
key: Key,
|
|
14499
|
+
): InteractivityDirectivePath<'callbacks', Key>;
|
|
14500
|
+
state<Key extends InteractivityKey<State>>(
|
|
14501
|
+
key: Key,
|
|
14502
|
+
): InteractivityDirectivePath<'state', Key>;
|
|
14503
|
+
context<Key extends InteractivityKey<Context>>(
|
|
14504
|
+
key: Key,
|
|
14505
|
+
): InteractivityDirectivePath<'context', Key>;
|
|
14506
|
+
negate<Path extends string>(
|
|
14507
|
+
path: Path,
|
|
14508
|
+
): NegatedInteractivityDirectivePath<Path>;
|
|
14509
|
+
}
|
|
14510
|
+
|
|
14511
|
+
export interface TypedInteractivityStore<
|
|
14512
|
+
Namespace extends string,
|
|
14513
|
+
State extends InteractivityStateShape,
|
|
14514
|
+
Context extends InteractivityContextShape,
|
|
14515
|
+
Actions extends InteractivityActionShape,
|
|
14516
|
+
Callbacks extends InteractivityCallbackShape,
|
|
14517
|
+
> {
|
|
14518
|
+
readonly namespace: Namespace;
|
|
14519
|
+
readonly state: State;
|
|
14520
|
+
readonly context: Context;
|
|
14521
|
+
readonly actions: Actions;
|
|
14522
|
+
readonly callbacks: Callbacks;
|
|
14523
|
+
readonly directive: TypedInteractivityDirectiveHelpers<
|
|
14524
|
+
State,
|
|
14525
|
+
Context,
|
|
14526
|
+
Actions,
|
|
14527
|
+
Callbacks,
|
|
14528
|
+
Namespace
|
|
14529
|
+
>;
|
|
14530
|
+
createContext(value: Context): Context;
|
|
14531
|
+
}
|
|
14532
|
+
|
|
14533
|
+
export function defineInteractivityStore<
|
|
14534
|
+
Namespace extends string,
|
|
14535
|
+
State extends InteractivityStateShape,
|
|
14536
|
+
Context extends InteractivityContextShape,
|
|
14537
|
+
Actions extends InteractivityActionShape,
|
|
14538
|
+
Callbacks extends InteractivityCallbackShape,
|
|
14539
|
+
>(config: {
|
|
14540
|
+
readonly namespace: Namespace;
|
|
14541
|
+
readonly state: State;
|
|
14542
|
+
readonly context: Context;
|
|
14543
|
+
readonly actions: Actions;
|
|
14544
|
+
readonly callbacks: Callbacks;
|
|
14545
|
+
}): TypedInteractivityStore<Namespace, State, Context, Actions, Callbacks> {
|
|
14546
|
+
return {
|
|
14547
|
+
namespace: config.namespace,
|
|
14548
|
+
state: config.state,
|
|
14549
|
+
context: config.context,
|
|
14550
|
+
actions: config.actions,
|
|
14551
|
+
callbacks: config.callbacks,
|
|
14552
|
+
directive: {
|
|
14553
|
+
interactive: config.namespace,
|
|
14554
|
+
action<Key extends InteractivityMethodKey<Actions>>(key: Key) {
|
|
14555
|
+
return \`actions.\${key}\` as InteractivityDirectivePath<'actions', Key>;
|
|
14556
|
+
},
|
|
14557
|
+
callback<Key extends InteractivityMethodKey<Callbacks>>(key: Key) {
|
|
14558
|
+
return \`callbacks.\${key}\` as InteractivityDirectivePath<'callbacks', Key>;
|
|
14559
|
+
},
|
|
14560
|
+
state<Key extends InteractivityKey<State>>(key: Key) {
|
|
14561
|
+
return \`state.\${key}\` as InteractivityDirectivePath<'state', Key>;
|
|
14562
|
+
},
|
|
14563
|
+
context<Key extends InteractivityKey<Context>>(key: Key) {
|
|
14564
|
+
return \`context.\${key}\` as InteractivityDirectivePath<'context', Key>;
|
|
14565
|
+
},
|
|
14566
|
+
negate<Path extends string>(path: Path) {
|
|
14567
|
+
return \`!\${path}\` as NegatedInteractivityDirectivePath<Path>;
|
|
14568
|
+
},
|
|
14569
|
+
},
|
|
14570
|
+
createContext(value) {
|
|
14571
|
+
return value;
|
|
14572
|
+
},
|
|
14573
|
+
};
|
|
14574
|
+
}
|
|
14575
|
+
|
|
14576
|
+
type InteractivityActionHandler = Function;
|
|
14577
|
+
|
|
14578
|
+
export interface {{pascalCase}}StoreActions {
|
|
14579
|
+
handleClick: InteractivityActionHandler;
|
|
14580
|
+
handleMouseEnter: InteractivityActionHandler;
|
|
14581
|
+
handleMouseLeave: InteractivityActionHandler;
|
|
14582
|
+
reset: InteractivityActionHandler;
|
|
14583
|
+
}
|
|
14584
|
+
|
|
14585
|
+
export interface {{pascalCase}}StoreCallbacks {}
|
|
14586
|
+
|
|
14587
|
+
export const {{slugCamelCase}}Store = defineInteractivityStore({
|
|
14588
|
+
namespace: '{{slugKebabCase}}',
|
|
14589
|
+
state: {} as {{pascalCase}}State,
|
|
14590
|
+
context: {} as {{pascalCase}}Context,
|
|
14591
|
+
actions: {} as {{pascalCase}}StoreActions,
|
|
14592
|
+
callbacks: {} as {{pascalCase}}StoreCallbacks,
|
|
14593
|
+
});
|
|
14594
|
+
`;
|
|
13884
14595
|
var INTERACTIVITY_SCRIPT_TEMPLATE = `/**
|
|
13885
14596
|
* WordPress Interactivity API implementation for {{title}} block
|
|
13886
14597
|
*/
|
|
13887
14598
|
import { store, getContext, getElement, withSyncEvent } from '@wordpress/interactivity';
|
|
13888
|
-
import
|
|
14599
|
+
import {
|
|
14600
|
+
{{slugCamelCase}}Store,
|
|
14601
|
+
type {{pascalCase}}StoreActions,
|
|
14602
|
+
} from './interactivity-store';
|
|
14603
|
+
import type { {{pascalCase}}Context, {{pascalCase}}State } from './types';
|
|
13889
14604
|
|
|
13890
14605
|
function getBlockContext() {
|
|
13891
14606
|
return getContext<{{pascalCase}}Context>();
|
|
13892
14607
|
}
|
|
13893
14608
|
|
|
13894
|
-
|
|
13895
|
-
|
|
13896
|
-
|
|
13897
|
-
|
|
14609
|
+
const actions: {{pascalCase}}StoreActions = {
|
|
14610
|
+
// Handle block click
|
|
14611
|
+
handleClick: () => {
|
|
14612
|
+
const context = getBlockContext();
|
|
14613
|
+
const { ref } = getElement();
|
|
14614
|
+
|
|
14615
|
+
if (!ref) {
|
|
14616
|
+
return;
|
|
14617
|
+
}
|
|
14618
|
+
|
|
14619
|
+
if (context.maxClicks > 0 && context.clicks >= context.maxClicks) {
|
|
14620
|
+
return;
|
|
14621
|
+
}
|
|
14622
|
+
|
|
14623
|
+
const previousClicks = context.clicks;
|
|
14624
|
+
|
|
14625
|
+
// Increment click counter
|
|
14626
|
+
context.clicks += 1;
|
|
14627
|
+
|
|
14628
|
+
// Trigger animation
|
|
14629
|
+
if (context.animation !== 'none') {
|
|
14630
|
+
context.isAnimating = true;
|
|
14631
|
+
setTimeout(() => {
|
|
14632
|
+
context.isAnimating = false;
|
|
14633
|
+
}, 1000);
|
|
14634
|
+
}
|
|
14635
|
+
|
|
14636
|
+
// Emit custom event
|
|
14637
|
+
ref.dispatchEvent(new CustomEvent('{{slugKebabCase}}:click', {
|
|
14638
|
+
detail: { clicks: context.clicks }
|
|
14639
|
+
}));
|
|
14640
|
+
|
|
14641
|
+
// Check if max clicks reached
|
|
14642
|
+
if (context.maxClicks > 0 && previousClicks < context.maxClicks && context.clicks === context.maxClicks) {
|
|
14643
|
+
ref.dispatchEvent(new CustomEvent('{{slugKebabCase}}:complete', {
|
|
14644
|
+
detail: { totalClicks: context.clicks }
|
|
14645
|
+
}));
|
|
14646
|
+
}
|
|
14647
|
+
},
|
|
14648
|
+
|
|
14649
|
+
// Handle hover events
|
|
14650
|
+
handleMouseEnter: () => {
|
|
14651
|
+
const context = getBlockContext();
|
|
14652
|
+
if (context.animation === 'none') return;
|
|
14653
|
+
context.isAnimating = true;
|
|
14654
|
+
},
|
|
14655
|
+
|
|
14656
|
+
handleMouseLeave: () => {
|
|
14657
|
+
const context = getBlockContext();
|
|
14658
|
+
if (context.animation === 'none') return;
|
|
14659
|
+
context.isAnimating = false;
|
|
14660
|
+
},
|
|
14661
|
+
|
|
14662
|
+
// Reset counter
|
|
14663
|
+
reset: withSyncEvent((event: Event) => {
|
|
14664
|
+
event.stopPropagation();
|
|
14665
|
+
const context = getBlockContext();
|
|
14666
|
+
context.clicks = 0;
|
|
14667
|
+
context.isAnimating = false;
|
|
14668
|
+
})
|
|
14669
|
+
};
|
|
14670
|
+
|
|
14671
|
+
const state = {
|
|
13898
14672
|
get clicks() {
|
|
13899
14673
|
return getBlockContext().clicks;
|
|
13900
14674
|
},
|
|
@@ -13922,70 +14696,14 @@ store('{{slugKebabCase}}', {
|
|
|
13922
14696
|
const context = getBlockContext();
|
|
13923
14697
|
return context.clicks >= context.maxClicks && context.maxClicks > 0;
|
|
13924
14698
|
}
|
|
13925
|
-
|
|
14699
|
+
} satisfies {{pascalCase}}State;
|
|
13926
14700
|
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
if (!ref) {
|
|
13935
|
-
return;
|
|
13936
|
-
}
|
|
13937
|
-
|
|
13938
|
-
if (context.maxClicks > 0 && context.clicks >= context.maxClicks) {
|
|
13939
|
-
return;
|
|
13940
|
-
}
|
|
13941
|
-
|
|
13942
|
-
const previousClicks = context.clicks;
|
|
13943
|
-
|
|
13944
|
-
// Increment click counter
|
|
13945
|
-
context.clicks += 1;
|
|
13946
|
-
|
|
13947
|
-
// Trigger animation
|
|
13948
|
-
if (context.animation !== 'none') {
|
|
13949
|
-
context.isAnimating = true;
|
|
13950
|
-
setTimeout(() => {
|
|
13951
|
-
context.isAnimating = false;
|
|
13952
|
-
}, 1000);
|
|
13953
|
-
}
|
|
13954
|
-
|
|
13955
|
-
// Emit custom event
|
|
13956
|
-
ref.dispatchEvent(new CustomEvent('{{slugKebabCase}}:click', {
|
|
13957
|
-
detail: { clicks: context.clicks }
|
|
13958
|
-
}));
|
|
13959
|
-
|
|
13960
|
-
// Check if max clicks reached
|
|
13961
|
-
if (context.maxClicks > 0 && previousClicks < context.maxClicks && context.clicks === context.maxClicks) {
|
|
13962
|
-
ref.dispatchEvent(new CustomEvent('{{slugKebabCase}}:complete', {
|
|
13963
|
-
detail: { totalClicks: context.clicks }
|
|
13964
|
-
}));
|
|
13965
|
-
}
|
|
13966
|
-
},
|
|
13967
|
-
|
|
13968
|
-
// Handle hover events
|
|
13969
|
-
handleMouseEnter: () => {
|
|
13970
|
-
const context = getBlockContext();
|
|
13971
|
-
if (context.animation === 'none') return;
|
|
13972
|
-
context.isAnimating = true;
|
|
13973
|
-
},
|
|
13974
|
-
|
|
13975
|
-
handleMouseLeave: () => {
|
|
13976
|
-
const context = getBlockContext();
|
|
13977
|
-
if (context.animation === 'none') return;
|
|
13978
|
-
context.isAnimating = false;
|
|
13979
|
-
},
|
|
13980
|
-
|
|
13981
|
-
// Reset counter
|
|
13982
|
-
reset: withSyncEvent((event: Event) => {
|
|
13983
|
-
event.stopPropagation();
|
|
13984
|
-
const context = getBlockContext();
|
|
13985
|
-
context.clicks = 0;
|
|
13986
|
-
context.isAnimating = false;
|
|
13987
|
-
})
|
|
13988
|
-
}
|
|
14701
|
+
// Store configuration
|
|
14702
|
+
store({{slugCamelCase}}Store.namespace, {
|
|
14703
|
+
// State - reactive data that updates the UI
|
|
14704
|
+
state,
|
|
14705
|
+
actions,
|
|
14706
|
+
callbacks: {{slugCamelCase}}Store.callbacks,
|
|
13989
14707
|
});
|
|
13990
14708
|
`;
|
|
13991
14709
|
var INTERACTIVITY_VALIDATORS_TEMPLATE = `import typia from 'typia';
|
|
@@ -15798,6 +16516,10 @@ function buildInteractivityCodeArtifacts(variables) {
|
|
|
15798
16516
|
relativePath: "src/interactivity.ts",
|
|
15799
16517
|
template: INTERACTIVITY_SCRIPT_TEMPLATE
|
|
15800
16518
|
},
|
|
16519
|
+
{
|
|
16520
|
+
relativePath: "src/interactivity-store.ts",
|
|
16521
|
+
template: INTERACTIVITY_STORE_TEMPLATE
|
|
16522
|
+
},
|
|
15801
16523
|
{
|
|
15802
16524
|
relativePath: "src/validators.ts",
|
|
15803
16525
|
template: INTERACTIVITY_VALIDATORS_TEMPLATE
|
|
@@ -16505,17 +17227,17 @@ async function scaffoldProject({
|
|
|
16505
17227
|
phase: "finalize-project",
|
|
16506
17228
|
title: "Finalizing scaffold output"
|
|
16507
17229
|
});
|
|
16508
|
-
const readmePath =
|
|
16509
|
-
if (!
|
|
16510
|
-
await
|
|
17230
|
+
const readmePath = path18.join(projectDir, "README.md");
|
|
17231
|
+
if (!fs15.existsSync(readmePath)) {
|
|
17232
|
+
await fsp11.writeFile(readmePath, buildReadme(resolvedTemplateId, variables, resolvedPackageManager, {
|
|
16511
17233
|
withMigrationUi: isBuiltInTemplate || isWorkspace ? withMigrationUi : false,
|
|
16512
17234
|
withTestPreset: isBuiltInTemplate ? withTestPreset : false,
|
|
16513
17235
|
withWpEnv: isBuiltInTemplate ? withWpEnv : false
|
|
16514
17236
|
}), "utf8");
|
|
16515
17237
|
}
|
|
16516
|
-
const gitignorePath =
|
|
16517
|
-
const existingGitignore =
|
|
16518
|
-
await
|
|
17238
|
+
const gitignorePath = path18.join(projectDir, ".gitignore");
|
|
17239
|
+
const existingGitignore = fs15.existsSync(gitignorePath) ? await fsp11.readFile(gitignorePath, "utf8") : "";
|
|
17240
|
+
await fsp11.writeFile(gitignorePath, mergeTextLines(buildGitignore(), existingGitignore), "utf8");
|
|
16519
17241
|
await normalizePackageJson(projectDir, resolvedPackageManager);
|
|
16520
17242
|
if (isBuiltInTemplate) {
|
|
16521
17243
|
const variableGroups = getScaffoldTemplateVariableGroups(variables);
|
|
@@ -16560,6 +17282,8 @@ async function resolveOptionalInteractiveExternalLayerId({
|
|
|
16560
17282
|
callerCwd,
|
|
16561
17283
|
externalLayerId,
|
|
16562
17284
|
externalLayerSource,
|
|
17285
|
+
listExternalTemplateLayers = listSelectableExternalTemplateLayers,
|
|
17286
|
+
resolveExternalTemplateSeed = resolveTemplateSeed,
|
|
16563
17287
|
selectExternalLayerId
|
|
16564
17288
|
}) {
|
|
16565
17289
|
if (!externalLayerSource || externalLayerId || !selectExternalLayerId) {
|
|
@@ -16568,9 +17292,9 @@ async function resolveOptionalInteractiveExternalLayerId({
|
|
|
16568
17292
|
externalLayerSource
|
|
16569
17293
|
};
|
|
16570
17294
|
}
|
|
16571
|
-
const layerSeed = await
|
|
17295
|
+
const layerSeed = await resolveExternalTemplateSeed(parseTemplateLocator(externalLayerSource), callerCwd);
|
|
16572
17296
|
try {
|
|
16573
|
-
const selectableLayers = await
|
|
17297
|
+
const selectableLayers = await listExternalTemplateLayers(layerSeed.rootDir);
|
|
16574
17298
|
if (selectableLayers.length <= 1) {
|
|
16575
17299
|
await layerSeed.cleanup?.();
|
|
16576
17300
|
return {
|
|
@@ -16586,7 +17310,6 @@ async function resolveOptionalInteractiveExternalLayerId({
|
|
|
16586
17310
|
externalLayerSource: layerSeed.rootDir
|
|
16587
17311
|
};
|
|
16588
17312
|
}
|
|
16589
|
-
await layerSeed.cleanup?.();
|
|
16590
17313
|
throw new Error(`Unknown external layer "${selectedLayerId}". Expected one of: ${selectableLayers.map((layer) => layer.id).join(", ")}`);
|
|
16591
17314
|
} catch (error) {
|
|
16592
17315
|
await layerSeed.cleanup?.();
|
|
@@ -16596,4 +17319,4 @@ async function resolveOptionalInteractiveExternalLayerId({
|
|
|
16596
17319
|
|
|
16597
17320
|
export { syncPersistenceRestArtifacts, copyInterpolatedDirectory, listInterpolatedDirectoryOutputs, getPrimaryDevelopmentScript, getOptionalOnboardingSteps, getOptionalOnboardingNote, getOptionalOnboardingShortNote, formatNonEmptyTargetDirectoryError, require_semver2 as require_semver, parseTemplateLocator, resolveExternalTemplateLayers, resolveTemplateSeed, normalizeOptionalCliString, resolveLocalCliPathOption, assertExternalLayerCompositionOptions, assertBuiltInTemplateVariantAllowed, parseAlternateRenderTargets, parseCompoundInnerBlocksPreset, OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY, REQUIRED_WORKSPACE_ABILITY_COMPATIBILITY, resolveScaffoldCompatibilityPolicy, renderScaffoldCompatibilityConfig, updatePluginHeaderCompatibility, getDefaultAnswers, resolveTemplateId, resolvePackageManagerId, collectScaffoldAnswers, DATA_STORAGE_MODES, PERSISTENCE_POLICIES, isDataStorageMode, isPersistencePolicy, scaffoldProject, resolveOptionalInteractiveExternalLayerId };
|
|
16598
17321
|
|
|
16599
|
-
//# debugId=
|
|
17322
|
+
//# debugId=C53957BD2FAAAD8464756E2164756E21
|