@timeax/scaffold 0.0.2 → 0.0.3
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/cli.cjs +55 -14
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +55 -14
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +51 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -1
- package/dist/index.d.ts +68 -1
- package/dist/index.mjs +49 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/readme.md +150 -51
- package/src/core/config-loader.ts +4 -3
- package/src/core/init-scaffold.ts +8 -3
- package/src/core/structure-txt.ts +88 -15
- package/src/index.ts +3 -2
- package/src/schema/config.ts +10 -1
- package/src/schema/index.ts +1 -0
package/dist/cli.mjs
CHANGED
|
@@ -10,6 +10,9 @@ import { transform } from 'esbuild';
|
|
|
10
10
|
import { minimatch } from 'minimatch';
|
|
11
11
|
import chokidar from 'chokidar';
|
|
12
12
|
|
|
13
|
+
// src/schema/index.ts
|
|
14
|
+
var SCAFFOLD_ROOT_DIR = ".scaffold";
|
|
15
|
+
|
|
13
16
|
// src/util/logger.ts
|
|
14
17
|
var supportsColor = typeof process !== "undefined" && process.stdout && process.stdout.isTTY && process.env.NO_COLOR !== "1";
|
|
15
18
|
function wrap(code) {
|
|
@@ -133,14 +136,14 @@ function toProjectRelativePath(projectRoot, absolutePath) {
|
|
|
133
136
|
var logger = defaultLogger.child("[config]");
|
|
134
137
|
async function loadScaffoldConfig(cwd, options = {}) {
|
|
135
138
|
const absCwd = path2.resolve(cwd);
|
|
136
|
-
const initialScaffoldDir = options.scaffoldDir ? path2.resolve(absCwd, options.scaffoldDir) : path2.join(absCwd,
|
|
139
|
+
const initialScaffoldDir = options.scaffoldDir ? path2.resolve(absCwd, options.scaffoldDir) : path2.join(absCwd, SCAFFOLD_ROOT_DIR);
|
|
137
140
|
const configPath = options.configPath ?? resolveConfigPath(initialScaffoldDir);
|
|
138
141
|
const config = await importConfig(configPath);
|
|
139
142
|
let configRoot = absCwd;
|
|
140
143
|
if (config.root) {
|
|
141
144
|
configRoot = path2.resolve(absCwd, config.root);
|
|
142
145
|
}
|
|
143
|
-
const scaffoldDir = options.scaffoldDir ? path2.resolve(absCwd, options.scaffoldDir) : path2.join(configRoot,
|
|
146
|
+
const scaffoldDir = options.scaffoldDir ? path2.resolve(absCwd, options.scaffoldDir) : path2.join(configRoot, SCAFFOLD_ROOT_DIR);
|
|
144
147
|
const baseRoot = config.base ? path2.resolve(configRoot, config.base) : configRoot;
|
|
145
148
|
logger.debug(
|
|
146
149
|
`Loaded config: configRoot=${configRoot}, baseRoot=${baseRoot}, scaffoldDir=${scaffoldDir}`
|
|
@@ -205,14 +208,50 @@ async function importTsConfig(configPath) {
|
|
|
205
208
|
}
|
|
206
209
|
|
|
207
210
|
// src/core/structure-txt.ts
|
|
211
|
+
function stripInlineComment(content) {
|
|
212
|
+
let cutIndex = -1;
|
|
213
|
+
const len = content.length;
|
|
214
|
+
for (let i = 0; i < len; i++) {
|
|
215
|
+
const ch = content[i];
|
|
216
|
+
const prev = i > 0 ? content[i - 1] : "";
|
|
217
|
+
if (ch === "#") {
|
|
218
|
+
if (i === 0) continue;
|
|
219
|
+
if (prev === " " || prev === " ") {
|
|
220
|
+
cutIndex = i;
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (ch === "/" && i + 1 < len && content[i + 1] === "/" && (prev === " " || prev === " ")) {
|
|
225
|
+
cutIndex = i;
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (cutIndex === -1) {
|
|
230
|
+
return content.trimEnd();
|
|
231
|
+
}
|
|
232
|
+
return content.slice(0, cutIndex).trimEnd();
|
|
233
|
+
}
|
|
208
234
|
function parseLine(line, lineNo) {
|
|
209
|
-
const match = line.match(/^(\s*)(
|
|
235
|
+
const match = line.match(/^(\s*)(.*)$/);
|
|
210
236
|
if (!match) return null;
|
|
211
237
|
const indentSpaces = match[1].length;
|
|
212
|
-
|
|
213
|
-
if (!rest
|
|
214
|
-
const
|
|
238
|
+
let rest = match[2];
|
|
239
|
+
if (!rest.trim()) return null;
|
|
240
|
+
const trimmedRest = rest.trimStart();
|
|
241
|
+
if (trimmedRest.startsWith("#") || trimmedRest.startsWith("//")) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
const stripped = stripInlineComment(rest);
|
|
245
|
+
const trimmed = stripped.trim();
|
|
246
|
+
if (!trimmed) return null;
|
|
247
|
+
const parts = trimmed.split(/\s+/);
|
|
248
|
+
if (!parts.length) return null;
|
|
215
249
|
const pathToken = parts[0];
|
|
250
|
+
if (pathToken.includes(":")) {
|
|
251
|
+
throw new Error(
|
|
252
|
+
`structure.txt: ":" is reserved for annotations (@stub:, @include:, etc). Invalid path "${pathToken}" on line ${lineNo}.`
|
|
253
|
+
);
|
|
254
|
+
}
|
|
216
255
|
let stub;
|
|
217
256
|
const include = [];
|
|
218
257
|
const exclude = [];
|
|
@@ -244,7 +283,7 @@ function parseLine(line, lineNo) {
|
|
|
244
283
|
exclude: exclude.length ? exclude : void 0
|
|
245
284
|
};
|
|
246
285
|
}
|
|
247
|
-
function parseStructureText(text) {
|
|
286
|
+
function parseStructureText(text, indentStep = 2) {
|
|
248
287
|
const lines = text.split(/\r?\n/);
|
|
249
288
|
const parsed = [];
|
|
250
289
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -254,15 +293,14 @@ function parseStructureText(text) {
|
|
|
254
293
|
}
|
|
255
294
|
const rootEntries = [];
|
|
256
295
|
const stack = [];
|
|
257
|
-
const INDENT_STEP = 2;
|
|
258
296
|
for (const p of parsed) {
|
|
259
297
|
const { indentSpaces, lineNo } = p;
|
|
260
|
-
if (indentSpaces %
|
|
298
|
+
if (indentSpaces % indentStep !== 0) {
|
|
261
299
|
throw new Error(
|
|
262
|
-
`structure.txt: Invalid indent on line ${lineNo}. Indent must be multiples of ${
|
|
300
|
+
`structure.txt: Invalid indent on line ${lineNo}. Indent must be multiples of ${indentStep} spaces.`
|
|
263
301
|
);
|
|
264
302
|
}
|
|
265
|
-
const level = indentSpaces /
|
|
303
|
+
const level = indentSpaces / indentStep;
|
|
266
304
|
if (level > stack.length) {
|
|
267
305
|
if (level !== stack.length + 1) {
|
|
268
306
|
throw new Error(
|
|
@@ -885,7 +923,10 @@ const config: ScaffoldConfig = {
|
|
|
885
923
|
// base: 'src', // apply to <root>/src
|
|
886
924
|
// base: '..', // apply to parent of <root>
|
|
887
925
|
// base: '.',
|
|
888
|
-
|
|
926
|
+
|
|
927
|
+
// Number of spaces per indent level in structure files (default: 2).
|
|
928
|
+
// indentStep: 2,
|
|
929
|
+
|
|
889
930
|
// Cache file path, relative to base.
|
|
890
931
|
// cacheFile: '.scaffold-cache.json',
|
|
891
932
|
|
|
@@ -917,7 +958,7 @@ const config: ScaffoldConfig = {
|
|
|
917
958
|
|
|
918
959
|
export default config;
|
|
919
960
|
`;
|
|
920
|
-
var DEFAULT_STRUCTURE_TXT = `#
|
|
961
|
+
var DEFAULT_STRUCTURE_TXT = `# ${SCAFFOLD_ROOT_DIR}/structure.txt
|
|
921
962
|
# Example structure definition.
|
|
922
963
|
# - Indent with 2 spaces per level
|
|
923
964
|
# - Directories must end with "/"
|
|
@@ -929,7 +970,7 @@ var DEFAULT_STRUCTURE_TXT = `# scaffold/structure.txt
|
|
|
929
970
|
# index.ts
|
|
930
971
|
`;
|
|
931
972
|
async function initScaffold(cwd, options = {}) {
|
|
932
|
-
const scaffoldDirRel = options.scaffoldDir ??
|
|
973
|
+
const scaffoldDirRel = options.scaffoldDir ?? SCAFFOLD_ROOT_DIR;
|
|
933
974
|
const scaffoldDirAbs = path2.resolve(cwd, scaffoldDirRel);
|
|
934
975
|
const configFileName = options.configFileName ?? "config.ts";
|
|
935
976
|
const structureFileName = options.structureFileName ?? "structure.txt";
|