@libria/scaffold 0.3.0 → 0.3.2

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.
@@ -1,218 +1,3 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- //#region \0rolldown/runtime.js
3
- var __create = Object.create;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
- key = keys[i];
13
- if (!__hasOwnProp.call(to, key) && key !== except) {
14
- __defProp(to, key, {
15
- get: ((k) => from[k]).bind(null, key),
16
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
- });
18
- }
19
- }
20
- }
21
- return to;
22
- };
23
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
24
- value: mod,
25
- enumerable: true
26
- }) : target, mod));
27
-
28
- //#endregion
29
- let fs_promises = require("fs/promises");
30
- fs_promises = __toESM(fs_promises);
31
- let path = require("path");
32
- path = __toESM(path);
33
- let node_child_process = require("node:child_process");
34
- let node_util = require("node:util");
35
-
36
- //#region src/config.ts
37
- const CONFIG_FILENAME = ".lbscaffold";
38
- /**
39
- * Find the config file by searching up the directory tree
40
- */
41
- async function findConfigPath(startDir = process.cwd()) {
42
- let currentDir = startDir;
43
- while (true) {
44
- const configPath = path.default.join(currentDir, CONFIG_FILENAME);
45
- try {
46
- await fs_promises.default.access(configPath);
47
- return configPath;
48
- } catch {
49
- const parentDir = path.default.dirname(currentDir);
50
- if (parentDir === currentDir) return null;
51
- currentDir = parentDir;
52
- }
53
- }
54
- }
55
- /**
56
- * Get the default config path in the current directory
57
- */
58
- function getDefaultConfigPath() {
59
- return path.default.join(process.cwd(), CONFIG_FILENAME);
60
- }
61
- /**
62
- * Load the config file
63
- */
64
- async function loadConfig(configPath) {
65
- const resolvedPath = configPath ?? await findConfigPath();
66
- if (!resolvedPath) return {};
67
- try {
68
- const content = await fs_promises.default.readFile(resolvedPath, "utf-8");
69
- return JSON.parse(content);
70
- } catch (error) {
71
- if (error.code === "ENOENT") return {};
72
- throw new Error(`Failed to load config from ${resolvedPath}: ${error.message}`);
73
- }
74
- }
75
- /**
76
- * Save the config file
77
- */
78
- async function saveConfig(config, configPath) {
79
- const resolvedPath = configPath ?? getDefaultConfigPath();
80
- await fs_promises.default.writeFile(resolvedPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
81
- }
82
- /**
83
- * Initialize a new config file
84
- */
85
- async function initConfig(configPath) {
86
- const resolvedPath = configPath ?? getDefaultConfigPath();
87
- try {
88
- await fs_promises.default.access(resolvedPath);
89
- throw new Error(`Config file already exists at ${resolvedPath}`);
90
- } catch (error) {
91
- if (error.code !== "ENOENT") throw error;
92
- }
93
- await saveConfig({
94
- plugins: ["./plugins/**"],
95
- packages: []
96
- }, resolvedPath);
97
- return resolvedPath;
98
- }
99
- /**
100
- * Add a plugin glob pattern to the config
101
- */
102
- async function addPluginGlob(glob, configPath) {
103
- const config = await loadConfig(configPath);
104
- if (!config.plugins) config.plugins = [];
105
- if (config.plugins.includes(glob)) throw new Error(`Plugin pattern '${glob}' already exists in config`);
106
- config.plugins.push(glob);
107
- await saveConfig(config, configPath ?? await findConfigPath() ?? getDefaultConfigPath());
108
- }
109
- /**
110
- * Remove a plugin glob pattern from the config
111
- */
112
- async function removePluginGlob(glob, configPath) {
113
- const resolvedPath = configPath ?? await findConfigPath();
114
- if (!resolvedPath) throw new Error("No config file found");
115
- const config = await loadConfig(resolvedPath);
116
- if (!config.plugins || !config.plugins.includes(glob)) throw new Error(`Plugin pattern '${glob}' not found in config`);
117
- config.plugins = config.plugins.filter((p) => p !== glob);
118
- await saveConfig(config, resolvedPath);
119
- }
120
- /**
121
- * List all plugin glob patterns in the config
122
- */
123
- async function listPluginGlobs(configPath) {
124
- return (await loadConfig(configPath)).plugins ?? [];
125
- }
126
- /**
127
- * Get absolute plugin paths from config globs
128
- */
129
- async function getPluginPaths(configPath) {
130
- const resolvedConfigPath = configPath ?? await findConfigPath();
131
- if (!resolvedConfigPath) return [];
132
- const config = await loadConfig(resolvedConfigPath);
133
- const configDir = path.default.dirname(resolvedConfigPath);
134
- return (config.plugins ?? []).map((glob) => {
135
- if (path.default.isAbsolute(glob)) return glob.replace(/\\/g, "/");
136
- return path.default.resolve(configDir, glob).replace(/\\/g, "/");
137
- });
138
- }
139
- /**
140
- * Add an npm package name to the config
141
- */
142
- async function addPackage(packageName, configPath) {
143
- const config = await loadConfig(configPath);
144
- if (!config.packages) config.packages = [];
145
- if (config.packages.includes(packageName)) throw new Error(`Package '${packageName}' already exists in config`);
146
- config.packages.push(packageName);
147
- await saveConfig(config, configPath ?? await findConfigPath() ?? getDefaultConfigPath());
148
- }
149
- /**
150
- * Remove an npm package name from the config
151
- */
152
- async function removePackage(packageName, configPath) {
153
- const resolvedPath = configPath ?? await findConfigPath();
154
- if (!resolvedPath) throw new Error("No config file found");
155
- const config = await loadConfig(resolvedPath);
156
- if (!config.packages || !config.packages.includes(packageName)) throw new Error(`Package '${packageName}' not found in config`);
157
- config.packages = config.packages.filter((p) => p !== packageName);
158
- await saveConfig(config, resolvedPath);
159
- }
160
- /**
161
- * List all npm package names in the config
162
- */
163
- async function listPackages(configPath) {
164
- return (await loadConfig(configPath)).packages ?? [];
165
- }
166
-
167
- //#endregion
168
- //#region src/utils/resolve-package.ts
169
- const execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
170
- /**
171
- * Resolve an npm package name to its installed root directory.
172
- * Tries local node_modules first (relative to cwd), then global.
173
- */
174
- async function resolvePackageDir(packageName) {
175
- const localCandidate = path.default.join(process.cwd(), "node_modules", packageName);
176
- try {
177
- await fs_promises.default.access(path.default.join(localCandidate, "package.json"));
178
- return localCandidate;
179
- } catch {}
180
- const globalDir = await getGlobalNodeModulesDir();
181
- if (globalDir) {
182
- const globalCandidate = path.default.join(globalDir, packageName);
183
- try {
184
- await fs_promises.default.access(path.default.join(globalCandidate, "package.json"));
185
- return globalCandidate;
186
- } catch {}
187
- }
188
- throw new Error(`Package '${packageName}' not found. Install it locally (npm install ${packageName}) or globally (npm install -g ${packageName}).`);
189
- }
190
- /**
191
- * Get the global node_modules directory using npm root -g.
192
- */
193
- async function getGlobalNodeModulesDir() {
194
- try {
195
- const { stdout } = await execFileAsync("npm", ["root", "-g"], { encoding: "utf-8" });
196
- const dir = stdout.trim();
197
- await fs_promises.default.access(dir);
198
- return dir;
199
- } catch {
200
- return null;
201
- }
202
- }
203
-
204
- //#endregion
205
- exports.addPackage = addPackage;
206
- exports.addPluginGlob = addPluginGlob;
207
- exports.findConfigPath = findConfigPath;
208
- exports.getDefaultConfigPath = getDefaultConfigPath;
209
- exports.getPluginPaths = getPluginPaths;
210
- exports.initConfig = initConfig;
211
- exports.listPackages = listPackages;
212
- exports.listPluginGlobs = listPluginGlobs;
213
- exports.loadConfig = loadConfig;
214
- exports.removePackage = removePackage;
215
- exports.removePluginGlob = removePluginGlob;
216
- exports.resolvePackageDir = resolvePackageDir;
217
- exports.saveConfig = saveConfig;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`fs/promises`);c=s(c);let l=require(`path`);l=s(l);let u=require(`url`);const d=`.lbscaffold.json`;async function f(e=process.cwd()){let t=e;for(;;){let e=l.default.join(t,d);try{return await c.default.access(e),e}catch{let e=l.default.dirname(t);if(e===t)return null;t=e}}}function p(){return l.default.join(process.cwd(),d)}async function m(e){let t=e??await f();if(!t)return{};try{let e=await c.default.readFile(t,`utf-8`);return JSON.parse(e)}catch(e){if(e.code===`ENOENT`)return{};throw Error(`Failed to load config from ${t}: ${e.message}`)}}async function h(e,t){let n=t??p();await c.default.writeFile(n,JSON.stringify(e,null,2)+`
2
+ `,`utf-8`)}async function g(e){let t=e??p();try{throw await c.default.access(t),Error(`Config file already exists at ${t}`)}catch(e){if(e.code!==`ENOENT`)throw e}return await h({plugins:[`./plugins/**`],packages:[]},t),t}async function _(e,t){let n=await m(t);if(n.plugins||=[],n.plugins.includes(e))throw Error(`Plugin pattern '${e}' already exists in config`);n.plugins.push(e),await h(n,t??await f()??p())}async function v(e,t){let n=t??await f();if(!n)throw Error(`No config file found`);let r=await m(n);if(!r.plugins||!r.plugins.includes(e))throw Error(`Plugin pattern '${e}' not found in config`);r.plugins=r.plugins.filter(t=>t!==e),await h(r,n)}async function y(e){return(await m(e)).plugins??[]}async function b(e){let t=e??await f();if(!t)return[];let n=await m(t),r=l.default.dirname(t);return(n.plugins??[]).map(e=>l.default.isAbsolute(e)?e.replace(/\\/g,`/`):l.default.resolve(r,e).replace(/\\/g,`/`))}async function x(e,t){let n=await m(t);if(n.packages||=[],n.packages.includes(e))throw Error(`Package '${e}' already exists in config`);n.packages.push(e),await h(n,t??await f()??p())}async function S(e,t){let n=t??await f();if(!n)throw Error(`No config file found`);let r=await m(n);if(!r.packages||!r.packages.includes(e))throw Error(`Package '${e}' not found in config`);r.packages=r.packages.filter(t=>t!==e),await h(r,n)}async function C(e){return(await m(e)).packages??[]}async function w(e){try{let t={}.resolve(e),n=l.default.dirname((0,u.fileURLToPath)(t));for(;n!==l.default.dirname(n);)try{return await c.default.access(l.default.join(n,`package.json`)),n}catch{n=l.default.dirname(n)}throw Error(`package.json not found`)}catch{throw Error(`Package '${e}' not found. Install it locally (npm install ${e}) or globally (npm install -g ${e}).`)}}exports.addPackage=x,exports.addPluginGlob=_,exports.findConfigPath=f,exports.getDefaultConfigPath=p,exports.getPluginPaths=b,exports.initConfig=g,exports.listPackages=C,exports.listPluginGlobs=y,exports.loadConfig=m,exports.removePackage=S,exports.removePluginGlob=v,exports.resolvePackageDir=w,exports.saveConfig=h;
218
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["fs","execFile","fs"],"sources":["../../src/config.ts","../../src/utils/resolve-package.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\n\nexport interface LbScaffoldConfig {\n plugins?: string[];\n packages?: string[];\n}\n\nconst CONFIG_FILENAME = '.lbscaffold';\n\n/**\n * Find the config file by searching up the directory tree\n */\nexport async function findConfigPath(startDir: string = process.cwd()): Promise<string | null> {\n let currentDir = startDir;\n\n while (true) {\n const configPath = path.join(currentDir, CONFIG_FILENAME);\n try {\n await fs.access(configPath);\n return configPath;\n } catch {\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n // Reached root\n return null;\n }\n currentDir = parentDir;\n }\n }\n}\n\n/**\n * Get the default config path in the current directory\n */\nexport function getDefaultConfigPath(): string {\n return path.join(process.cwd(), CONFIG_FILENAME);\n}\n\n/**\n * Load the config file\n */\nexport async function loadConfig(configPath?: string): Promise<LbScaffoldConfig> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n return {};\n }\n\n try {\n const content = await fs.readFile(resolvedPath, 'utf-8');\n return JSON.parse(content) as LbScaffoldConfig;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return {};\n }\n throw new Error(`Failed to load config from ${resolvedPath}: ${(error as Error).message}`);\n }\n}\n\n/**\n * Save the config file\n */\nexport async function saveConfig(config: LbScaffoldConfig, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? getDefaultConfigPath();\n await fs.writeFile(resolvedPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\n/**\n * Initialize a new config file\n */\nexport async function initConfig(configPath?: string): Promise<string> {\n const resolvedPath = configPath ?? getDefaultConfigPath();\n\n try {\n await fs.access(resolvedPath);\n throw new Error(`Config file already exists at ${resolvedPath}`);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error;\n }\n }\n\n const defaultConfig: LbScaffoldConfig = {\n plugins: ['./plugins/**'],\n packages: [],\n };\n\n await saveConfig(defaultConfig, resolvedPath);\n return resolvedPath;\n}\n\n/**\n * Add a plugin glob pattern to the config\n */\nexport async function addPluginGlob(glob: string, configPath?: string): Promise<void> {\n const config = await loadConfig(configPath);\n\n if (!config.plugins) {\n config.plugins = [];\n }\n\n if (config.plugins.includes(glob)) {\n throw new Error(`Plugin pattern '${glob}' already exists in config`);\n }\n\n config.plugins.push(glob);\n await saveConfig(config, configPath ?? (await findConfigPath()) ?? getDefaultConfigPath());\n}\n\n/**\n * Remove a plugin glob pattern from the config\n */\nexport async function removePluginGlob(glob: string, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n throw new Error('No config file found');\n }\n\n const config = await loadConfig(resolvedPath);\n\n if (!config.plugins || !config.plugins.includes(glob)) {\n throw new Error(`Plugin pattern '${glob}' not found in config`);\n }\n\n config.plugins = config.plugins.filter(p => p !== glob);\n await saveConfig(config, resolvedPath);\n}\n\n/**\n * List all plugin glob patterns in the config\n */\nexport async function listPluginGlobs(configPath?: string): Promise<string[]> {\n const config = await loadConfig(configPath);\n return config.plugins ?? [];\n}\n\n/**\n * Get absolute plugin paths from config globs\n */\nexport async function getPluginPaths(configPath?: string): Promise<string[]> {\n const resolvedConfigPath = configPath ?? (await findConfigPath());\n\n if (!resolvedConfigPath) {\n return [];\n }\n\n const config = await loadConfig(resolvedConfigPath);\n const configDir = path.dirname(resolvedConfigPath);\n\n return (config.plugins ?? []).map(glob => {\n // If glob is absolute, use as-is; otherwise resolve relative to config file\n if (path.isAbsolute(glob)) {\n return glob.replace(/\\\\/g, '/');\n }\n return path.resolve(configDir, glob).replace(/\\\\/g, '/');\n });\n}\n\n/**\n * Add an npm package name to the config\n */\nexport async function addPackage(packageName: string, configPath?: string): Promise<void> {\n const config = await loadConfig(configPath);\n\n if (!config.packages) {\n config.packages = [];\n }\n\n if (config.packages.includes(packageName)) {\n throw new Error(`Package '${packageName}' already exists in config`);\n }\n\n config.packages.push(packageName);\n await saveConfig(config, configPath ?? (await findConfigPath()) ?? getDefaultConfigPath());\n}\n\n/**\n * Remove an npm package name from the config\n */\nexport async function removePackage(packageName: string, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n throw new Error('No config file found');\n }\n\n const config = await loadConfig(resolvedPath);\n\n if (!config.packages || !config.packages.includes(packageName)) {\n throw new Error(`Package '${packageName}' not found in config`);\n }\n\n config.packages = config.packages.filter(p => p !== packageName);\n await saveConfig(config, resolvedPath);\n}\n\n/**\n * List all npm package names in the config\n */\nexport async function listPackages(configPath?: string): Promise<string[]> {\n const config = await loadConfig(configPath);\n return config.packages ?? [];\n}\n","import fs from 'fs/promises';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport path from 'path';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Resolve an npm package name to its installed root directory.\n * Tries local node_modules first (relative to cwd), then global.\n */\nexport async function resolvePackageDir(packageName: string): Promise<string> {\n // Strategy 1: resolve from local node_modules via cwd\n const localCandidate = path.join(process.cwd(), 'node_modules', packageName);\n try {\n await fs.access(path.join(localCandidate, 'package.json'));\n return localCandidate;\n } catch {\n // Not found locally, try global\n }\n\n // Strategy 2: resolve from global node_modules\n const globalDir = await getGlobalNodeModulesDir();\n if (globalDir) {\n const globalCandidate = path.join(globalDir, packageName);\n try {\n await fs.access(path.join(globalCandidate, 'package.json'));\n return globalCandidate;\n } catch {\n // Not found globally either\n }\n }\n\n throw new Error(\n `Package '${packageName}' not found. ` +\n `Install it locally (npm install ${packageName}) or globally (npm install -g ${packageName}).`\n );\n}\n\n/**\n * Get the global node_modules directory using npm root -g.\n */\nasync function getGlobalNodeModulesDir(): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync('npm', ['root', '-g'], { encoding: 'utf-8' });\n const dir = stdout.trim();\n await fs.access(dir);\n return dir;\n } catch {\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,MAAM,kBAAkB;;;;AAKxB,eAAsB,eAAe,WAAmB,QAAQ,KAAK,EAA0B;CAC3F,IAAI,aAAa;AAEjB,QAAO,MAAM;EACT,MAAM,aAAa,aAAK,KAAK,YAAY,gBAAgB;AACzD,MAAI;AACA,SAAMA,oBAAG,OAAO,WAAW;AAC3B,UAAO;UACH;GACJ,MAAM,YAAY,aAAK,QAAQ,WAAW;AAC1C,OAAI,cAAc,WAEd,QAAO;AAEX,gBAAa;;;;;;;AAQzB,SAAgB,uBAA+B;AAC3C,QAAO,aAAK,KAAK,QAAQ,KAAK,EAAE,gBAAgB;;;;;AAMpD,eAAsB,WAAW,YAAgD;CAC7E,MAAM,eAAe,cAAe,MAAM,gBAAgB;AAE1D,KAAI,CAAC,aACD,QAAO,EAAE;AAGb,KAAI;EACA,MAAM,UAAU,MAAMA,oBAAG,SAAS,cAAc,QAAQ;AACxD,SAAO,KAAK,MAAM,QAAQ;UACrB,OAAO;AACZ,MAAK,MAAgC,SAAS,SAC1C,QAAO,EAAE;AAEb,QAAM,IAAI,MAAM,8BAA8B,aAAa,IAAK,MAAgB,UAAU;;;;;;AAOlG,eAAsB,WAAW,QAA0B,YAAoC;CAC3F,MAAM,eAAe,cAAc,sBAAsB;AACzD,OAAMA,oBAAG,UAAU,cAAc,KAAK,UAAU,QAAQ,MAAM,EAAE,GAAG,MAAM,QAAQ;;;;;AAMrF,eAAsB,WAAW,YAAsC;CACnE,MAAM,eAAe,cAAc,sBAAsB;AAEzD,KAAI;AACA,QAAMA,oBAAG,OAAO,aAAa;AAC7B,QAAM,IAAI,MAAM,iCAAiC,eAAe;UAC3D,OAAO;AACZ,MAAK,MAAgC,SAAS,SAC1C,OAAM;;AASd,OAAM,WALkC;EACpC,SAAS,CAAC,eAAe;EACzB,UAAU,EAAE;EACf,EAE+B,aAAa;AAC7C,QAAO;;;;;AAMX,eAAsB,cAAc,MAAc,YAAoC;CAClF,MAAM,SAAS,MAAM,WAAW,WAAW;AAE3C,KAAI,CAAC,OAAO,QACR,QAAO,UAAU,EAAE;AAGvB,KAAI,OAAO,QAAQ,SAAS,KAAK,CAC7B,OAAM,IAAI,MAAM,mBAAmB,KAAK,4BAA4B;AAGxE,QAAO,QAAQ,KAAK,KAAK;AACzB,OAAM,WAAW,QAAQ,cAAe,MAAM,gBAAgB,IAAK,sBAAsB,CAAC;;;;;AAM9F,eAAsB,iBAAiB,MAAc,YAAoC;CACrF,MAAM,eAAe,cAAe,MAAM,gBAAgB;AAE1D,KAAI,CAAC,aACD,OAAM,IAAI,MAAM,uBAAuB;CAG3C,MAAM,SAAS,MAAM,WAAW,aAAa;AAE7C,KAAI,CAAC,OAAO,WAAW,CAAC,OAAO,QAAQ,SAAS,KAAK,CACjD,OAAM,IAAI,MAAM,mBAAmB,KAAK,uBAAuB;AAGnE,QAAO,UAAU,OAAO,QAAQ,QAAO,MAAK,MAAM,KAAK;AACvD,OAAM,WAAW,QAAQ,aAAa;;;;;AAM1C,eAAsB,gBAAgB,YAAwC;AAE1E,SADe,MAAM,WAAW,WAAW,EAC7B,WAAW,EAAE;;;;;AAM/B,eAAsB,eAAe,YAAwC;CACzE,MAAM,qBAAqB,cAAe,MAAM,gBAAgB;AAEhE,KAAI,CAAC,mBACD,QAAO,EAAE;CAGb,MAAM,SAAS,MAAM,WAAW,mBAAmB;CACnD,MAAM,YAAY,aAAK,QAAQ,mBAAmB;AAElD,SAAQ,OAAO,WAAW,EAAE,EAAE,KAAI,SAAQ;AAEtC,MAAI,aAAK,WAAW,KAAK,CACrB,QAAO,KAAK,QAAQ,OAAO,IAAI;AAEnC,SAAO,aAAK,QAAQ,WAAW,KAAK,CAAC,QAAQ,OAAO,IAAI;GAC1D;;;;;AAMN,eAAsB,WAAW,aAAqB,YAAoC;CACtF,MAAM,SAAS,MAAM,WAAW,WAAW;AAE3C,KAAI,CAAC,OAAO,SACR,QAAO,WAAW,EAAE;AAGxB,KAAI,OAAO,SAAS,SAAS,YAAY,CACrC,OAAM,IAAI,MAAM,YAAY,YAAY,4BAA4B;AAGxE,QAAO,SAAS,KAAK,YAAY;AACjC,OAAM,WAAW,QAAQ,cAAe,MAAM,gBAAgB,IAAK,sBAAsB,CAAC;;;;;AAM9F,eAAsB,cAAc,aAAqB,YAAoC;CACzF,MAAM,eAAe,cAAe,MAAM,gBAAgB;AAE1D,KAAI,CAAC,aACD,OAAM,IAAI,MAAM,uBAAuB;CAG3C,MAAM,SAAS,MAAM,WAAW,aAAa;AAE7C,KAAI,CAAC,OAAO,YAAY,CAAC,OAAO,SAAS,SAAS,YAAY,CAC1D,OAAM,IAAI,MAAM,YAAY,YAAY,uBAAuB;AAGnE,QAAO,WAAW,OAAO,SAAS,QAAO,MAAK,MAAM,YAAY;AAChE,OAAM,WAAW,QAAQ,aAAa;;;;;AAM1C,eAAsB,aAAa,YAAwC;AAEvE,SADe,MAAM,WAAW,WAAW,EAC7B,YAAY,EAAE;;;;;ACtMhC,MAAM,yCAA0BC,4BAAS;;;;;AAMzC,eAAsB,kBAAkB,aAAsC;CAE1E,MAAM,iBAAiB,aAAK,KAAK,QAAQ,KAAK,EAAE,gBAAgB,YAAY;AAC5E,KAAI;AACA,QAAMC,oBAAG,OAAO,aAAK,KAAK,gBAAgB,eAAe,CAAC;AAC1D,SAAO;SACH;CAKR,MAAM,YAAY,MAAM,yBAAyB;AACjD,KAAI,WAAW;EACX,MAAM,kBAAkB,aAAK,KAAK,WAAW,YAAY;AACzD,MAAI;AACA,SAAMA,oBAAG,OAAO,aAAK,KAAK,iBAAiB,eAAe,CAAC;AAC3D,UAAO;UACH;;AAKZ,OAAM,IAAI,MACN,YAAY,YAAY,+CACe,YAAY,gCAAgC,YAAY,IAClG;;;;;AAML,eAAe,0BAAkD;AAC7D,KAAI;EACA,MAAM,EAAE,WAAW,MAAM,cAAc,OAAO,CAAC,QAAQ,KAAK,EAAE,EAAE,UAAU,SAAS,CAAC;EACpF,MAAM,MAAM,OAAO,MAAM;AACzB,QAAMA,oBAAG,OAAO,IAAI;AACpB,SAAO;SACH;AACJ,SAAO"}
1
+ {"version":3,"file":"index.cjs","names":["fs","fs"],"sources":["../../src/config.ts","../../src/utils/resolve-package.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\n\nexport interface LbScaffoldConfig {\n plugins?: string[];\n packages?: string[];\n}\n\nconst CONFIG_FILENAME = '.lbscaffold.json';\n\n/**\n * Find the config file by searching up the directory tree\n */\nexport async function findConfigPath(startDir: string = process.cwd()): Promise<string | null> {\n let currentDir = startDir;\n\n while (true) {\n const configPath = path.join(currentDir, CONFIG_FILENAME);\n try {\n await fs.access(configPath);\n return configPath;\n } catch {\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n // Reached root\n return null;\n }\n currentDir = parentDir;\n }\n }\n}\n\n/**\n * Get the default config path in the current directory\n */\nexport function getDefaultConfigPath(): string {\n return path.join(process.cwd(), CONFIG_FILENAME);\n}\n\n/**\n * Load the config file\n */\nexport async function loadConfig(configPath?: string): Promise<LbScaffoldConfig> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n return {};\n }\n\n try {\n const content = await fs.readFile(resolvedPath, 'utf-8');\n return JSON.parse(content) as LbScaffoldConfig;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return {};\n }\n throw new Error(`Failed to load config from ${resolvedPath}: ${(error as Error).message}`);\n }\n}\n\n/**\n * Save the config file\n */\nexport async function saveConfig(config: LbScaffoldConfig, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? getDefaultConfigPath();\n await fs.writeFile(resolvedPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\n/**\n * Initialize a new config file\n */\nexport async function initConfig(configPath?: string): Promise<string> {\n const resolvedPath = configPath ?? getDefaultConfigPath();\n\n try {\n await fs.access(resolvedPath);\n throw new Error(`Config file already exists at ${resolvedPath}`);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error;\n }\n }\n\n const defaultConfig: LbScaffoldConfig = {\n plugins: ['./plugins/**'],\n packages: [],\n };\n\n await saveConfig(defaultConfig, resolvedPath);\n return resolvedPath;\n}\n\n/**\n * Add a plugin glob pattern to the config\n */\nexport async function addPluginGlob(glob: string, configPath?: string): Promise<void> {\n const config = await loadConfig(configPath);\n\n if (!config.plugins) {\n config.plugins = [];\n }\n\n if (config.plugins.includes(glob)) {\n throw new Error(`Plugin pattern '${glob}' already exists in config`);\n }\n\n config.plugins.push(glob);\n await saveConfig(config, configPath ?? (await findConfigPath()) ?? getDefaultConfigPath());\n}\n\n/**\n * Remove a plugin glob pattern from the config\n */\nexport async function removePluginGlob(glob: string, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n throw new Error('No config file found');\n }\n\n const config = await loadConfig(resolvedPath);\n\n if (!config.plugins || !config.plugins.includes(glob)) {\n throw new Error(`Plugin pattern '${glob}' not found in config`);\n }\n\n config.plugins = config.plugins.filter(p => p !== glob);\n await saveConfig(config, resolvedPath);\n}\n\n/**\n * List all plugin glob patterns in the config\n */\nexport async function listPluginGlobs(configPath?: string): Promise<string[]> {\n const config = await loadConfig(configPath);\n return config.plugins ?? [];\n}\n\n/**\n * Get absolute plugin paths from config globs\n */\nexport async function getPluginPaths(configPath?: string): Promise<string[]> {\n const resolvedConfigPath = configPath ?? (await findConfigPath());\n\n if (!resolvedConfigPath) {\n return [];\n }\n\n const config = await loadConfig(resolvedConfigPath);\n const configDir = path.dirname(resolvedConfigPath);\n\n return (config.plugins ?? []).map(glob => {\n // If glob is absolute, use as-is; otherwise resolve relative to config file\n if (path.isAbsolute(glob)) {\n return glob.replace(/\\\\/g, '/');\n }\n return path.resolve(configDir, glob).replace(/\\\\/g, '/');\n });\n}\n\n/**\n * Add an npm package name to the config\n */\nexport async function addPackage(packageName: string, configPath?: string): Promise<void> {\n const config = await loadConfig(configPath);\n\n if (!config.packages) {\n config.packages = [];\n }\n\n if (config.packages.includes(packageName)) {\n throw new Error(`Package '${packageName}' already exists in config`);\n }\n\n config.packages.push(packageName);\n await saveConfig(config, configPath ?? (await findConfigPath()) ?? getDefaultConfigPath());\n}\n\n/**\n * Remove an npm package name from the config\n */\nexport async function removePackage(packageName: string, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n throw new Error('No config file found');\n }\n\n const config = await loadConfig(resolvedPath);\n\n if (!config.packages || !config.packages.includes(packageName)) {\n throw new Error(`Package '${packageName}' not found in config`);\n }\n\n config.packages = config.packages.filter(p => p !== packageName);\n await saveConfig(config, resolvedPath);\n}\n\n/**\n * List all npm package names in the config\n */\nexport async function listPackages(configPath?: string): Promise<string[]> {\n const config = await loadConfig(configPath);\n return config.packages ?? [];\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\n/**\n * Resolve an npm package name to its installed root directory.\n * Uses import.meta.resolve() to find the package entry point,\n * then walks up to find the package.json — this works regardless\n * of the package's `exports` configuration.\n *\n * Correctly handles:\n * - npm workspaces (hoisted node_modules)\n * - Symlinked packages\n * - Global installs\n */\nexport async function resolvePackageDir(packageName: string): Promise<string> {\n try {\n const entryUrl = import.meta.resolve(packageName);\n let dir = path.dirname(fileURLToPath(entryUrl));\n\n // Walk up until we find the package.json\n while (dir !== path.dirname(dir)) {\n try {\n await fs.access(path.join(dir, 'package.json'));\n return dir;\n } catch {\n dir = path.dirname(dir);\n }\n }\n\n throw new Error('package.json not found');\n } catch {\n throw new Error(\n `Package '${packageName}' not found. ` +\n `Install it locally (npm install ${packageName}) or globally (npm install -g ${packageName}).`\n );\n }\n}\n"],"mappings":"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"}
@@ -55,7 +55,14 @@ declare function listPackages(configPath?: string): Promise<string[]>;
55
55
  //#region src/utils/resolve-package.d.ts
