@wp-typia/project-tools 0.22.7 → 0.22.9
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/dist/runtime/block-targets.d.ts +40 -0
- package/dist/runtime/block-targets.js +71 -0
- package/dist/runtime/built-in-block-artifact-types.js +2 -1
- package/dist/runtime/built-in-block-attribute-specs.js +2 -1
- package/dist/runtime/built-in-block-code-artifacts.js +2 -0
- package/dist/runtime/built-in-block-non-ts-family-artifacts.js +12 -9
- package/dist/runtime/built-in-block-non-ts-render-utils.js +2 -0
- package/dist/runtime/cli-add-block-config.js +2 -1
- package/dist/runtime/cli-add-block.js +16 -4
- package/dist/runtime/cli-add-types.d.ts +8 -0
- package/dist/runtime/cli-add-types.js +11 -0
- package/dist/runtime/cli-add-workspace-ability-scaffold.js +21 -15
- package/dist/runtime/cli-add-workspace-ability.js +2 -2
- package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +17 -13
- package/dist/runtime/cli-add-workspace-admin-view.js +2 -2
- package/dist/runtime/cli-add-workspace-ai.js +2 -2
- package/dist/runtime/cli-add-workspace-assets.js +42 -48
- package/dist/runtime/cli-add-workspace-rest.js +2 -2
- package/dist/runtime/cli-add-workspace.js +6 -38
- package/dist/runtime/cli-add.d.ts +3 -2
- package/dist/runtime/cli-add.js +2 -2
- package/dist/runtime/cli-core.d.ts +4 -2
- package/dist/runtime/cli-core.js +3 -2
- package/dist/runtime/cli-diagnostics.js +6 -0
- package/dist/runtime/cli-doctor-workspace.js +2 -0
- package/dist/runtime/cli-scaffold.js +5 -4
- package/dist/runtime/create-template-validation.d.ts +10 -0
- package/dist/runtime/create-template-validation.js +95 -0
- package/dist/runtime/id-suggestions.d.ts +21 -0
- package/dist/runtime/id-suggestions.js +48 -0
- package/dist/runtime/index.d.ts +5 -2
- package/dist/runtime/index.js +3 -1
- package/dist/runtime/migration-maintenance-verify.js +2 -0
- package/dist/runtime/package-versions.js +15 -2
- package/dist/runtime/php-utils.js +66 -0
- package/dist/runtime/scaffold-answer-resolution.js +5 -108
- package/dist/runtime/scaffold-apply-utils.js +3 -2
- package/dist/runtime/scaffold-identifiers.js +4 -3
- package/dist/runtime/scaffold-template-assertions.d.ts +6 -0
- package/dist/runtime/scaffold-template-assertions.js +33 -0
- package/dist/runtime/scaffold-template-variable-groups.d.ts +2 -0
- package/dist/runtime/scaffold-template-variable-groups.js +7 -0
- package/dist/runtime/scaffold.js +3 -3
- package/dist/runtime/string-case.d.ts +2 -4
- package/dist/runtime/string-case.js +13 -4
- package/dist/runtime/template-builtins.js +11 -8
- package/dist/runtime/template-layers.js +2 -2
- package/dist/runtime/template-source-cache-policy.d.ts +53 -0
- package/dist/runtime/template-source-cache-policy.js +135 -0
- package/dist/runtime/template-source-cache.d.ts +1 -45
- package/dist/runtime/template-source-cache.js +9 -152
- package/dist/runtime/template-source-external.d.ts +3 -0
- package/dist/runtime/template-source-external.js +5 -2
- package/dist/runtime/template-source-remote.d.ts +6 -0
- package/dist/runtime/template-source-remote.js +8 -2
- package/dist/runtime/template-source-seeds.d.ts +13 -0
- package/dist/runtime/template-source-seeds.js +36 -8
- package/dist/runtime/template-source.js +2 -2
- package/dist/runtime/ts-property-names.d.ts +11 -0
- package/dist/runtime/ts-property-names.js +16 -0
- package/dist/runtime/workspace-inventory.d.ts +33 -7
- package/dist/runtime/workspace-inventory.js +94 -41
- package/package.json +11 -1
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Environment variable that disables external template cache reads and writes.
|
|
5
|
+
*
|
|
6
|
+
* Set to `0`, `false`, `no`, or `off` to bypass the cache.
|
|
7
|
+
*/
|
|
8
|
+
export const EXTERNAL_TEMPLATE_CACHE_ENV = 'WP_TYPIA_EXTERNAL_TEMPLATE_CACHE';
|
|
9
|
+
/**
|
|
10
|
+
* Environment variable that overrides the external template cache root.
|
|
11
|
+
*/
|
|
12
|
+
export const EXTERNAL_TEMPLATE_CACHE_DIR_ENV = 'WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR';
|
|
13
|
+
/**
|
|
14
|
+
* Environment variable that enables TTL-based external template cache pruning.
|
|
15
|
+
*
|
|
16
|
+
* Unset, empty, zero, negative, and non-numeric values keep pruning disabled.
|
|
17
|
+
*/
|
|
18
|
+
export const EXTERNAL_TEMPLATE_CACHE_TTL_DAYS_ENV = 'WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_TTL_DAYS';
|
|
19
|
+
/**
|
|
20
|
+
* Environment variable that overrides how often TTL pruning may scan the cache.
|
|
21
|
+
*
|
|
22
|
+
* Unset values use the default interval. Zero, negative, and non-numeric values
|
|
23
|
+
* disable scan throttling.
|
|
24
|
+
*/
|
|
25
|
+
export const EXTERNAL_TEMPLATE_CACHE_PRUNE_INTERVAL_MS_ENV = 'WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_PRUNE_INTERVAL_MS';
|
|
26
|
+
/**
|
|
27
|
+
* Milliseconds in one TTL day.
|
|
28
|
+
*/
|
|
29
|
+
const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
30
|
+
/**
|
|
31
|
+
* Default minimum interval between full external template cache prune scans.
|
|
32
|
+
*/
|
|
33
|
+
const DEFAULT_CACHE_PRUNE_INTERVAL_MS = 60 * 60 * 1000;
|
|
34
|
+
/**
|
|
35
|
+
* Normalized environment values that disable the cache.
|
|
36
|
+
*/
|
|
37
|
+
const DISABLED_CACHE_VALUES = new Set(['0', 'false', 'no', 'off']);
|
|
38
|
+
/**
|
|
39
|
+
* Checks whether remote external template source caching is enabled.
|
|
40
|
+
*
|
|
41
|
+
* Caching is enabled by default. Set `WP_TYPIA_EXTERNAL_TEMPLATE_CACHE` to
|
|
42
|
+
* `0`, `false`, `no`, or `off` to force uncached resolution.
|
|
43
|
+
*
|
|
44
|
+
* @param env Environment object to inspect, defaulting to `process.env`.
|
|
45
|
+
* @returns Whether external template source cache reads and writes are enabled.
|
|
46
|
+
*/
|
|
47
|
+
export function isExternalTemplateCacheEnabled(env = process.env) {
|
|
48
|
+
const rawValue = env[EXTERNAL_TEMPLATE_CACHE_ENV];
|
|
49
|
+
if (rawValue === undefined) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
return !DISABLED_CACHE_VALUES.has(rawValue.trim().toLowerCase());
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolves the external template source cache root directory.
|
|
56
|
+
*
|
|
57
|
+
* `WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR` overrides the location. Without an
|
|
58
|
+
* override, wp-typia uses a per-user `wp-typia-template-source-cache-*`
|
|
59
|
+
* directory inside the operating system temp directory.
|
|
60
|
+
*
|
|
61
|
+
* @param env Environment object to inspect, defaulting to `process.env`.
|
|
62
|
+
* @returns Absolute cache root directory path.
|
|
63
|
+
*/
|
|
64
|
+
export function getExternalTemplateCacheRoot(env = process.env) {
|
|
65
|
+
const configuredCacheDir = env[EXTERNAL_TEMPLATE_CACHE_DIR_ENV]?.trim();
|
|
66
|
+
if (configuredCacheDir) {
|
|
67
|
+
return path.resolve(configuredCacheDir);
|
|
68
|
+
}
|
|
69
|
+
return path.join(os.tmpdir(), `wp-typia-template-source-cache-${getCurrentUserCacheSegment()}`);
|
|
70
|
+
}
|
|
71
|
+
function parseExternalTemplateCacheTtlDays(value) {
|
|
72
|
+
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
const ttlDays = typeof value === 'number' ? value : Number(value.trim());
|
|
76
|
+
if (!Number.isFinite(ttlDays) || ttlDays <= 0) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return ttlDays;
|
|
80
|
+
}
|
|
81
|
+
export function resolveExternalTemplateCacheTtlMs(options = {}) {
|
|
82
|
+
const env = options.env ?? process.env;
|
|
83
|
+
const ttlDays = options.ttlDays === undefined
|
|
84
|
+
? parseExternalTemplateCacheTtlDays(env[EXTERNAL_TEMPLATE_CACHE_TTL_DAYS_ENV])
|
|
85
|
+
: parseExternalTemplateCacheTtlDays(options.ttlDays);
|
|
86
|
+
if (ttlDays === null) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const ttlMs = ttlDays * MILLISECONDS_PER_DAY;
|
|
90
|
+
return Number.isFinite(ttlMs) ? ttlMs : null;
|
|
91
|
+
}
|
|
92
|
+
function parseExternalTemplateCachePruneIntervalMs(value) {
|
|
93
|
+
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const intervalMs = typeof value === 'number' ? value : Number(value.trim());
|
|
97
|
+
if (!Number.isFinite(intervalMs) || intervalMs <= 0) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
return intervalMs;
|
|
101
|
+
}
|
|
102
|
+
export function resolveExternalTemplateCachePruneIntervalMs(options = {}) {
|
|
103
|
+
if (options.pruneIntervalMs !== undefined) {
|
|
104
|
+
return parseExternalTemplateCachePruneIntervalMs(options.pruneIntervalMs);
|
|
105
|
+
}
|
|
106
|
+
const env = options.env ?? process.env;
|
|
107
|
+
const envValue = env[EXTERNAL_TEMPLATE_CACHE_PRUNE_INTERVAL_MS_ENV];
|
|
108
|
+
if (envValue === undefined) {
|
|
109
|
+
return DEFAULT_CACHE_PRUNE_INTERVAL_MS;
|
|
110
|
+
}
|
|
111
|
+
return parseExternalTemplateCachePruneIntervalMs(envValue);
|
|
112
|
+
}
|
|
113
|
+
export function getExternalTemplateCacheNowMs(now) {
|
|
114
|
+
const nowMs = now instanceof Date
|
|
115
|
+
? now.getTime()
|
|
116
|
+
: typeof now === 'number'
|
|
117
|
+
? now
|
|
118
|
+
: Date.now();
|
|
119
|
+
return Number.isFinite(nowMs) ? nowMs : Date.now();
|
|
120
|
+
}
|
|
121
|
+
function getCurrentUserCacheSegment() {
|
|
122
|
+
if (typeof process.getuid === 'function') {
|
|
123
|
+
return String(process.getuid());
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const safeUsername = os
|
|
127
|
+
.userInfo()
|
|
128
|
+
.username.trim()
|
|
129
|
+
.replace(/[^A-Za-z0-9._-]+/gu, '-');
|
|
130
|
+
return safeUsername.length > 0 ? safeUsername : 'user';
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return 'user';
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -1,26 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Environment variable that disables external template cache reads and writes.
|
|
3
|
-
*
|
|
4
|
-
* Set to `0`, `false`, `no`, or `off` to bypass the cache.
|
|
5
|
-
*/
|
|
6
|
-
export declare const EXTERNAL_TEMPLATE_CACHE_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE";
|
|
7
|
-
/**
|
|
8
|
-
* Environment variable that overrides the external template cache root.
|
|
9
|
-
*/
|
|
10
|
-
export declare const EXTERNAL_TEMPLATE_CACHE_DIR_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR";
|
|
11
|
-
/**
|
|
12
|
-
* Environment variable that enables TTL-based external template cache pruning.
|
|
13
|
-
*
|
|
14
|
-
* Unset, empty, zero, negative, and non-numeric values keep pruning disabled.
|
|
15
|
-
*/
|
|
16
|
-
export declare const EXTERNAL_TEMPLATE_CACHE_TTL_DAYS_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_TTL_DAYS";
|
|
17
|
-
/**
|
|
18
|
-
* Environment variable that overrides how often TTL pruning may scan the cache.
|
|
19
|
-
*
|
|
20
|
-
* Unset values use the default interval. Zero, negative, and non-numeric values
|
|
21
|
-
* disable scan throttling.
|
|
22
|
-
*/
|
|
23
|
-
export declare const EXTERNAL_TEMPLATE_CACHE_PRUNE_INTERVAL_MS_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_PRUNE_INTERVAL_MS";
|
|
1
|
+
export { EXTERNAL_TEMPLATE_CACHE_DIR_ENV, EXTERNAL_TEMPLATE_CACHE_ENV, EXTERNAL_TEMPLATE_CACHE_PRUNE_INTERVAL_MS_ENV, EXTERNAL_TEMPLATE_CACHE_TTL_DAYS_ENV, getExternalTemplateCacheRoot, isExternalTemplateCacheEnabled, } from './template-source-cache-policy.js';
|
|
24
2
|
/**
|
|
25
3
|
* Serializable metadata recorded in the cache marker for diagnostics.
|
|
26
4
|
*/
|
|
@@ -125,27 +103,6 @@ export interface ExternalTemplateCachePruneResult {
|
|
|
125
103
|
*/
|
|
126
104
|
ttlMs: number | null;
|
|
127
105
|
}
|
|
128
|
-
/**
|
|
129
|
-
* Checks whether remote external template source caching is enabled.
|
|
130
|
-
*
|
|
131
|
-
* Caching is enabled by default. Set `WP_TYPIA_EXTERNAL_TEMPLATE_CACHE` to
|
|
132
|
-
* `0`, `false`, `no`, or `off` to force uncached resolution.
|
|
133
|
-
*
|
|
134
|
-
* @param env Environment object to inspect, defaulting to `process.env`.
|
|
135
|
-
* @returns Whether external template source cache reads and writes are enabled.
|
|
136
|
-
*/
|
|
137
|
-
export declare function isExternalTemplateCacheEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
138
|
-
/**
|
|
139
|
-
* Resolves the external template source cache root directory.
|
|
140
|
-
*
|
|
141
|
-
* `WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR` overrides the location. Without an
|
|
142
|
-
* override, wp-typia uses a per-user `wp-typia-template-source-cache-*`
|
|
143
|
-
* directory inside the operating system temp directory.
|
|
144
|
-
*
|
|
145
|
-
* @param env Environment object to inspect, defaulting to `process.env`.
|
|
146
|
-
* @returns Absolute cache root directory path.
|
|
147
|
-
*/
|
|
148
|
-
export declare function getExternalTemplateCacheRoot(env?: NodeJS.ProcessEnv): string;
|
|
149
106
|
/**
|
|
150
107
|
* Creates a deterministic cache key from source identity and integrity parts.
|
|
151
108
|
*
|
|
@@ -187,4 +144,3 @@ export declare function findReusableExternalTemplateSourceCache(descriptor: Exte
|
|
|
187
144
|
* @returns Cache resolution details, or `null` when caching is disabled.
|
|
188
145
|
*/
|
|
189
146
|
export declare function resolveExternalTemplateSourceCache(descriptor: ExternalTemplateCacheDescriptor, populateSourceDir: (sourceDir: string) => Promise<void>): Promise<ExternalTemplateCacheResolution | null>;
|
|
190
|
-
export {};
|
|
@@ -1,31 +1,9 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
import fs from 'node:fs';
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
3
2
|
import { promises as fsp } from 'node:fs';
|
|
4
|
-
import os from 'node:os';
|
|
5
3
|
import path from 'node:path';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* Set to `0`, `false`, `no`, or `off` to bypass the cache.
|
|
10
|
-
*/
|
|
11
|
-
export const EXTERNAL_TEMPLATE_CACHE_ENV = 'WP_TYPIA_EXTERNAL_TEMPLATE_CACHE';
|
|
12
|
-
/**
|
|
13
|
-
* Environment variable that overrides the external template cache root.
|
|
14
|
-
*/
|
|
15
|
-
export const EXTERNAL_TEMPLATE_CACHE_DIR_ENV = 'WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR';
|
|
16
|
-
/**
|
|
17
|
-
* Environment variable that enables TTL-based external template cache pruning.
|
|
18
|
-
*
|
|
19
|
-
* Unset, empty, zero, negative, and non-numeric values keep pruning disabled.
|
|
20
|
-
*/
|
|
21
|
-
export const EXTERNAL_TEMPLATE_CACHE_TTL_DAYS_ENV = 'WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_TTL_DAYS';
|
|
22
|
-
/**
|
|
23
|
-
* Environment variable that overrides how often TTL pruning may scan the cache.
|
|
24
|
-
*
|
|
25
|
-
* Unset values use the default interval. Zero, negative, and non-numeric values
|
|
26
|
-
* disable scan throttling.
|
|
27
|
-
*/
|
|
28
|
-
export const EXTERNAL_TEMPLATE_CACHE_PRUNE_INTERVAL_MS_ENV = 'WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_PRUNE_INTERVAL_MS';
|
|
4
|
+
import { getNodeErrorCode, pathExists } from './fs-async.js';
|
|
5
|
+
import { getExternalTemplateCacheNowMs, getExternalTemplateCacheRoot, isExternalTemplateCacheEnabled, resolveExternalTemplateCachePruneIntervalMs, resolveExternalTemplateCacheTtlMs, } from './template-source-cache-policy.js';
|
|
6
|
+
export { EXTERNAL_TEMPLATE_CACHE_DIR_ENV, EXTERNAL_TEMPLATE_CACHE_ENV, EXTERNAL_TEMPLATE_CACHE_PRUNE_INTERVAL_MS_ENV, EXTERNAL_TEMPLATE_CACHE_TTL_DAYS_ENV, getExternalTemplateCacheRoot, isExternalTemplateCacheEnabled, } from './template-source-cache-policy.js';
|
|
29
7
|
/**
|
|
30
8
|
* Marker file written after a cache entry is fully populated.
|
|
31
9
|
*/
|
|
@@ -34,14 +12,6 @@ const CACHE_MARKER_FILE = 'wp-typia-template-cache.json';
|
|
|
34
12
|
* Marker file written after a full TTL prune scan completes.
|
|
35
13
|
*/
|
|
36
14
|
const CACHE_PRUNE_MARKER_FILE = 'wp-typia-template-cache-prune.json';
|
|
37
|
-
/**
|
|
38
|
-
* Milliseconds in one TTL day.
|
|
39
|
-
*/
|
|
40
|
-
const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
41
|
-
/**
|
|
42
|
-
* Default minimum interval between full external template cache prune scans.
|
|
43
|
-
*/
|
|
44
|
-
const DEFAULT_CACHE_PRUNE_INTERVAL_MS = 60 * 60 * 1000;
|
|
45
15
|
/**
|
|
46
16
|
* Private directory mode used for cache roots and entries on POSIX platforms.
|
|
47
17
|
*/
|
|
@@ -50,10 +20,6 @@ const PRIVATE_CACHE_DIRECTORY_MODE = 0o700;
|
|
|
50
20
|
* Marker value used when URL-like metadata cannot be safely normalized.
|
|
51
21
|
*/
|
|
52
22
|
const REDACTED_CACHE_METADATA_VALUE = '[redacted]';
|
|
53
|
-
/**
|
|
54
|
-
* Normalized environment values that disable the cache.
|
|
55
|
-
*/
|
|
56
|
-
const DISABLED_CACHE_VALUES = new Set(['0', 'false', 'no', 'off']);
|
|
57
23
|
/**
|
|
58
24
|
* Filesystem errors that mean another writer published the same cache entry.
|
|
59
25
|
*/
|
|
@@ -80,80 +46,10 @@ const SAFE_CACHE_NAMESPACE_SEGMENT = /^[A-Za-z0-9_.-]+$/u;
|
|
|
80
46
|
* Cache entries are deterministic SHA-256 digest directory names.
|
|
81
47
|
*/
|
|
82
48
|
const SAFE_CACHE_ENTRY_SEGMENT = /^[a-f0-9]{64}$/u;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
* `0`, `false`, `no`, or `off` to force uncached resolution.
|
|
88
|
-
*
|
|
89
|
-
* @param env Environment object to inspect, defaulting to `process.env`.
|
|
90
|
-
* @returns Whether external template source cache reads and writes are enabled.
|
|
91
|
-
*/
|
|
92
|
-
export function isExternalTemplateCacheEnabled(env = process.env) {
|
|
93
|
-
const rawValue = env[EXTERNAL_TEMPLATE_CACHE_ENV];
|
|
94
|
-
if (rawValue === undefined) {
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
return !DISABLED_CACHE_VALUES.has(rawValue.trim().toLowerCase());
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Resolves the external template source cache root directory.
|
|
101
|
-
*
|
|
102
|
-
* `WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR` overrides the location. Without an
|
|
103
|
-
* override, wp-typia uses a per-user `wp-typia-template-source-cache-*`
|
|
104
|
-
* directory inside the operating system temp directory.
|
|
105
|
-
*
|
|
106
|
-
* @param env Environment object to inspect, defaulting to `process.env`.
|
|
107
|
-
* @returns Absolute cache root directory path.
|
|
108
|
-
*/
|
|
109
|
-
export function getExternalTemplateCacheRoot(env = process.env) {
|
|
110
|
-
const configuredCacheDir = env[EXTERNAL_TEMPLATE_CACHE_DIR_ENV]?.trim();
|
|
111
|
-
if (configuredCacheDir) {
|
|
112
|
-
return path.resolve(configuredCacheDir);
|
|
113
|
-
}
|
|
114
|
-
return path.join(os.tmpdir(), `wp-typia-template-source-cache-${getCurrentUserCacheSegment()}`);
|
|
115
|
-
}
|
|
116
|
-
function parseExternalTemplateCacheTtlDays(value) {
|
|
117
|
-
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
118
|
-
return null;
|
|
119
|
-
}
|
|
120
|
-
const ttlDays = typeof value === 'number' ? value : Number(value.trim());
|
|
121
|
-
if (!Number.isFinite(ttlDays) || ttlDays <= 0) {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
return ttlDays;
|
|
125
|
-
}
|
|
126
|
-
function resolveExternalTemplateCacheTtlMs(options = {}) {
|
|
127
|
-
const env = options.env ?? process.env;
|
|
128
|
-
const ttlDays = options.ttlDays === undefined
|
|
129
|
-
? parseExternalTemplateCacheTtlDays(env[EXTERNAL_TEMPLATE_CACHE_TTL_DAYS_ENV])
|
|
130
|
-
: parseExternalTemplateCacheTtlDays(options.ttlDays);
|
|
131
|
-
if (ttlDays === null) {
|
|
132
|
-
return null;
|
|
133
|
-
}
|
|
134
|
-
const ttlMs = ttlDays * MILLISECONDS_PER_DAY;
|
|
135
|
-
return Number.isFinite(ttlMs) ? ttlMs : null;
|
|
136
|
-
}
|
|
137
|
-
function parseExternalTemplateCachePruneIntervalMs(value) {
|
|
138
|
-
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
const intervalMs = typeof value === 'number' ? value : Number(value.trim());
|
|
142
|
-
if (!Number.isFinite(intervalMs) || intervalMs <= 0) {
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
return intervalMs;
|
|
146
|
-
}
|
|
147
|
-
function resolveExternalTemplateCachePruneIntervalMs(options = {}) {
|
|
148
|
-
if (options.pruneIntervalMs !== undefined) {
|
|
149
|
-
return parseExternalTemplateCachePruneIntervalMs(options.pruneIntervalMs);
|
|
150
|
-
}
|
|
151
|
-
const env = options.env ?? process.env;
|
|
152
|
-
const envValue = env[EXTERNAL_TEMPLATE_CACHE_PRUNE_INTERVAL_MS_ENV];
|
|
153
|
-
if (envValue === undefined) {
|
|
154
|
-
return DEFAULT_CACHE_PRUNE_INTERVAL_MS;
|
|
155
|
-
}
|
|
156
|
-
return parseExternalTemplateCachePruneIntervalMs(envValue);
|
|
49
|
+
function createTemporaryCacheEntryDirName(cacheKey) {
|
|
50
|
+
// Crypto randomness keeps concurrent cache populators from colliding on the
|
|
51
|
+
// staging directory before the final atomic rename publishes the cache entry.
|
|
52
|
+
return `.tmp-${cacheKey}-${process.pid}-${Date.now()}-${randomUUID()}`;
|
|
157
53
|
}
|
|
158
54
|
/**
|
|
159
55
|
* Creates a deterministic cache key from source identity and integrity parts.
|
|
@@ -166,15 +62,6 @@ export function createExternalTemplateCacheKey(keyParts) {
|
|
|
166
62
|
.update(JSON.stringify(keyParts))
|
|
167
63
|
.digest('hex');
|
|
168
64
|
}
|
|
169
|
-
async function pathExists(filePath) {
|
|
170
|
-
try {
|
|
171
|
-
await fsp.access(filePath, fs.constants.F_OK);
|
|
172
|
-
return true;
|
|
173
|
-
}
|
|
174
|
-
catch {
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
65
|
async function isDirectoryPath(directory) {
|
|
179
66
|
try {
|
|
180
67
|
const stats = await fsp.lstat(directory);
|
|
@@ -184,11 +71,6 @@ async function isDirectoryPath(directory) {
|
|
|
184
71
|
return false;
|
|
185
72
|
}
|
|
186
73
|
}
|
|
187
|
-
function getNodeErrorCode(error) {
|
|
188
|
-
return typeof error === 'object' && error !== null && 'code' in error
|
|
189
|
-
? String(error.code)
|
|
190
|
-
: '';
|
|
191
|
-
}
|
|
192
74
|
async function removeTemporaryCacheEntry(entryDir) {
|
|
193
75
|
try {
|
|
194
76
|
await fsp.rm(entryDir, { force: true, recursive: true });
|
|
@@ -197,21 +79,6 @@ async function removeTemporaryCacheEntry(entryDir) {
|
|
|
197
79
|
// Cache cleanup is best-effort; the caller can still continue uncached.
|
|
198
80
|
}
|
|
199
81
|
}
|
|
200
|
-
function getCurrentUserCacheSegment() {
|
|
201
|
-
if (typeof process.getuid === 'function') {
|
|
202
|
-
return String(process.getuid());
|
|
203
|
-
}
|
|
204
|
-
try {
|
|
205
|
-
const safeUsername = os
|
|
206
|
-
.userInfo()
|
|
207
|
-
.username.trim()
|
|
208
|
-
.replace(/[^A-Za-z0-9._-]+/gu, '-');
|
|
209
|
-
return safeUsername.length > 0 ? safeUsername : 'user';
|
|
210
|
-
}
|
|
211
|
-
catch {
|
|
212
|
-
return 'user';
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
82
|
function getCurrentUid() {
|
|
216
83
|
return typeof process.getuid === 'function' ? process.getuid() : null;
|
|
217
84
|
}
|
|
@@ -360,14 +227,6 @@ async function readCacheEntryMarker(markerPath) {
|
|
|
360
227
|
function cacheMetadataMatches(actual, expected) {
|
|
361
228
|
return Object.entries(expected).every(([key, value]) => actual[key] === value);
|
|
362
229
|
}
|
|
363
|
-
function getExternalTemplateCacheNowMs(now) {
|
|
364
|
-
const nowMs = now instanceof Date
|
|
365
|
-
? now.getTime()
|
|
366
|
-
: typeof now === 'number'
|
|
367
|
-
? now
|
|
368
|
-
: Date.now();
|
|
369
|
-
return Number.isFinite(nowMs) ? nowMs : Date.now();
|
|
370
|
-
}
|
|
371
230
|
function isCacheEntryFreshForTtl(createdAtMs, nowMs, ttlMs) {
|
|
372
231
|
return ttlMs === null || createdAtMs >= nowMs - ttlMs;
|
|
373
232
|
}
|
|
@@ -673,9 +532,7 @@ export async function resolveExternalTemplateSourceCache(descriptor, populateSou
|
|
|
673
532
|
if (existingMarker) {
|
|
674
533
|
await removeCacheEntryWithinRoot(cacheRoot, entryDir);
|
|
675
534
|
}
|
|
676
|
-
const temporaryEntryDir = path.join(namespaceDir,
|
|
677
|
-
.toString(16)
|
|
678
|
-
.slice(2)}`);
|
|
535
|
+
const temporaryEntryDir = path.join(namespaceDir, createTemporaryCacheEntryDirName(cacheKey));
|
|
679
536
|
const temporarySourceDir = path.join(temporaryEntryDir, 'source');
|
|
680
537
|
let populateFailed = false;
|
|
681
538
|
try {
|
|
@@ -7,6 +7,9 @@ export declare const EXTERNAL_TEMPLATE_TRUST_WARNING = "External template config
|
|
|
7
7
|
/**
|
|
8
8
|
* Search a source directory for the first supported external template entry.
|
|
9
9
|
*
|
|
10
|
+
* @deprecated Use `findExternalTemplateEntry()` from async template-source
|
|
11
|
+
* paths. This synchronous helper remains only for compatibility callers.
|
|
12
|
+
*
|
|
10
13
|
* @param sourceDir Directory that may contain an external template config entry.
|
|
11
14
|
* @returns The first matching entry path, or null when no supported entry exists.
|
|
12
15
|
*/
|
|
@@ -33,6 +33,9 @@ function resolveSourceSubpath(sourceDir, relativePath) {
|
|
|
33
33
|
/**
|
|
34
34
|
* Search a source directory for the first supported external template entry.
|
|
35
35
|
*
|
|
36
|
+
* @deprecated Use `findExternalTemplateEntry()` from async template-source
|
|
37
|
+
* paths. This synchronous helper remains only for compatibility callers.
|
|
38
|
+
*
|
|
36
39
|
* @param sourceDir Directory that may contain an external template config entry.
|
|
37
40
|
* @returns The first matching entry path, or null when no supported entry exists.
|
|
38
41
|
*/
|
|
@@ -205,11 +208,11 @@ export async function renderCreateBlockExternalTemplate(sourceDir, context, requ
|
|
|
205
208
|
const view = await buildExternalTemplateView(context, config, selectedVariant, variantConfig);
|
|
206
209
|
const blockTemplateDir = resolveSourceSubpath(sourceDir, templatePath);
|
|
207
210
|
await copyRenderedDirectory(blockTemplateDir, blockDir, view, {
|
|
208
|
-
filter: (sourcePath, _destinationPath, entry) => {
|
|
211
|
+
filter: async (sourcePath, _destinationPath, entry) => {
|
|
209
212
|
const mustacheVariantPath = path.join(path.dirname(sourcePath), `${entry.name}.mustache`);
|
|
210
213
|
return !(entry.isFile() &&
|
|
211
214
|
(entry.name === 'package.json' || entry.name === 'README.md') &&
|
|
212
|
-
|
|
215
|
+
(await pathExists(mustacheVariantPath)));
|
|
213
216
|
},
|
|
214
217
|
});
|
|
215
218
|
const assetsPath = typeof variantConfig.assetsPath === 'string'
|
|
@@ -2,6 +2,9 @@ import type { ResolvedTemplateSource, SeedSource, TemplateVariableContext } from
|
|
|
2
2
|
/**
|
|
3
3
|
* Read a remote block source and return its default block category.
|
|
4
4
|
*
|
|
5
|
+
* @deprecated Use `getDefaultCategoryAsync()` from async template-source paths.
|
|
6
|
+
* This synchronous helper remains only for compatibility callers.
|
|
7
|
+
*
|
|
5
8
|
* @param sourceDir Block source directory that may contain a block.json file.
|
|
6
9
|
* @returns The declared block category, or "widgets" when detection fails.
|
|
7
10
|
*/
|
|
@@ -16,6 +19,9 @@ export declare function getDefaultCategoryAsync(sourceDir: string): Promise<stri
|
|
|
16
19
|
/**
|
|
17
20
|
* Read `wpTypia.projectType` from a rendered or source template package
|
|
18
21
|
* manifest and return it when present.
|
|
22
|
+
*
|
|
23
|
+
* @deprecated Use `getTemplateProjectTypeAsync()` from async template-source
|
|
24
|
+
* paths. This synchronous helper remains only for compatibility callers.
|
|
19
25
|
*/
|
|
20
26
|
export declare function getTemplateProjectType(sourceDir: string): string | null;
|
|
21
27
|
/**
|
|
@@ -59,6 +59,9 @@ async function readRemoteBlockJsonAsync(blockDir) {
|
|
|
59
59
|
/**
|
|
60
60
|
* Read a remote block source and return its default block category.
|
|
61
61
|
*
|
|
62
|
+
* @deprecated Use `getDefaultCategoryAsync()` from async template-source paths.
|
|
63
|
+
* This synchronous helper remains only for compatibility callers.
|
|
64
|
+
*
|
|
62
65
|
* @param sourceDir Block source directory that may contain a block.json file.
|
|
63
66
|
* @returns The declared block category, or "widgets" when detection fails.
|
|
64
67
|
*/
|
|
@@ -139,6 +142,9 @@ async function readTemplatePackageJsonAsync(sourceDir) {
|
|
|
139
142
|
/**
|
|
140
143
|
* Read `wpTypia.projectType` from a rendered or source template package
|
|
141
144
|
* manifest and return it when present.
|
|
145
|
+
*
|
|
146
|
+
* @deprecated Use `getTemplateProjectTypeAsync()` from async template-source
|
|
147
|
+
* paths. This synchronous helper remains only for compatibility callers.
|
|
142
148
|
*/
|
|
143
149
|
export function getTemplateProjectType(sourceDir) {
|
|
144
150
|
const packageJsonEntry = readTemplatePackageJson(sourceDir);
|
|
@@ -185,11 +191,11 @@ export async function normalizeWpTypiaTemplateSeed(seed) {
|
|
|
185
191
|
const normalizedDir = path.join(tempRoot, 'template');
|
|
186
192
|
try {
|
|
187
193
|
await copyRawDirectory(seed.blockDir, normalizedDir, {
|
|
188
|
-
filter: (sourcePath, _targetPath, entry) => {
|
|
194
|
+
filter: async (sourcePath, _targetPath, entry) => {
|
|
189
195
|
const mustacheVariantPath = path.join(path.dirname(sourcePath), `${entry.name}.mustache`);
|
|
190
196
|
return !(entry.isFile() &&
|
|
191
197
|
(entry.name === 'package.json' || entry.name === 'README.md') &&
|
|
192
|
-
|
|
198
|
+
(await pathExists(mustacheVariantPath)));
|
|
193
199
|
},
|
|
194
200
|
});
|
|
195
201
|
if (seed.assetsDir && (await pathExists(seed.assetsDir))) {
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import type { RemoteTemplateLocator, SeedSource } from './template-source-contracts.js';
|
|
2
|
+
/**
|
|
3
|
+
* Synchronously identify the bundled workspace template seed.
|
|
4
|
+
*
|
|
5
|
+
* This remains sync-only for compatibility callers. Async template resolution
|
|
6
|
+
* paths should use `isOfficialWorkspaceTemplateSeedAsync()`.
|
|
7
|
+
*/
|
|
2
8
|
export declare function isOfficialWorkspaceTemplateSeed(seed: SeedSource): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Asynchronously identify the bundled workspace template seed.
|
|
11
|
+
*
|
|
12
|
+
* @param seed Seed source to inspect.
|
|
13
|
+
* @returns Whether the seed resolves to the official workspace template package.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isOfficialWorkspaceTemplateSeedAsync(seed: SeedSource): Promise<boolean>;
|
|
3
16
|
export declare function assertNoSymlinks(sourceDir: string): Promise<void>;
|
|
4
17
|
/**
|
|
5
18
|
* Resolves a template locator into a local seed source directory.
|
|
@@ -8,6 +8,7 @@ import { x as extractTarball } from 'tar';
|
|
|
8
8
|
import { createExternalTemplateTimeoutError, fetchWithExternalTemplateTimeout, getExternalTemplateMetadataMaxBytes, getExternalTemplateTarballMaxBytes, getExternalTemplateTimeoutMs, readBufferResponseWithLimit, readJsonResponseWithLimit, } from './external-template-guards.js';
|
|
9
9
|
import { findReusableExternalTemplateSourceCache, isExternalTemplateCacheEnabled, resolveExternalTemplateSourceCache, } from './template-source-cache.js';
|
|
10
10
|
import { CLI_DIAGNOSTIC_CODES, createCliDiagnosticCodeError, } from './cli-diagnostics.js';
|
|
11
|
+
import { pathExists } from './fs-async.js';
|
|
11
12
|
import { OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE, OFFICIAL_WORKSPACE_TEMPLATE_ALIAS, PROJECT_TOOLS_PACKAGE_ROOT, TEMPLATE_IDS, } from './template-registry.js';
|
|
12
13
|
import { isPlainObject } from './object-utils.js';
|
|
13
14
|
import { createManagedTempRoot } from './temp-roots.js';
|
|
@@ -184,7 +185,9 @@ async function fetchNpmTemplateSource(locator) {
|
|
|
184
185
|
* Resolve a locally installed npm template package from the caller workspace.
|
|
185
186
|
*
|
|
186
187
|
* Bare package ids are preferred here so monorepo and offline workflows can
|
|
187
|
-
* use an already-installed template without forcing a registry fetch.
|
|
188
|
+
* use an already-installed template without forcing a registry fetch. This
|
|
189
|
+
* path intentionally keeps Node's synchronous `require.resolve` semantics
|
|
190
|
+
* because the module resolver itself has no async equivalent.
|
|
188
191
|
*/
|
|
189
192
|
function resolveInstalledNpmTemplateSource(locator, cwd) {
|
|
190
193
|
if (locator.rawSpec !== '' && locator.rawSpec !== '*') {
|
|
@@ -244,6 +247,12 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
|
|
|
244
247
|
throw error;
|
|
245
248
|
}
|
|
246
249
|
}
|
|
250
|
+
/**
|
|
251
|
+
* Synchronously identify the bundled workspace template seed.
|
|
252
|
+
*
|
|
253
|
+
* This remains sync-only for compatibility callers. Async template resolution
|
|
254
|
+
* paths should use `isOfficialWorkspaceTemplateSeedAsync()`.
|
|
255
|
+
*/
|
|
247
256
|
export function isOfficialWorkspaceTemplateSeed(seed) {
|
|
248
257
|
const packageJsonPath = path.join(seed.rootDir, 'package.json');
|
|
249
258
|
if (!fs.existsSync(packageJsonPath)) {
|
|
@@ -257,6 +266,25 @@ export function isOfficialWorkspaceTemplateSeed(seed) {
|
|
|
257
266
|
return false;
|
|
258
267
|
}
|
|
259
268
|
}
|
|
269
|
+
/**
|
|
270
|
+
* Asynchronously identify the bundled workspace template seed.
|
|
271
|
+
*
|
|
272
|
+
* @param seed Seed source to inspect.
|
|
273
|
+
* @returns Whether the seed resolves to the official workspace template package.
|
|
274
|
+
*/
|
|
275
|
+
export async function isOfficialWorkspaceTemplateSeedAsync(seed) {
|
|
276
|
+
const packageJsonPath = path.join(seed.rootDir, 'package.json');
|
|
277
|
+
if (!(await pathExists(packageJsonPath))) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
const packageJson = JSON.parse(await fsp.readFile(packageJsonPath, 'utf8'));
|
|
282
|
+
return packageJson.name === OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE;
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
260
288
|
export async function assertNoSymlinks(sourceDir) {
|
|
261
289
|
const stats = await fsp.lstat(sourceDir);
|
|
262
290
|
if (stats.isSymbolicLink()) {
|
|
@@ -300,13 +328,13 @@ function runGitTemplateCommand(args, label, options = {}) {
|
|
|
300
328
|
function getGitHubTemplateRepositoryUrl(locator) {
|
|
301
329
|
return `https://github.com/${locator.owner}/${locator.repo}.git`;
|
|
302
330
|
}
|
|
303
|
-
function resolveGitHubTemplateDirectory(checkoutDir, locator) {
|
|
331
|
+
async function resolveGitHubTemplateDirectory(checkoutDir, locator) {
|
|
304
332
|
const sourceDir = path.resolve(checkoutDir, locator.sourcePath);
|
|
305
333
|
const relativeSourceDir = path.relative(checkoutDir, sourceDir);
|
|
306
334
|
if (relativeSourceDir.startsWith('..') || path.isAbsolute(relativeSourceDir)) {
|
|
307
335
|
throw new Error('GitHub template path must stay within the cloned repository.');
|
|
308
336
|
}
|
|
309
|
-
if (!
|
|
337
|
+
if (!(await pathExists(sourceDir))) {
|
|
310
338
|
throw new Error(`GitHub template path does not exist: ${locator.sourcePath}`);
|
|
311
339
|
}
|
|
312
340
|
return sourceDir;
|
|
@@ -438,7 +466,7 @@ async function reuseGitHubTemplateCacheByMetadata(locator) {
|
|
|
438
466
|
if (!cachedSource) {
|
|
439
467
|
return null;
|
|
440
468
|
}
|
|
441
|
-
const sourceDir = resolveGitHubTemplateDirectory(cachedSource.sourceDir, locator);
|
|
469
|
+
const sourceDir = await resolveGitHubTemplateDirectory(cachedSource.sourceDir, locator);
|
|
442
470
|
await assertNoSymlinks(sourceDir);
|
|
443
471
|
return {
|
|
444
472
|
blockDir: sourceDir,
|
|
@@ -482,12 +510,12 @@ async function resolveGitHubTemplateSource(locator) {
|
|
|
482
510
|
namespace: 'github',
|
|
483
511
|
}, async (checkoutDir) => {
|
|
484
512
|
cloneGitHubTemplateSource(locator, checkoutDir);
|
|
485
|
-
const sourceDir = resolveGitHubTemplateDirectory(checkoutDir, locator);
|
|
513
|
+
const sourceDir = await resolveGitHubTemplateDirectory(checkoutDir, locator);
|
|
486
514
|
await assertNoSymlinks(sourceDir);
|
|
487
515
|
pinGitHubTemplateCacheRevision(locator, checkoutDir, resolvedCacheRevision);
|
|
488
516
|
});
|
|
489
517
|
if (cachedSource) {
|
|
490
|
-
const sourceDir = resolveGitHubTemplateDirectory(cachedSource.sourceDir, locator);
|
|
518
|
+
const sourceDir = await resolveGitHubTemplateDirectory(cachedSource.sourceDir, locator);
|
|
491
519
|
await assertNoSymlinks(sourceDir);
|
|
492
520
|
return {
|
|
493
521
|
blockDir: sourceDir,
|
|
@@ -506,7 +534,7 @@ async function resolveGitHubTemplateSource(locator) {
|
|
|
506
534
|
const checkoutDir = path.join(remoteRoot, 'source');
|
|
507
535
|
try {
|
|
508
536
|
cloneGitHubTemplateSource(locator, checkoutDir);
|
|
509
|
-
const sourceDir = resolveGitHubTemplateDirectory(checkoutDir, locator);
|
|
537
|
+
const sourceDir = await resolveGitHubTemplateDirectory(checkoutDir, locator);
|
|
510
538
|
await assertNoSymlinks(sourceDir);
|
|
511
539
|
return {
|
|
512
540
|
blockDir: sourceDir,
|
|
@@ -530,7 +558,7 @@ async function resolveGitHubTemplateSource(locator) {
|
|
|
530
558
|
export async function resolveTemplateSeed(locator, cwd) {
|
|
531
559
|
if (locator.kind === 'path') {
|
|
532
560
|
const sourceDir = path.resolve(cwd, locator.templatePath);
|
|
533
|
-
if (!
|
|
561
|
+
if (!(await pathExists(sourceDir))) {
|
|
534
562
|
throw new Error(`Template path does not exist: ${sourceDir}`);
|
|
535
563
|
}
|
|
536
564
|
await assertNoSymlinks(sourceDir);
|
|
@@ -2,7 +2,7 @@ import { OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE, isBuiltInTemplateId, } from './tem
|
|
|
2
2
|
import { resolveBuiltInTemplateSource } from './template-builtins.js';
|
|
3
3
|
import { parseTemplateLocator, } from './template-source-locators.js';
|
|
4
4
|
import { detectTemplateSourceFormat, getTemplateProjectTypeAsync, getDefaultCategoryAsync, getTemplateVariableContext, normalizeCreateBlockSubset, normalizeWpTypiaTemplateSeed, renderCreateBlockExternalTemplate, } from './template-source-normalization.js';
|
|
5
|
-
import {
|
|
5
|
+
import { isOfficialWorkspaceTemplateSeedAsync, resolveTemplateSeed, } from './template-source-seeds.js';
|
|
6
6
|
import { assertBuiltInTemplateVariantAllowed, } from './cli-validation.js';
|
|
7
7
|
import { getScaffoldTemplateVariableGroups } from './scaffold-template-variable-groups.js';
|
|
8
8
|
export { parseGitHubTemplateLocator, parseNpmTemplateLocator, parseTemplateLocator, } from './template-source-locators.js';
|
|
@@ -27,7 +27,7 @@ export async function resolveTemplateSource(templateId, cwd, variables, variant)
|
|
|
27
27
|
const context = getTemplateVariableContext(variables);
|
|
28
28
|
const seed = await resolveTemplateSeed(locator, cwd);
|
|
29
29
|
const isOfficialWorkspaceTemplate = templateId === OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE ||
|
|
30
|
-
|
|
30
|
+
(await isOfficialWorkspaceTemplateSeedAsync(seed));
|
|
31
31
|
let normalizedSeed = null;
|
|
32
32
|
try {
|
|
33
33
|
const format = await detectTemplateSourceFormat(seed.blockDir);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
/**
|
|
3
|
+
* Extract the literal text for TypeScript property names this runtime supports.
|
|
4
|
+
*
|
|
5
|
+
* Computed property names are intentionally not resolved because their runtime
|
|
6
|
+
* values are not statically knowable from the syntax node alone.
|
|
7
|
+
*
|
|
8
|
+
* @param name TypeScript property name node.
|
|
9
|
+
* @returns Identifier, string-literal, or numeric-literal text; otherwise `null`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getPropertyNameText(name: ts.PropertyName): string | null;
|