@treelocator/init 0.1.8 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +260 -24
  2. package/package.json +2 -2
  3. package/LICENSE +0 -22
package/dist/index.js CHANGED
@@ -106,6 +106,171 @@ function getInstallCommand(pm, packages) {
106
106
  return `npm install -D ${pkgs}`;
107
107
  }
108
108
  }
109
+ function checkConfiguration(info) {
110
+ const results = [];
111
+ const pkgPath = path.join(process.cwd(), "package.json");
112
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
113
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
114
+ if (deps["@treelocator/runtime"]) {
115
+ results.push({
116
+ name: "@treelocator/runtime",
117
+ status: "ok",
118
+ message: `Installed (${deps["@treelocator/runtime"]})`
119
+ });
120
+ } else {
121
+ results.push({
122
+ name: "@treelocator/runtime",
123
+ status: "error",
124
+ message: "Not installed",
125
+ fix: getInstallCommand(info.packageManager, ["@treelocator/runtime"])
126
+ });
127
+ }
128
+ const needsBabelJsx = info.buildTool === "vite" && info.framework !== "vue" && info.framework !== "svelte";
129
+ if (needsBabelJsx) {
130
+ if (deps["@locator/babel-jsx"]) {
131
+ results.push({
132
+ name: "@locator/babel-jsx",
133
+ status: "ok",
134
+ message: `Installed (${deps["@locator/babel-jsx"]})`
135
+ });
136
+ } else {
137
+ results.push({
138
+ name: "@locator/babel-jsx",
139
+ status: "error",
140
+ message: "Not installed (required for JSX frameworks with Vite)",
141
+ fix: getInstallCommand(info.packageManager, ["@locator/babel-jsx"])
142
+ });
143
+ }
144
+ } else if (info.buildTool === "next") {
145
+ if (deps["@locator/webpack-loader"]) {
146
+ results.push({
147
+ name: "@locator/webpack-loader",
148
+ status: "ok",
149
+ message: `Installed (${deps["@locator/webpack-loader"]})`
150
+ });
151
+ } else {
152
+ results.push({
153
+ name: "@locator/webpack-loader",
154
+ status: "error",
155
+ message: "Not installed (required for Next.js)",
156
+ fix: getInstallCommand(info.packageManager, ["@locator/webpack-loader"])
157
+ });
158
+ }
159
+ }
160
+ if (info.configFile && fs.existsSync(info.configFile)) {
161
+ const configContent = fs.readFileSync(info.configFile, "utf-8");
162
+ if (needsBabelJsx) {
163
+ if (configContent.includes("@locator/babel-jsx") || configContent.includes("locator/babel-jsx")) {
164
+ results.push({
165
+ name: `${info.configFile} babel plugin`,
166
+ status: "ok",
167
+ message: "Babel plugin configured"
168
+ });
169
+ } else {
170
+ const hasBabelConfig = configContent.includes("babel:");
171
+ if (hasBabelConfig) {
172
+ results.push({
173
+ name: `${info.configFile} babel plugin`,
174
+ status: "warning",
175
+ message: "Babel config exists but @locator/babel-jsx not found",
176
+ fix: `Add ["@locator/babel-jsx/dist", { env: "development" }] to babel.plugins`
177
+ });
178
+ } else {
179
+ results.push({
180
+ name: `${info.configFile} babel plugin`,
181
+ status: "error",
182
+ message: "Babel plugin not configured",
183
+ fix: `Add babel: { plugins: [["@locator/babel-jsx/dist", { env: "development" }]] } to your framework plugin options`
184
+ });
185
+ }
186
+ }
187
+ } else if (info.buildTool === "next") {
188
+ if (configContent.includes("@locator/webpack-loader") || configContent.includes("locator/webpack-loader")) {
189
+ results.push({
190
+ name: `${info.configFile} webpack loader`,
191
+ status: "ok",
192
+ message: "Webpack loader configured"
193
+ });
194
+ } else {
195
+ results.push({
196
+ name: `${info.configFile} webpack loader`,
197
+ status: "error",
198
+ message: "Webpack loader not configured",
199
+ fix: `Add webpack config with @locator/webpack-loader to ${info.configFile}`
200
+ });
201
+ }
202
+ }
203
+ } else if (info.configFile) {
204
+ results.push({
205
+ name: `${info.configFile}`,
206
+ status: "error",
207
+ message: "Config file not found",
208
+ fix: `Create ${info.configFile}`
209
+ });
210
+ }
211
+ if (info.entryFile && fs.existsSync(info.entryFile)) {
212
+ const entryContent = fs.readFileSync(info.entryFile, "utf-8");
213
+ if (entryContent.includes("@treelocator/runtime")) {
214
+ results.push({
215
+ name: `${info.entryFile} runtime import`,
216
+ status: "ok",
217
+ message: "Runtime imported"
218
+ });
219
+ } else {
220
+ results.push({
221
+ name: `${info.entryFile} runtime import`,
222
+ status: "warning",
223
+ message: "Runtime not imported (optional but recommended)",
224
+ fix: `Add: import "@treelocator/runtime"`
225
+ });
226
+ }
227
+ }
228
+ return results;
229
+ }
230
+ function printCheckResults(results) {
231
+ let hasErrors = false;
232
+ let hasWarnings = false;
233
+ console.log(pc.bold("\nConfiguration Check Results:\n"));
234
+ for (const result of results) {
235
+ let icon;
236
+ let color;
237
+ switch (result.status) {
238
+ case "ok":
239
+ icon = "\u2713";
240
+ color = pc.green;
241
+ break;
242
+ case "warning":
243
+ icon = "\u26A0";
244
+ color = pc.yellow;
245
+ hasWarnings = true;
246
+ break;
247
+ case "error":
248
+ icon = "\u2717";
249
+ color = pc.red;
250
+ hasErrors = true;
251
+ break;
252
+ }
253
+ console.log(` ${color(icon)} ${pc.bold(result.name)}`);
254
+ console.log(` ${color(result.message)}`);
255
+ if (result.fix) {
256
+ console.log(` ${pc.dim("Fix:")} ${pc.cyan(result.fix)}`);
257
+ }
258
+ console.log();
259
+ }
260
+ if (hasErrors) {
261
+ console.log(pc.red(pc.bold("Some required configurations are missing.")));
262
+ console.log(pc.dim("Run without --check to set up TreeLocatorJS.\n"));
263
+ return false;
264
+ } else if (hasWarnings) {
265
+ console.log(pc.yellow(pc.bold("Configuration looks good with minor warnings.")));
266
+ console.log(pc.green("TreeLocatorJS should work correctly.\n"));
267
+ return true;
268
+ } else {
269
+ console.log(pc.green(pc.bold("All configurations are correct!")));
270
+ console.log(pc.green("TreeLocatorJS is properly set up.\n"));
271
+ return true;
272
+ }
273
+ }
109
274
  function updateViteConfig(configFile, framework) {
110
275
  let content = fs.readFileSync(configFile, "utf-8");
111
276
  if (content.includes("@locator/babel-jsx")) {
@@ -136,20 +301,26 @@ function updateViteConfig(configFile, framework) {
136
301
  }
137
302
  }
138
303
  if (framework === "solid") {
139
- const solidPluginRegex = /solidPlugin\(\s*\)/;
140
- const solidPluginWithOptionsRegex = /solidPlugin\(\s*\{/;
304
+ const solidPluginRegex = /solid(?:Plugin)?\(\s*\)/;
305
+ const solidPluginWithOptionsRegex = /solid(?:Plugin)?\(\s*\{/;
141
306
  if (solidPluginRegex.test(content)) {
142
307
  content = content.replace(
143
308
  solidPluginRegex,
144
- `solidPlugin({
309
+ (match) => {
310
+ const funcName = match.includes("solidPlugin") ? "solidPlugin" : "solid";
311
+ return `${funcName}({
145
312
  ${babelConfig},
146
- })`
313
+ })`;
314
+ }
147
315
  );
148
316
  } else if (solidPluginWithOptionsRegex.test(content)) {
149
317
  content = content.replace(
150
- /solidPlugin\(\s*\{/,
151
- `solidPlugin({
152
- ${babelConfig},`
318
+ /solid(?:Plugin)?\(\s*\{/,
319
+ (match) => {
320
+ const funcName = match.includes("solidPlugin") ? "solidPlugin" : "solid";
321
+ return `${funcName}({
322
+ ${babelConfig},`;
323
+ }
153
324
  );
154
325
  }
155
326
  }
@@ -255,9 +426,25 @@ export function LocatorProvider({ children }: { children: React.ReactNode }) {
255
426
  fs.writeFileSync(entryFile, content);
256
427
  console.log(pc.green(`Updated ${entryFile}`));
257
428
  }
258
- async function main() {
429
+ async function runCheck(info) {
430
+ console.log(pc.bold(pc.cyan("\n TreeLocatorJS Configuration Check\n")));
431
+ console.log(pc.dim("Detected:"));
432
+ console.log(pc.dim(` Package manager: ${info.packageManager}`));
433
+ console.log(pc.dim(` Build tool: ${info.buildTool}`));
434
+ console.log(pc.dim(` Framework: ${info.framework}`));
435
+ console.log(pc.dim(` Config file: ${info.configFile || "not found"}`));
436
+ console.log(pc.dim(` Entry file: ${info.entryFile || "not found"}`));
437
+ if (info.buildTool === "unknown") {
438
+ console.log(pc.red("\nCould not detect build tool (Vite or Next.js)."));
439
+ console.log(pc.dim("TreeLocatorJS currently supports Vite and Next.js projects."));
440
+ process.exit(1);
441
+ }
442
+ const results = checkConfiguration(info);
443
+ const isOk = printCheckResults(results);
444
+ process.exit(isOk ? 0 : 1);
445
+ }
446
+ async function runSetup(info, skipConfirm = false) {
259
447
  console.log(pc.bold(pc.cyan("\n TreeLocatorJS Setup Wizard\n")));
260
- const info = detectProject();
261
448
  console.log(pc.dim("Detected:"));
262
449
  console.log(pc.dim(` Package manager: ${info.packageManager}`));
263
450
  console.log(pc.dim(` Build tool: ${info.buildTool}`));
@@ -273,19 +460,25 @@ async function main() {
273
460
  console.log(pc.red("Could not detect framework."));
274
461
  process.exit(1);
275
462
  }
276
- const { confirm } = await prompts({
277
- type: "confirm",
278
- name: "confirm",
279
- message: "Install and configure TreeLocatorJS?",
280
- initial: true
281
- });
282
- if (!confirm) {
283
- console.log(pc.dim("Cancelled."));
284
- process.exit(0);
463
+ if (!skipConfirm) {
464
+ const { confirm } = await prompts({
465
+ type: "confirm",
466
+ name: "confirm",
467
+ message: "Install and configure TreeLocatorJS?",
468
+ initial: true
469
+ });
470
+ if (!confirm) {
471
+ console.log(pc.dim("Cancelled."));
472
+ process.exit(0);
473
+ }
474
+ } else {
475
+ console.log(pc.green("Running in non-interactive mode, proceeding with installation..."));
285
476
  }
286
477
  const packages = ["@treelocator/runtime"];
287
478
  if (info.buildTool === "vite") {
288
- packages.push("@locator/babel-jsx");
479
+ if (info.framework !== "vue" && info.framework !== "svelte") {
480
+ packages.push("@locator/babel-jsx");
481
+ }
289
482
  } else if (info.buildTool === "next") {
290
483
  packages.push("@locator/webpack-loader");
291
484
  }
@@ -299,12 +492,18 @@ Installing ${packages.join(", ")}...`));
299
492
  process.exit(1);
300
493
  }
301
494
  if (info.configFile) {
302
- console.log(pc.dim(`
495
+ const needsConfigUpdate = info.buildTool === "next" || info.buildTool === "vite" && info.framework !== "vue" && info.framework !== "svelte";
496
+ if (needsConfigUpdate) {
497
+ console.log(pc.dim(`
303
498
  Updating ${info.configFile}...`));
304
- if (info.buildTool === "vite") {
305
- updateViteConfig(info.configFile, info.framework);
306
- } else if (info.buildTool === "next") {
307
- updateNextConfig(info.configFile);
499
+ if (info.buildTool === "vite") {
500
+ updateViteConfig(info.configFile, info.framework);
501
+ } else if (info.buildTool === "next") {
502
+ updateNextConfig(info.configFile);
503
+ }
504
+ } else {
505
+ console.log(pc.dim(`
506
+ No config update needed for ${info.framework} (uses built-in source tracking)`));
308
507
  }
309
508
  }
310
509
  if (info.entryFile) {
@@ -316,4 +515,41 @@ Updating ${info.entryFile}...`));
316
515
  console.log(pc.bold(pc.green("\nTreeLocatorJS installed successfully!")));
317
516
  console.log(pc.dim("\nUsage: Hold Alt and click any component to copy its ancestry.\n"));
318
517
  }
518
+ async function main() {
519
+ const args = process.argv.slice(2);
520
+ const isCheck = args.includes("--check") || args.includes("-c") || args.includes("check");
521
+ const isHelp = args.includes("--help") || args.includes("-h") || args.includes("help");
522
+ const isYes = args.includes("--yes") || args.includes("-y") || process.env.TREELOCATOR_AUTO_CONFIRM === "1";
523
+ if (isHelp) {
524
+ console.log(`
525
+ ${pc.bold(pc.cyan("TreeLocatorJS Setup"))}
526
+
527
+ ${pc.bold("Usage:")}
528
+ npx @treelocator/init Install and configure TreeLocatorJS
529
+ npx @treelocator/init check Check if configuration is correct
530
+ npx @treelocator/init --help Show this help message
531
+
532
+ ${pc.bold("Options:")}
533
+ --check, -c, check Verify existing configuration without making changes
534
+ --yes, -y Skip confirmation prompt (non-interactive mode)
535
+ --help, -h, help Show this help message
536
+
537
+ ${pc.bold("Environment Variables:")}
538
+ TREELOCATOR_AUTO_CONFIRM=1 Skip confirmation prompt (same as --yes)
539
+
540
+ ${pc.bold("What it checks:")}
541
+ \u2022 @treelocator/runtime package is installed
542
+ \u2022 @locator/babel-jsx (Vite) or @locator/webpack-loader (Next.js) is installed
543
+ \u2022 Build config has the babel plugin / webpack loader configured
544
+ \u2022 Entry file imports the runtime (optional)
545
+ `);
546
+ process.exit(0);
547
+ }
548
+ const info = detectProject();
549
+ if (isCheck) {
550
+ await runCheck(info);
551
+ } else {
552
+ await runSetup(info, isYes);
553
+ }
554
+ }
319
555
  main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treelocator/init",
3
- "version": "0.1.8",
3
+ "version": "0.2.1",
4
4
  "description": "Setup wizard for TreeLocatorJS - auto-configure component ancestry tracking",
5
5
  "bin": {
6
6
  "treelocatorjs": "./dist/index.js",
@@ -48,5 +48,5 @@
48
48
  "component-ancestry"
49
49
  ],
50
50
  "license": "MIT",
51
- "gitHead": "69fb05167bd689b2e3602fcbc74a70912695f136"
51
+ "gitHead": "afc8a534284e818665bb4d03b7fa940ec5ad5880"
52
52
  }
package/LICENSE DELETED
@@ -1,22 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Krzysztof Wende
4
- Copyright (c) 2023 Michael Musil (original LocatorJS)
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in all
14
- copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
- SOFTWARE.