56
56
  /**
57
57
  * Resolve an npm package name to its installed root directory.
58
- * Tries local node_modules first (relative to cwd), then global.
58
+ * Uses import.meta.resolve() to find the package entry point,
59
+ * then walks up to find the package.json — this works regardless
60
+ * of the package's `exports` configuration.
61
+ *
62
+ * Correctly handles:
63
+ * - npm workspaces (hoisted node_modules)
64
+ * - Symlinked packages
65
+ * - Global installs
59
66
  */
60
67
  declare function resolvePackageDir(packageName: string): Promise<string>;
61
68
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/config.ts","../../src/utils/resolve-package.ts"],"mappings":";UAGiB,gBAAA;EACb,OAAA;EACA,QAAA;AAAA;;;AAQJ;iBAAsB,cAAA,CAAe,QAAA,YAAmC,OAAA;;;;iBAsBxD,oBAAA,CAAA;;;;iBAOM,UAAA,CAAW,UAAA,YAAsB,OAAA,CAAQ,gBAAA;AAA/D;;;AAAA,iBAqBsB,UAAA,CAAW,MAAA,EAAQ,gBAAA,EAAkB,UAAA,YAAsB,OAAA;;;;iBAQ3D,UAAA,CAAW,UAAA,YAAsB,OAAA;;AARvD;;iBAgCsB,aAAA,CAAc,IAAA,UAAc,UAAA,YAAsB,OAAA;;;;iBAkBlD,gBAAA,CAAiB,IAAA,UAAc,UAAA,YAAsB,OAAA;;;;iBAoBrD,eAAA,CAAgB,UAAA,YAAsB,OAAA;;;;iBAQtC,cAAA,CAAe,UAAA,YAAsB,OAAA;AA9C3D;;;AAAA,iBAoEsB,UAAA,CAAW,WAAA,UAAqB,UAAA,YAAsB,OAAA;;;;iBAkBtD,aAAA,CAAc,WAAA,UAAqB,UAAA,YAAsB,OAAA;;AApE/E;;iBAwFsB,YAAA,CAAa,UAAA,YAAsB,OAAA;;;;AAtMzD;;;iBCQsB,iBAAA,CAAkB,WAAA,WAAsB,OAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/config.ts","../../src/utils/resolve-package.ts"],"mappings":";UAGiB,gBAAA;EACb,OAAA;EACA,QAAA;AAAA;;;AAQJ;iBAAsB,cAAA,CAAe,QAAA,YAAmC,OAAA;;;;iBAsBxD,oBAAA,CAAA;;;;iBAOM,UAAA,CAAW,UAAA,YAAsB,OAAA,CAAQ,gBAAA;AAA/D;;;AAAA,iBAqBsB,UAAA,CAAW,MAAA,EAAQ,gBAAA,EAAkB,UAAA,YAAsB,OAAA;;;;iBAQ3D,UAAA,CAAW,UAAA,YAAsB,OAAA;;AARvD;;iBAgCsB,aAAA,CAAc,IAAA,UAAc,UAAA,YAAsB,OAAA;;;;iBAkBlD,gBAAA,CAAiB,IAAA,UAAc,UAAA,YAAsB,OAAA;;;;iBAoBrD,eAAA,CAAgB,UAAA,YAAsB,OAAA;;;;iBAQtC,cAAA,CAAe,UAAA,YAAsB,OAAA;AA9C3D;;;AAAA,iBAoEsB,UAAA,CAAW,WAAA,UAAqB,UAAA,YAAsB,OAAA;;;;iBAkBtD,aAAA,CAAc,WAAA,UAAqB,UAAA,YAAsB,OAAA;;AApE/E;;iBAwFsB,YAAA,CAAa,UAAA,YAAsB,OAAA;;;;AAtMzD;;;;;AAUA;;;;;iBCEsB,iBAAA,CAAkB,WAAA,WAAsB,OAAA"}
@@ -55,7 +55,14 @@ declare function listPackages(configPath?: string): Promise<string[]>;
55
55
  //#region src/utils/resolve-package.d.ts
56
56
  /**
57
57
  * Resolve an npm package name to its installed root directory.
58
- * Tries local node_modules first (relative to cwd), then global.
58
+ * Uses import.meta.resolve() to find the package entry point,
59
+ * then walks up to find the package.json — this works regardless
60
+ * of the package's `exports` configuration.
61
+ *
62
+ * Correctly handles:
63
+ * - npm workspaces (hoisted node_modules)
64
+ * - Symlinked packages
65
+ * - Global installs
59
66
  */
60
67
  declare function resolvePackageDir(packageName: string): Promise<string>;
61
68
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/config.ts","../../src/utils/resolve-package.ts"],"mappings":";UAGiB,gBAAA;EACb,OAAA;EACA,QAAA;AAAA;;;AAQJ;iBAAsB,cAAA,CAAe,QAAA,YAAmC,OAAA;;;;iBAsBxD,oBAAA,CAAA;;;;iBAOM,UAAA,CAAW,UAAA,YAAsB,OAAA,CAAQ,gBAAA;AAA/D;;;AAAA,iBAqBsB,UAAA,CAAW,MAAA,EAAQ,gBAAA,EAAkB,UAAA,YAAsB,OAAA;;;;iBAQ3D,UAAA,CAAW,UAAA,YAAsB,OAAA;;AARvD;;iBAgCsB,aAAA,CAAc,IAAA,UAAc,UAAA,YAAsB,OAAA;;;;iBAkBlD,gBAAA,CAAiB,IAAA,UAAc,UAAA,YAAsB,OAAA;;;;iBAoBrD,eAAA,CAAgB,UAAA,YAAsB,OAAA;;;;iBAQtC,cAAA,CAAe,UAAA,YAAsB,OAAA;AA9C3D;;;AAAA,iBAoEsB,UAAA,CAAW,WAAA,UAAqB,UAAA,YAAsB,OAAA;;;;iBAkBtD,aAAA,CAAc,WAAA,UAAqB,UAAA,YAAsB,OAAA;;AApE/E;;iBAwFsB,YAAA,CAAa,UAAA,YAAsB,OAAA;;;;AAtMzD;;;iBCQsB,iBAAA,CAAkB,WAAA,WAAsB,OAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/config.ts","../../src/utils/resolve-package.ts"],"mappings":";UAGiB,gBAAA;EACb,OAAA;EACA,QAAA;AAAA;;;AAQJ;iBAAsB,cAAA,CAAe,QAAA,YAAmC,OAAA;;;;iBAsBxD,oBAAA,CAAA;;;;iBAOM,UAAA,CAAW,UAAA,YAAsB,OAAA,CAAQ,gBAAA;AAA/D;;;AAAA,iBAqBsB,UAAA,CAAW,MAAA,EAAQ,gBAAA,EAAkB,UAAA,YAAsB,OAAA;;;;iBAQ3D,UAAA,CAAW,UAAA,YAAsB,OAAA;;AARvD;;iBAgCsB,aAAA,CAAc,IAAA,UAAc,UAAA,YAAsB,OAAA;;;;iBAkBlD,gBAAA,CAAiB,IAAA,UAAc,UAAA,YAAsB,OAAA;;;;iBAoBrD,eAAA,CAAgB,UAAA,YAAsB,OAAA;;;;iBAQtC,cAAA,CAAe,UAAA,YAAsB,OAAA;AA9C3D;;;AAAA,iBAoEsB,UAAA,CAAW,WAAA,UAAqB,UAAA,YAAsB,OAAA;;;;iBAkBtD,aAAA,CAAc,WAAA,UAAqB,UAAA,YAAsB,OAAA;;AApE/E;;iBAwFsB,YAAA,CAAa,UAAA,YAAsB,OAAA;;;;AAtMzD;;;;;AAUA;;;;;iBCEsB,iBAAA,CAAkB,WAAA,WAAsB,OAAA"}
@@ -1,176 +1,3 @@
1
- import fs from "fs/promises";
2
- import path from "path";
3
- import { execFile } from "node:child_process";
4
- import { promisify } from "node:util";
5
-
6
- //#region src/config.ts
7
- const CONFIG_FILENAME = ".lbscaffold";
8
- /**
9
- * Find the config file by searching up the directory tree
10
- */
11
- async function findConfigPath(startDir = process.cwd()) {
12
- let currentDir = startDir;
13
- while (true) {
14
- const configPath = path.join(currentDir, CONFIG_FILENAME);
15
- try {
16
- await fs.access(configPath);
17
- return configPath;
18
- } catch {
19
- const parentDir = path.dirname(currentDir);
20
- if (parentDir === currentDir) return null;
21
- currentDir = parentDir;
22
- }
23
- }
24
- }
25
- /**
26
- * Get the default config path in the current directory
27
- */
28
- function getDefaultConfigPath() {
29
- return path.join(process.cwd(), CONFIG_FILENAME);
30
- }
31
- /**
32
- * Load the config file
33
- */
34
- async function loadConfig(configPath) {
35
- const resolvedPath = configPath ?? await findConfigPath();
36
- if (!resolvedPath) return {};
37
- try {
38
- const content = await fs.readFile(resolvedPath, "utf-8");
39
- return JSON.parse(content);
40
- } catch (error) {
41
- if (error.code === "ENOENT") return {};
42
- throw new Error(`Failed to load config from ${resolvedPath}: ${error.message}`);
43
- }
44
- }
45
- /**
46
- * Save the config file
47
- */
48
- async function saveConfig(config, configPath) {
49
- const resolvedPath = configPath ?? getDefaultConfigPath();
50
- await fs.writeFile(resolvedPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
51
- }
52
- /**
53
- * Initialize a new config file
54
- */
55
- async function initConfig(configPath) {
56
- const resolvedPath = configPath ?? getDefaultConfigPath();
57
- try {
58
- await fs.access(resolvedPath);
59
- throw new Error(`Config file already exists at ${resolvedPath}`);
60
- } catch (error) {
61
- if (error.code !== "ENOENT") throw error;
62
- }
63
- await saveConfig({
64
- plugins: ["./plugins/**"],
65
- packages: []
66
- }, resolvedPath);
67
- return resolvedPath;
68
- }
69
- /**
70
- * Add a plugin glob pattern to the config
71
- */
72
- async function addPluginGlob(glob, configPath) {
73
- const config = await loadConfig(configPath);
74
- if (!config.plugins) config.plugins = [];
75
- if (config.plugins.includes(glob)) throw new Error(`Plugin pattern '${glob}' already exists in config`);
76
- config.plugins.push(glob);
77
- await saveConfig(config, configPath ?? await findConfigPath() ?? getDefaultConfigPath());
78
- }
79
- /**
80
- * Remove a plugin glob pattern from the config
81
- */
82
- async function removePluginGlob(glob, configPath) {
83
- const resolvedPath = configPath ?? await findConfigPath();
84
- if (!resolvedPath) throw new Error("No config file found");
85
- const config = await loadConfig(resolvedPath);
86
- if (!config.plugins || !config.plugins.includes(glob)) throw new Error(`Plugin pattern '${glob}' not found in config`);
87
- config.plugins = config.plugins.filter((p) => p !== glob);
88
- await saveConfig(config, resolvedPath);
89
- }
90
- /**
91
- * List all plugin glob patterns in the config
92
- */
93
- async function listPluginGlobs(configPath) {
94
- return (await loadConfig(configPath)).plugins ?? [];
95
- }
96
- /**
97
- * Get absolute plugin paths from config globs
98
- */
99
- async function getPluginPaths(configPath) {
100
- const resolvedConfigPath = configPath ?? await findConfigPath();
101
- if (!resolvedConfigPath) return [];
102
- const config = await loadConfig(resolvedConfigPath);
103
- const configDir = path.dirname(resolvedConfigPath);
104
- return (config.plugins ?? []).map((glob) => {
105
- if (path.isAbsolute(glob)) return glob.replace(/\\/g, "/");
106
- return path.resolve(configDir, glob).replace(/\\/g, "/");
107
- });
108
- }
109
- /**
110
- * Add an npm package name to the config
111
- */
112
- async function addPackage(packageName, configPath) {
113
- const config = await loadConfig(configPath);
114
- if (!config.packages) config.packages = [];
115
- if (config.packages.includes(packageName)) throw new Error(`Package '${packageName}' already exists in config`);
116
- config.packages.push(packageName);
117
- await saveConfig(config, configPath ?? await findConfigPath() ?? getDefaultConfigPath());
118
- }
119
- /**
120
- * Remove an npm package name from the config
121
- */
122
- async function removePackage(packageName, configPath) {
123
- const resolvedPath = configPath ?? await findConfigPath();
124
- if (!resolvedPath) throw new Error("No config file found");
125
- const config = await loadConfig(resolvedPath);
126
- if (!config.packages || !config.packages.includes(packageName)) throw new Error(`Package '${packageName}' not found in config`);
127
- config.packages = config.packages.filter((p) => p !== packageName);
128
- await saveConfig(config, resolvedPath);
129
- }
130
- /**
131
- * List all npm package names in the config
132
- */
133
- async function listPackages(configPath) {
134
- return (await loadConfig(configPath)).packages ?? [];
135
- }
136
-
137
- //#endregion
138
- //#region src/utils/resolve-package.ts
139
- const execFileAsync = promisify(execFile);
140
- /**
141
- * Resolve an npm package name to its installed root directory.
142
- * Tries local node_modules first (relative to cwd), then global.
143
- */
144
- async function resolvePackageDir(packageName) {
145
- const localCandidate = path.join(process.cwd(), "node_modules", packageName);
146
- try {
147
- await fs.access(path.join(localCandidate, "package.json"));
148
- return localCandidate;
149
- } catch {}
150
- const globalDir = await getGlobalNodeModulesDir();
151
- if (globalDir) {
152
- const globalCandidate = path.join(globalDir, packageName);
153
- try {
154
- await fs.access(path.join(globalCandidate, "package.json"));
155
- return globalCandidate;
156
- } catch {}
157
- }
158
- throw new Error(`Package '${packageName}' not found. Install it locally (npm install ${packageName}) or globally (npm install -g ${packageName}).`);
159
- }
160
- /**
161
- * Get the global node_modules directory using npm root -g.
162
- */
163
- async function getGlobalNodeModulesDir() {
164
- try {
165
- const { stdout } = await execFileAsync("npm", ["root", "-g"], { encoding: "utf-8" });
166
- const dir = stdout.trim();
167
- await fs.access(dir);
168
- return dir;
169
- } catch {
170
- return null;
171
- }
172
- }
173
-
174
- //#endregion
175
- export { addPackage, addPluginGlob, findConfigPath, getDefaultConfigPath, getPluginPaths, initConfig, listPackages, listPluginGlobs, loadConfig, removePackage, removePluginGlob, resolvePackageDir, saveConfig };
1
+ import e from"fs/promises";import t from"path";import{fileURLToPath as n}from"url";const r=`.lbscaffold.json`;async function i(n=process.cwd()){let i=n;for(;;){let n=t.join(i,r);try{return await e.access(n),n}catch{let e=t.dirname(i);if(e===i)return null;i=e}}}function a(){return t.join(process.cwd(),r)}async function o(t){let n=t??await i();if(!n)return{};try{let t=await e.readFile(n,`utf-8`);return JSON.parse(t)}catch(e){if(e.code===`ENOENT`)return{};throw Error(`Failed to load config from ${n}: ${e.message}`)}}async function s(t,n){let r=n??a();await e.writeFile(r,JSON.stringify(t,null,2)+`
2
+ `,`utf-8`)}async function c(t){let n=t??a();try{throw await e.access(n),Error(`Config file already exists at ${n}`)}catch(e){if(e.code!==`ENOENT`)throw e}return await s({plugins:[`./plugins/**`],packages:[]},n),n}async function l(e,t){let n=await o(t);if(n.plugins||=[],n.plugins.includes(e))throw Error(`Plugin pattern '${e}' already exists in config`);n.plugins.push(e),await s(n,t??await i()??a())}async function u(e,t){let n=t??await i();if(!n)throw Error(`No config file found`);let r=await o(n);if(!r.plugins||!r.plugins.includes(e))throw Error(`Plugin pattern '${e}' not found in config`);r.plugins=r.plugins.filter(t=>t!==e),await s(r,n)}async function d(e){return(await o(e)).plugins??[]}async function f(e){let n=e??await i();if(!n)return[];let r=await o(n),a=t.dirname(n);return(r.plugins??[]).map(e=>t.isAbsolute(e)?e.replace(/\\/g,`/`):t.resolve(a,e).replace(/\\/g,`/`))}async function p(e,t){let n=await o(t);if(n.packages||=[],n.packages.includes(e))throw Error(`Package '${e}' already exists in config`);n.packages.push(e),await s(n,t??await i()??a())}async function m(e,t){let n=t??await i();if(!n)throw Error(`No config file found`);let r=await o(n);if(!r.packages||!r.packages.includes(e))throw Error(`Package '${e}' not found in config`);r.packages=r.packages.filter(t=>t!==e),await s(r,n)}async function h(e){return(await o(e)).packages??[]}async function g(r){try{let i=import.meta.resolve(r),a=t.dirname(n(i));for(;a!==t.dirname(a);)try{return await e.access(t.join(a,`package.json`)),a}catch{a=t.dirname(a)}throw Error(`package.json not found`)}catch{throw Error(`Package '${r}' not found. Install it locally (npm install ${r}) or globally (npm install -g ${r}).`)}}export{p as addPackage,l as addPluginGlob,i as findConfigPath,a as getDefaultConfigPath,f as getPluginPaths,c as initConfig,h as listPackages,d as listPluginGlobs,o as loadConfig,m as removePackage,u as removePluginGlob,g as resolvePackageDir,s as saveConfig};
176
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/config.ts","../../src/utils/resolve-package.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\n\nexport interface LbScaffoldConfig {\n plugins?: string[];\n packages?: string[];\n}\n\nconst CONFIG_FILENAME = '.lbscaffold';\n\n/**\n * Find the config file by searching up the directory tree\n */\nexport async function findConfigPath(startDir: string = process.cwd()): Promise<string | null> {\n let currentDir = startDir;\n\n while (true) {\n const configPath = path.join(currentDir, CONFIG_FILENAME);\n try {\n await fs.access(configPath);\n return configPath;\n } catch {\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n // Reached root\n return null;\n }\n currentDir = parentDir;\n }\n }\n}\n\n/**\n * Get the default config path in the current directory\n */\nexport function getDefaultConfigPath(): string {\n return path.join(process.cwd(), CONFIG_FILENAME);\n}\n\n/**\n * Load the config file\n */\nexport async function loadConfig(configPath?: string): Promise<LbScaffoldConfig> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n return {};\n }\n\n try {\n const content = await fs.readFile(resolvedPath, 'utf-8');\n return JSON.parse(content) as LbScaffoldConfig;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return {};\n }\n throw new Error(`Failed to load config from ${resolvedPath}: ${(error as Error).message}`);\n }\n}\n\n/**\n * Save the config file\n */\nexport async function saveConfig(config: LbScaffoldConfig, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? getDefaultConfigPath();\n await fs.writeFile(resolvedPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\n/**\n * Initialize a new config file\n */\nexport async function initConfig(configPath?: string): Promise<string> {\n const resolvedPath = configPath ?? getDefaultConfigPath();\n\n try {\n await fs.access(resolvedPath);\n throw new Error(`Config file already exists at ${resolvedPath}`);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error;\n }\n }\n\n const defaultConfig: LbScaffoldConfig = {\n plugins: ['./plugins/**'],\n packages: [],\n };\n\n await saveConfig(defaultConfig, resolvedPath);\n return resolvedPath;\n}\n\n/**\n * Add a plugin glob pattern to the config\n */\nexport async function addPluginGlob(glob: string, configPath?: string): Promise<void> {\n const config = await loadConfig(configPath);\n\n if (!config.plugins) {\n config.plugins = [];\n }\n\n if (config.plugins.includes(glob)) {\n throw new Error(`Plugin pattern '${glob}' already exists in config`);\n }\n\n config.plugins.push(glob);\n await saveConfig(config, configPath ?? (await findConfigPath()) ?? getDefaultConfigPath());\n}\n\n/**\n * Remove a plugin glob pattern from the config\n */\nexport async function removePluginGlob(glob: string, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n throw new Error('No config file found');\n }\n\n const config = await loadConfig(resolvedPath);\n\n if (!config.plugins || !config.plugins.includes(glob)) {\n throw new Error(`Plugin pattern '${glob}' not found in config`);\n }\n\n config.plugins = config.plugins.filter(p => p !== glob);\n await saveConfig(config, resolvedPath);\n}\n\n/**\n * List all plugin glob patterns in the config\n */\nexport async function listPluginGlobs(configPath?: string): Promise<string[]> {\n const config = await loadConfig(configPath);\n return config.plugins ?? [];\n}\n\n/**\n * Get absolute plugin paths from config globs\n */\nexport async function getPluginPaths(configPath?: string): Promise<string[]> {\n const resolvedConfigPath = configPath ?? (await findConfigPath());\n\n if (!resolvedConfigPath) {\n return [];\n }\n\n const config = await loadConfig(resolvedConfigPath);\n const configDir = path.dirname(resolvedConfigPath);\n\n return (config.plugins ?? []).map(glob => {\n // If glob is absolute, use as-is; otherwise resolve relative to config file\n if (path.isAbsolute(glob)) {\n return glob.replace(/\\\\/g, '/');\n }\n return path.resolve(configDir, glob).replace(/\\\\/g, '/');\n });\n}\n\n/**\n * Add an npm package name to the config\n */\nexport async function addPackage(packageName: string, configPath?: string): Promise<void> {\n const config = await loadConfig(configPath);\n\n if (!config.packages) {\n config.packages = [];\n }\n\n if (config.packages.includes(packageName)) {\n throw new Error(`Package '${packageName}' already exists in config`);\n }\n\n config.packages.push(packageName);\n await saveConfig(config, configPath ?? (await findConfigPath()) ?? getDefaultConfigPath());\n}\n\n/**\n * Remove an npm package name from the config\n */\nexport async function removePackage(packageName: string, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n throw new Error('No config file found');\n }\n\n const config = await loadConfig(resolvedPath);\n\n if (!config.packages || !config.packages.includes(packageName)) {\n throw new Error(`Package '${packageName}' not found in config`);\n }\n\n config.packages = config.packages.filter(p => p !== packageName);\n await saveConfig(config, resolvedPath);\n}\n\n/**\n * List all npm package names in the config\n */\nexport async function listPackages(configPath?: string): Promise<string[]> {\n const config = await loadConfig(configPath);\n return config.packages ?? [];\n}\n","import fs from 'fs/promises';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport path from 'path';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Resolve an npm package name to its installed root directory.\n * Tries local node_modules first (relative to cwd), then global.\n */\nexport async function resolvePackageDir(packageName: string): Promise<string> {\n // Strategy 1: resolve from local node_modules via cwd\n const localCandidate = path.join(process.cwd(), 'node_modules', packageName);\n try {\n await fs.access(path.join(localCandidate, 'package.json'));\n return localCandidate;\n } catch {\n // Not found locally, try global\n }\n\n // Strategy 2: resolve from global node_modules\n const globalDir = await getGlobalNodeModulesDir();\n if (globalDir) {\n const globalCandidate = path.join(globalDir, packageName);\n try {\n await fs.access(path.join(globalCandidate, 'package.json'));\n return globalCandidate;\n } catch {\n // Not found globally either\n }\n }\n\n throw new Error(\n `Package '${packageName}' not found. ` +\n `Install it locally (npm install ${packageName}) or globally (npm install -g ${packageName}).`\n );\n}\n\n/**\n * Get the global node_modules directory using npm root -g.\n */\nasync function getGlobalNodeModulesDir(): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync('npm', ['root', '-g'], { encoding: 'utf-8' });\n const dir = stdout.trim();\n await fs.access(dir);\n return dir;\n } catch {\n return null;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/config.ts","../../src/utils/resolve-package.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\n\nexport interface LbScaffoldConfig {\n plugins?: string[];\n packages?: string[];\n}\n\nconst CONFIG_FILENAME = '.lbscaffold.json';\n\n/**\n * Find the config file by searching up the directory tree\n */\nexport async function findConfigPath(startDir: string = process.cwd()): Promise<string | null> {\n let currentDir = startDir;\n\n while (true) {\n const configPath = path.join(currentDir, CONFIG_FILENAME);\n try {\n await fs.access(configPath);\n return configPath;\n } catch {\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n // Reached root\n return null;\n }\n currentDir = parentDir;\n }\n }\n}\n\n/**\n * Get the default config path in the current directory\n */\nexport function getDefaultConfigPath(): string {\n return path.join(process.cwd(), CONFIG_FILENAME);\n}\n\n/**\n * Load the config file\n */\nexport async function loadConfig(configPath?: string): Promise<LbScaffoldConfig> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n return {};\n }\n\n try {\n const content = await fs.readFile(resolvedPath, 'utf-8');\n return JSON.parse(content) as LbScaffoldConfig;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return {};\n }\n throw new Error(`Failed to load config from ${resolvedPath}: ${(error as Error).message}`);\n }\n}\n\n/**\n * Save the config file\n */\nexport async function saveConfig(config: LbScaffoldConfig, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? getDefaultConfigPath();\n await fs.writeFile(resolvedPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\n/**\n * Initialize a new config file\n */\nexport async function initConfig(configPath?: string): Promise<string> {\n const resolvedPath = configPath ?? getDefaultConfigPath();\n\n try {\n await fs.access(resolvedPath);\n throw new Error(`Config file already exists at ${resolvedPath}`);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error;\n }\n }\n\n const defaultConfig: LbScaffoldConfig = {\n plugins: ['./plugins/**'],\n packages: [],\n };\n\n await saveConfig(defaultConfig, resolvedPath);\n return resolvedPath;\n}\n\n/**\n * Add a plugin glob pattern to the config\n */\nexport async function addPluginGlob(glob: string, configPath?: string): Promise<void> {\n const config = await loadConfig(configPath);\n\n if (!config.plugins) {\n config.plugins = [];\n }\n\n if (config.plugins.includes(glob)) {\n throw new Error(`Plugin pattern '${glob}' already exists in config`);\n }\n\n config.plugins.push(glob);\n await saveConfig(config, configPath ?? (await findConfigPath()) ?? getDefaultConfigPath());\n}\n\n/**\n * Remove a plugin glob pattern from the config\n */\nexport async function removePluginGlob(glob: string, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n throw new Error('No config file found');\n }\n\n const config = await loadConfig(resolvedPath);\n\n if (!config.plugins || !config.plugins.includes(glob)) {\n throw new Error(`Plugin pattern '${glob}' not found in config`);\n }\n\n config.plugins = config.plugins.filter(p => p !== glob);\n await saveConfig(config, resolvedPath);\n}\n\n/**\n * List all plugin glob patterns in the config\n */\nexport async function listPluginGlobs(configPath?: string): Promise<string[]> {\n const config = await loadConfig(configPath);\n return config.plugins ?? [];\n}\n\n/**\n * Get absolute plugin paths from config globs\n */\nexport async function getPluginPaths(configPath?: string): Promise<string[]> {\n const resolvedConfigPath = configPath ?? (await findConfigPath());\n\n if (!resolvedConfigPath) {\n return [];\n }\n\n const config = await loadConfig(resolvedConfigPath);\n const configDir = path.dirname(resolvedConfigPath);\n\n return (config.plugins ?? []).map(glob => {\n // If glob is absolute, use as-is; otherwise resolve relative to config file\n if (path.isAbsolute(glob)) {\n return glob.replace(/\\\\/g, '/');\n }\n return path.resolve(configDir, glob).replace(/\\\\/g, '/');\n });\n}\n\n/**\n * Add an npm package name to the config\n */\nexport async function addPackage(packageName: string, configPath?: string): Promise<void> {\n const config = await loadConfig(configPath);\n\n if (!config.packages) {\n config.packages = [];\n }\n\n if (config.packages.includes(packageName)) {\n throw new Error(`Package '${packageName}' already exists in config`);\n }\n\n config.packages.push(packageName);\n await saveConfig(config, configPath ?? (await findConfigPath()) ?? getDefaultConfigPath());\n}\n\n/**\n * Remove an npm package name from the config\n */\nexport async function removePackage(packageName: string, configPath?: string): Promise<void> {\n const resolvedPath = configPath ?? (await findConfigPath());\n\n if (!resolvedPath) {\n throw new Error('No config file found');\n }\n\n const config = await loadConfig(resolvedPath);\n\n if (!config.packages || !config.packages.includes(packageName)) {\n throw new Error(`Package '${packageName}' not found in config`);\n }\n\n config.packages = config.packages.filter(p => p !== packageName);\n await saveConfig(config, resolvedPath);\n}\n\n/**\n * List all npm package names in the config\n */\nexport async function listPackages(configPath?: string): Promise<string[]> {\n const config = await loadConfig(configPath);\n return config.packages ?? [];\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\n/**\n * Resolve an npm package name to its installed root directory.\n * Uses import.meta.resolve() to find the package entry point,\n * then walks up to find the package.json — this works regardless\n * of the package's `exports` configuration.\n *\n * Correctly handles:\n * - npm workspaces (hoisted node_modules)\n * - Symlinked packages\n * - Global installs\n */\nexport async function resolvePackageDir(packageName: string): Promise<string> {\n try {\n const entryUrl = import.meta.resolve(packageName);\n let dir = path.dirname(fileURLToPath(entryUrl));\n\n // Walk up until we find the package.json\n while (dir !== path.dirname(dir)) {\n try {\n await fs.access(path.join(dir, 'package.json'));\n return dir;\n } catch {\n dir = path.dirname(dir);\n }\n }\n\n throw new Error('package.json not found');\n } catch {\n throw new Error(\n `Package '${packageName}' not found. ` +\n `Install it locally (npm install ${packageName}) or globally (npm install -g ${packageName}).`\n );\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@libria/scaffold",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "A pluggable CLI that transforms blank directories into production-ready codebases in seconds",
5
5
  "main": "dist/cli/index.cjs",
6
6
  "module": "dist/cli/index.mjs",
@@ -36,15 +36,16 @@
36
36
  "homepage": "https://github.com/LibriaForge/scaffold#readme",
37
37
  "dependencies": {
38
38
  "@libria/plugin-loader": "^2.0.0-alpha",
39
- "@libria/scaffold-core": "^0.3.0",
39
+ "@libria/scaffold-core": "^0.3.1",
40
40
  "commander": "^14.0.3",
41
41
  "fast-glob": "^3.3.3",
42
42
  "fs-extra": "^11.3.3",
43
43
  "interactive-commander": "^0.6.0"
44
44
  },
45
45
  "optionalDependencies": {
46
- "@libria/scaffold-angular": "^0.0.4",
47
- "@libria/scaffold-nestjs": "^0.0.3",
48
- "@libria/scaffold-ts-lib": "^0.0.6"
46
+ "@libria/scaffold-plugin-angular": "^0.0.1",
47
+ "@libria/scaffold-plugin-nestjs": "^0.0.1",
48
+ "@libria/scaffold-plugin-ts-lib": "^0.0.1",
49
+ "@libria/scaffold-plugin-ts-workspace": "^0.0.1"
49
50
  }
50
51
  }