stackscan 0.1.17 → 0.1.19

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 (39) hide show
  1. package/dist/chunk-2R4IRVBW.mjs +19 -0
  2. package/dist/chunk-3JWM3QKI.mjs +2013 -0
  3. package/dist/chunk-5XOMETBV.mjs +158 -0
  4. package/dist/chunk-75Z7C4SW.mjs +19 -0
  5. package/dist/chunk-AU42WGBI.mjs +158 -0
  6. package/dist/chunk-BPDLELPJ.mjs +235 -0
  7. package/dist/chunk-JFE6WNCW.mjs +235 -0
  8. package/dist/chunk-MEH6MW3S.mjs +235 -0
  9. package/dist/chunk-NWUJIUCE.mjs +2028 -0
  10. package/dist/chunk-OX7SYHLD.mjs +235 -0
  11. package/dist/chunk-QNTMPVPN.mjs +19 -0
  12. package/dist/chunk-RRAAD3VC.mjs +2075 -0
  13. package/dist/chunk-TEUMOU3M.mjs +158 -0
  14. package/dist/cli.js +224 -95
  15. package/dist/cli.mjs +7 -5
  16. package/dist/index.js +220 -93
  17. package/dist/index.mjs +4 -4
  18. package/dist/scan.d.mts +2 -1
  19. package/dist/scan.d.ts +2 -1
  20. package/dist/scan.js +220 -93
  21. package/dist/scan.mjs +3 -3
  22. package/dist/scan.old.d.mts +8 -0
  23. package/dist/scan.old.d.ts +8 -0
  24. package/dist/scan.old.js +5770 -0
  25. package/dist/scan.old.mjs +205 -0
  26. package/dist/sync.js +129 -34
  27. package/dist/sync.mjs +3 -3
  28. package/dist/techDefinitions.js +129 -34
  29. package/dist/techDefinitions.mjs +1 -1
  30. package/dist/techMap.js +129 -34
  31. package/dist/techMap.mjs +2 -2
  32. package/package.json +1 -1
  33. package/public/assets/logos/backend/convex.svg +5 -0
  34. package/public/assets/logos/backend/springboot.svg +1 -0
  35. package/public/assets/logos/css/shadcn.svg +6 -0
  36. package/public/assets/logos/defaults/package.svg +18 -0
  37. package/public/assets/logos/language/css3.svg +6 -0
  38. package/public/assets/logos/language/html5.svg +6 -0
  39. package/public/assets/logos/language/typescript.svg +1 -1
package/dist/cli.mjs CHANGED
@@ -4,9 +4,9 @@ import {
4
4
  } from "./chunk-ACCTMJVS.mjs";
5
5
  import {
6
6
  scan
7
- } from "./chunk-PL2BQ6GK.mjs";
8
- import "./chunk-LSUI3VI4.mjs";
9
- import "./chunk-LB3L25FS.mjs";
7
+ } from "./chunk-JFE6WNCW.mjs";
8
+ import "./chunk-2R4IRVBW.mjs";
9
+ import "./chunk-RRAAD3VC.mjs";
10
10
  import "./chunk-UJM3S22V.mjs";
11
11
  import "./chunk-NGEKE4DQ.mjs";
12
12
  import "./chunk-EOKQCSHI.mjs";
@@ -16,8 +16,10 @@ import "./chunk-EH2SEQZP.mjs";
16
16
  import { Command } from "commander";
17
17
  var program = new Command();
18
18
  program.name("stackscan").description("Auto-detect tech stacks and generate tech.json or markdown.").version("0.1.0");
19
- program.command("scan", { isDefault: true }).description("Scan stacks from multiple projects in public/stackscan/").option("--color <mode>", "Color mode (brand, white, black, or hex)", "brand").option("--no-readme", "Do not update the root README.md").action(async (options) => {
20
- await scan(options);
19
+ program.command("scan [path]", { isDefault: true }).description("Scan stacks from multiple projects in public/stackscan/ or a specific project path").option("--color <mode>", "Color mode (brand, white, black, or hex)", "brand").option("--no-readme", "Do not update the root README.md").option("--out <file>", "Output JSON file (only for single project scan)").action(async (path, options) => {
20
+ let targetPath = typeof path === "string" ? path : void 0;
21
+ let opts = typeof path === "object" ? path : options;
22
+ await scan(targetPath, opts);
21
23
  });
22
24
  program.command("add <path>").description("Add a project (folder or package.json) to the public/stackscan workspace").action(async (path) => {
23
25
  await add(path);
package/dist/index.js CHANGED
@@ -3794,7 +3794,10 @@ var techDefinitions = [
3794
3794
  "id": "remix",
3795
3795
  "name": "Remix",
3796
3796
  "aliases": [
3797
- "remix"
3797
+ "remix",
3798
+ "@remix-run/react",
3799
+ "@remix-run/node",
3800
+ "@remix-run/serve"
3798
3801
  ],
3799
3802
  "category": "frontend",
3800
3803
  "logo": "frontend/remix.svg",
@@ -3874,7 +3877,10 @@ var techDefinitions = [
3874
3877
  "id": "angular",
3875
3878
  "name": "Angular",
3876
3879
  "aliases": [
3877
- "@angular/core"
3880
+ "@angular/core",
3881
+ "@angular/common",
3882
+ "@angular/platform-browser",
3883
+ "@angular/cli"
3878
3884
  ],
3879
3885
  "category": "frontend",
3880
3886
  "logo": "frontend/angular.svg",
@@ -3884,7 +3890,9 @@ var techDefinitions = [
3884
3890
  "id": "lit",
3885
3891
  "name": "Lit",
3886
3892
  "aliases": [
3887
- "lit"
3893
+ "lit",
3894
+ "lit-element",
3895
+ "lit-html"
3888
3896
  ],
3889
3897
  "category": "frontend",
3890
3898
  "logo": "frontend/lit.svg",
@@ -3904,7 +3912,8 @@ var techDefinitions = [
3904
3912
  "id": "ember",
3905
3913
  "name": "Ember",
3906
3914
  "aliases": [
3907
- "ember-source"
3915
+ "ember-source",
3916
+ "ember-cli"
3908
3917
  ],
3909
3918
  "category": "frontend",
3910
3919
  "logo": "frontend/emberdotjs.svg",
@@ -4004,22 +4013,14 @@ var techDefinitions = [
4004
4013
  "id": "mantine",
4005
4014
  "name": "Mantine",
4006
4015
  "aliases": [
4007
- "@mantine/core"
4016
+ "@mantine/core",
4017
+ "@mantine/hooks",
4018
+ "@mantine/form"
4008
4019
  ],
4009
4020
  "category": "css",
4010
4021
  "logo": "fallback/mantine-logo.svg",
4011
4022
  "frameworks": []
4012
4023
  },
4013
- {
4014
- "id": "shadcnui",
4015
- "name": "shadcn/ui",
4016
- "aliases": [
4017
- "shadcn"
4018
- ],
4019
- "category": "css",
4020
- "logo": "css/shadcnui.svg",
4021
- "frameworks": []
4022
- },
4023
4024
  {
4024
4025
  "id": "daisyui",
4025
4026
  "name": "DaisyUI",
@@ -4054,7 +4055,8 @@ var techDefinitions = [
4054
4055
  "id": "headlessui",
4055
4056
  "name": "Headless UI",
4056
4057
  "aliases": [
4057
- "@headlessui/react"
4058
+ "@headlessui/react",
4059
+ "@headlessui/vue"
4058
4060
  ],
4059
4061
  "category": "css",
4060
4062
  "logo": "css/headlessui.svg",
@@ -4064,7 +4066,9 @@ var techDefinitions = [
4064
4066
  "id": "emotion",
4065
4067
  "name": "Emotion",
4066
4068
  "aliases": [
4067
- "@emotion/react"
4069
+ "@emotion/react",
4070
+ "@emotion/styled",
4071
+ "@emotion/css"
4068
4072
  ],
4069
4073
  "category": "css",
4070
4074
  "logo": "css/emotion.svg",
@@ -4124,7 +4128,9 @@ var techDefinitions = [
4124
4128
  "id": "redux",
4125
4129
  "name": "Redux",
4126
4130
  "aliases": [
4127
- "redux"
4131
+ "redux",
4132
+ "react-redux",
4133
+ "@reduxjs/toolkit"
4128
4134
  ],
4129
4135
  "category": "state",
4130
4136
  "logo": "state/redux.svg",
@@ -4134,7 +4140,9 @@ var techDefinitions = [
4134
4140
  "id": "mobx",
4135
4141
  "name": "MobX",
4136
4142
  "aliases": [
4137
- "mobx"
4143
+ "mobx",
4144
+ "mobx-react",
4145
+ "mobx-react-lite"
4138
4146
  ],
4139
4147
  "category": "state",
4140
4148
  "logo": "state/mobx.svg",
@@ -4174,7 +4182,9 @@ var techDefinitions = [
4174
4182
  "id": "xstate",
4175
4183
  "name": "XState",
4176
4184
  "aliases": [
4177
- "xstate"
4185
+ "xstate",
4186
+ "@xstate/react",
4187
+ "@xstate/fsm"
4178
4188
  ],
4179
4189
  "category": "state",
4180
4190
  "logo": "state/xstate.svg",
@@ -4184,7 +4194,10 @@ var techDefinitions = [
4184
4194
  "id": "tanstackquery",
4185
4195
  "name": "TanStack Query",
4186
4196
  "aliases": [
4187
- "@tanstack/react-query"
4197
+ "@tanstack/react-query",
4198
+ "@tanstack/vue-query",
4199
+ "@tanstack/svelte-query",
4200
+ "react-query"
4188
4201
  ],
4189
4202
  "category": "state",
4190
4203
  "logo": "fallback/reactquery.svg",
@@ -4394,7 +4407,11 @@ var techDefinitions = [
4394
4407
  "id": "storybook",
4395
4408
  "name": "Storybook",
4396
4409
  "aliases": [
4397
- "@storybook/react"
4410
+ "storybook",
4411
+ "@storybook/react",
4412
+ "@storybook/vue",
4413
+ "@storybook/angular",
4414
+ "@storybook/addon-essentials"
4398
4415
  ],
4399
4416
  "category": "testing",
4400
4417
  "logo": "testing/storybook.svg",
@@ -4574,7 +4591,8 @@ var techDefinitions = [
4574
4591
  "id": "prisma",
4575
4592
  "name": "Prisma",
4576
4593
  "aliases": [
4577
- "prisma"
4594
+ "prisma",
4595
+ "@prisma/client"
4578
4596
  ],
4579
4597
  "category": "orm",
4580
4598
  "logo": "orm/prisma.svg",
@@ -4614,7 +4632,9 @@ var techDefinitions = [
4614
4632
  "id": "postgresql",
4615
4633
  "name": "PostgreSQL",
4616
4634
  "aliases": [
4617
- "pg"
4635
+ "pg",
4636
+ "pg-promise",
4637
+ "node-postgres"
4618
4638
  ],
4619
4639
  "category": "database",
4620
4640
  "logo": "database/postgresql.svg",
@@ -4645,7 +4665,8 @@ var techDefinitions = [
4645
4665
  "id": "sqlite",
4646
4666
  "name": "SQLite",
4647
4667
  "aliases": [
4648
- "sqlite3"
4668
+ "sqlite3",
4669
+ "better-sqlite3"
4649
4670
  ],
4650
4671
  "category": "database",
4651
4672
  "logo": "database/sqlite.svg",
@@ -4665,7 +4686,9 @@ var techDefinitions = [
4665
4686
  "id": "redis",
4666
4687
  "name": "Redis",
4667
4688
  "aliases": [
4668
- "redis"
4689
+ "redis",
4690
+ "ioredis",
4691
+ "@redis/client"
4669
4692
  ],
4670
4693
  "category": "database",
4671
4694
  "logo": "database/redis.svg",
@@ -4845,7 +4868,11 @@ var techDefinitions = [
4845
4868
  "id": "auth0",
4846
4869
  "name": "Auth0",
4847
4870
  "aliases": [
4848
- "auth0"
4871
+ "auth0",
4872
+ "auth0-js",
4873
+ "@auth0/auth0-react",
4874
+ "@auth0/auth0-vue",
4875
+ "@auth0/auth0-angular"
4849
4876
  ],
4850
4877
  "category": "auth",
4851
4878
  "logo": "auth/auth0.svg",
@@ -4855,7 +4882,9 @@ var techDefinitions = [
4855
4882
  "id": "clerk",
4856
4883
  "name": "Clerk",
4857
4884
  "aliases": [
4858
- "@clerk/nextjs"
4885
+ "@clerk/nextjs",
4886
+ "@clerk/clerk-react",
4887
+ "@clerk/clerk-sdk-node"
4859
4888
  ],
4860
4889
  "category": "auth",
4861
4890
  "logo": "auth/clerk.svg",
@@ -4865,7 +4894,9 @@ var techDefinitions = [
4865
4894
  "id": "supabaseauth",
4866
4895
  "name": "Supabase Auth",
4867
4896
  "aliases": [
4868
- "@supabase/auth-helpers-nextjs"
4897
+ "@supabase/auth-helpers-nextjs",
4898
+ "@supabase/auth-helpers-react",
4899
+ "@supabase/ssr"
4869
4900
  ],
4870
4901
  "category": "auth",
4871
4902
  "logo": "database/supabase.svg",
@@ -4875,7 +4906,10 @@ var techDefinitions = [
4875
4906
  "id": "firebaseauth",
4876
4907
  "name": "Firebase Auth",
4877
4908
  "aliases": [
4878
- "firebase"
4909
+ "firebase",
4910
+ "firebase-admin",
4911
+ "@firebase/app",
4912
+ "@firebase/auth"
4879
4913
  ],
4880
4914
  "category": "auth",
4881
4915
  "logo": "auth/firebase.svg",
@@ -4957,7 +4991,9 @@ var techDefinitions = [
4957
4991
  "id": "langchain",
4958
4992
  "name": "LangChain",
4959
4993
  "aliases": [
4960
- "langchain"
4994
+ "langchain",
4995
+ "@langchain/core",
4996
+ "@langchain/openai"
4961
4997
  ],
4962
4998
  "category": "ai",
4963
4999
  "logo": "ai/langchain.svg",
@@ -5137,7 +5173,10 @@ var techDefinitions = [
5137
5173
  "id": "aws",
5138
5174
  "name": "AWS",
5139
5175
  "aliases": [
5140
- "aws-sdk"
5176
+ "aws-sdk",
5177
+ "@aws-sdk/client-s3",
5178
+ "@aws-sdk/client-dynamodb",
5179
+ "@aws-sdk/client-lambda"
5141
5180
  ],
5142
5181
  "category": "cloud",
5143
5182
  "logo": "cloud/amazonwebservices.svg",
@@ -5357,7 +5396,8 @@ var techDefinitions = [
5357
5396
  "id": "shopify",
5358
5397
  "name": "Shopify",
5359
5398
  "aliases": [
5360
- "@shopify/shopify-api"
5399
+ "@shopify/shopify-api",
5400
+ "shopify"
5361
5401
  ],
5362
5402
  "category": "cms",
5363
5403
  "logo": "cms/shopify.svg",
@@ -5617,7 +5657,9 @@ var techDefinitions = [
5617
5657
  "id": "stripe",
5618
5658
  "name": "Stripe",
5619
5659
  "aliases": [
5620
- "stripe"
5660
+ "stripe",
5661
+ "@stripe/stripe-js",
5662
+ "@stripe/react-stripe-js"
5621
5663
  ],
5622
5664
  "category": "payment",
5623
5665
  "logo": "payment/stripe.svg",
@@ -5642,6 +5684,59 @@ var techDefinitions = [
5642
5684
  "category": "payment",
5643
5685
  "logo": "fallback/lemonsqueezy.svg",
5644
5686
  "frameworks": []
5687
+ },
5688
+ {
5689
+ "id": "css",
5690
+ "name": "CSS",
5691
+ "aliases": [
5692
+ "css"
5693
+ ],
5694
+ "category": "language",
5695
+ "logo": "language/css3.svg",
5696
+ "frameworks": []
5697
+ },
5698
+ {
5699
+ "id": "html",
5700
+ "name": "HTML",
5701
+ "aliases": [
5702
+ "html"
5703
+ ],
5704
+ "category": "language",
5705
+ "logo": "language/html5.svg",
5706
+ "frameworks": []
5707
+ },
5708
+ {
5709
+ "id": "convex",
5710
+ "name": "Convex",
5711
+ "aliases": [
5712
+ "convex",
5713
+ "convex-dev"
5714
+ ],
5715
+ "category": "backend",
5716
+ "logo": "backend/convex.svg",
5717
+ "frameworks": []
5718
+ },
5719
+ {
5720
+ "id": "shadcn",
5721
+ "name": "shadcn/ui",
5722
+ "aliases": [
5723
+ "shadcn",
5724
+ "shadcn-ui",
5725
+ "shadcn/ui"
5726
+ ],
5727
+ "category": "css",
5728
+ "logo": "css/shadcn.svg",
5729
+ "frameworks": []
5730
+ },
5731
+ {
5732
+ "id": "springboot",
5733
+ "name": "Spring Boot",
5734
+ "aliases": [
5735
+ "spring-boot"
5736
+ ],
5737
+ "category": "backend",
5738
+ "logo": "backend/springboot.svg",
5739
+ "frameworks": []
5645
5740
  }
5646
5741
  ];
5647
5742
 
@@ -5697,12 +5792,99 @@ var getCategoryPriority = (cat) => {
5697
5792
  const idx = CATEGORY_PRIORITY.indexOf(cat ? cat.toLowerCase() : "");
5698
5793
  return idx === -1 ? 999 : idx;
5699
5794
  };
5700
- async function scan(options = {}) {
5795
+ async function analyzeProject(projectPath, options) {
5796
+ const packageJsonPath = import_path3.default.join(projectPath, "package.json");
5797
+ if (!import_fs.default.existsSync(packageJsonPath)) {
5798
+ throw new Error(`No package.json found at ${packageJsonPath}`);
5799
+ }
5800
+ const content = import_fs.default.readFileSync(packageJsonPath, "utf-8");
5801
+ const pkg = JSON.parse(content);
5802
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
5803
+ const detectedTechs = [];
5804
+ Object.keys(allDeps).forEach((dep) => {
5805
+ if (SKIPPED_TECHS.includes(dep)) return;
5806
+ if (techMap[dep]) {
5807
+ const tech = techMap[dep];
5808
+ let color = null;
5809
+ if (options.color === "white") color = "#FFFFFF";
5810
+ else if (options.color === "black") color = "#000000";
5811
+ else if (options.color && options.color.startsWith("#")) color = options.color;
5812
+ else {
5813
+ const depSlug = dep.toLowerCase();
5814
+ const nameSlug = tech.name.toLowerCase();
5815
+ const nameSlugNoSpaces = tech.name.toLowerCase().replace(/\s+/g, "");
5816
+ const hex = simple_icons_hex_default[depSlug] || simple_icons_hex_default[nameSlug] || simple_icons_hex_default[nameSlugNoSpaces];
5817
+ if (hex) color = `#${hex}`;
5818
+ }
5819
+ detectedTechs.push({
5820
+ name: tech.name,
5821
+ slug: dep,
5822
+ logo: tech.logo,
5823
+ type: tech.type,
5824
+ color
5825
+ });
5826
+ }
5827
+ });
5828
+ const uniqueSlugs = Array.from(new Set(detectedTechs.map((t) => t.slug)));
5829
+ let uniqueTechs = uniqueSlugs.map((slug) => detectedTechs.find((t) => t.slug === slug));
5830
+ const seenLogos = /* @__PURE__ */ new Set();
5831
+ uniqueTechs = uniqueTechs.filter((t) => {
5832
+ if (seenLogos.has(t.logo)) {
5833
+ return false;
5834
+ }
5835
+ seenLogos.add(t.logo);
5836
+ return true;
5837
+ });
5838
+ uniqueTechs.sort((a, b) => {
5839
+ const pA = getCategoryPriority(a.type);
5840
+ const pB = getCategoryPriority(b.type);
5841
+ if (pA !== pB) return pA - pB;
5842
+ return a.name.localeCompare(b.name);
5843
+ });
5844
+ const assetsDir = import_path3.default.join(process.cwd(), "public", "assets", "logos");
5845
+ if (options.copyAssets !== false) {
5846
+ await copyAssets(uniqueTechs, assetsDir, { colorMode: options.color });
5847
+ }
5848
+ return uniqueTechs.map((t) => ({
5849
+ ...t,
5850
+ logo: `https://raw.githubusercontent.com/benjamindotdev/stackscan/main/public/assets/logos/${t.logo}`,
5851
+ relativePath: `./public/assets/logos/${t.logo}`
5852
+ }));
5853
+ }
5854
+ async function scan(targetPath, optionsOrUndefined) {
5855
+ let options = {};
5856
+ let pathArg = void 0;
5857
+ if (typeof targetPath === "string") {
5858
+ pathArg = targetPath;
5859
+ options = optionsOrUndefined || {};
5860
+ } else if (typeof targetPath === "object") {
5861
+ options = targetPath;
5862
+ }
5701
5863
  if (options.readme === void 0) options.readme = true;
5702
5864
  console.log("\u{1F680} Starting Scan...");
5703
5865
  if (options.color) {
5704
5866
  console.log(`\u{1F3A8} Color mode: ${options.color}`);
5705
5867
  }
5868
+ if (pathArg) {
5869
+ const absPath = import_path3.default.resolve(pathArg);
5870
+ console.log(`Scanning single project at: ${absPath}`);
5871
+ try {
5872
+ const techsWithUrls = await analyzeProject(absPath, options);
5873
+ if (options.out) {
5874
+ const outPath = import_path3.default.resolve(options.out);
5875
+ import_fs.default.writeFileSync(outPath, JSON.stringify(techsWithUrls, null, 2));
5876
+ console.log(`\u2705 Generated stack output to: ${options.out}`);
5877
+ } else {
5878
+ const outPath = import_path3.default.join(absPath, "stack.json");
5879
+ import_fs.default.writeFileSync(outPath, JSON.stringify(techsWithUrls, null, 2));
5880
+ console.log(`\u2705 Generated stack.json at: ${outPath}`);
5881
+ }
5882
+ } catch (err) {
5883
+ console.error(`\u274C Error scanning project:`, err.message);
5884
+ process.exit(1);
5885
+ }
5886
+ return;
5887
+ }
5706
5888
  if (!import_fs.default.existsSync(BASE_DIR2)) {
5707
5889
  console.log(`Creating stackscan directory at: ${BASE_DIR2}`);
5708
5890
  import_fs.default.mkdirSync(BASE_DIR2, { recursive: true });
@@ -5718,66 +5900,11 @@ async function scan(options = {}) {
5718
5900
  console.log(`Found ${projectDirs.length} projects to process.
5719
5901
  `);
5720
5902
  const allProjects = [];
5721
- const allTechs = [];
5722
5903
  for (const dir of projectDirs) {
5723
5904
  const projectPath = import_path3.default.join(BASE_DIR2, dir.name);
5724
- const packageJsonPath = import_path3.default.join(projectPath, "package.json");
5725
- if (import_fs.default.existsSync(packageJsonPath)) {
5905
+ if (import_fs.default.existsSync(import_path3.default.join(projectPath, "package.json"))) {
5726
5906
  try {
5727
- const content = import_fs.default.readFileSync(packageJsonPath, "utf-8");
5728
- const pkg = JSON.parse(content);
5729
- const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
5730
- const detectedTechs = [];
5731
- Object.keys(allDeps).forEach((dep) => {
5732
- if (SKIPPED_TECHS.includes(dep)) return;
5733
- if (techMap[dep]) {
5734
- const tech = techMap[dep];
5735
- let color = null;
5736
- if (options.color === "white") color = "#FFFFFF";
5737
- else if (options.color === "black") color = "#000000";
5738
- else if (options.color && options.color.startsWith("#")) color = options.color;
5739
- else {
5740
- const depSlug = dep.toLowerCase();
5741
- const nameSlug = tech.name.toLowerCase();
5742
- const nameSlugNoSpaces = tech.name.toLowerCase().replace(/\s+/g, "");
5743
- const hex = simple_icons_hex_default[depSlug] || simple_icons_hex_default[nameSlug] || simple_icons_hex_default[nameSlugNoSpaces];
5744
- if (hex) color = `#${hex}`;
5745
- }
5746
- detectedTechs.push({
5747
- name: tech.name,
5748
- slug: dep,
5749
- logo: tech.logo,
5750
- // Raw path for resolution
5751
- type: tech.type,
5752
- color
5753
- });
5754
- }
5755
- });
5756
- let uniqueTechs = Array.from(new Set(detectedTechs.map((t) => t.slug))).map((slug) => detectedTechs.find((t) => t.slug === slug));
5757
- const seenLogos = /* @__PURE__ */ new Set();
5758
- uniqueTechs = uniqueTechs.filter((t) => {
5759
- if (seenLogos.has(t.logo)) {
5760
- return false;
5761
- }
5762
- seenLogos.add(t.logo);
5763
- return true;
5764
- });
5765
- uniqueTechs.sort((a, b) => {
5766
- const pA = getCategoryPriority(a.type);
5767
- const pB = getCategoryPriority(b.type);
5768
- if (pA !== pB) return pA - pB;
5769
- return a.name.localeCompare(b.name);
5770
- });
5771
- const assetsDir = import_path3.default.join(process.cwd(), "public", "assets", "logos");
5772
- if (options.copyAssets !== false) {
5773
- await copyAssets(uniqueTechs, assetsDir, { colorMode: options.color });
5774
- }
5775
- const techsWithUrls = uniqueTechs.map((t) => ({
5776
- ...t,
5777
- logo: `https://raw.githubusercontent.com/benjamindotdev/stackscan/main/public/assets/logos/${t.logo}`,
5778
- relativePath: `./public/assets/logos/${t.logo}`
5779
- }));
5780
- allTechs.push(...techsWithUrls);
5907
+ const techsWithUrls = await analyzeProject(projectPath, options);
5781
5908
  import_fs.default.writeFileSync(
5782
5909
  import_path3.default.join(projectPath, "stack.json"),
5783
5910
  JSON.stringify(techsWithUrls, null, 2)
@@ -5788,7 +5915,7 @@ async function scan(options = {}) {
5788
5915
  name: dir.name,
5789
5916
  techs: techsWithUrls
5790
5917
  });
5791
- console.log(`\u2705 ${dir.name.padEnd(20)} -> stack.json (${uniqueTechs.length} techs)`);
5918
+ console.log(`\u2705 ${dir.name.padEnd(20)} -> stack.json (${techsWithUrls.length} techs)`);
5792
5919
  } catch (err) {
5793
5920
  console.error(`\u274C Error processing ${dir.name}:`, err.message);
5794
5921
  }
package/dist/index.mjs CHANGED
@@ -4,16 +4,16 @@ import {
4
4
  } from "./chunk-ACCTMJVS.mjs";
5
5
  import {
6
6
  scan
7
- } from "./chunk-PL2BQ6GK.mjs";
7
+ } from "./chunk-JFE6WNCW.mjs";
8
8
  import {
9
9
  sync
10
- } from "./chunk-XS2LU2MN.mjs";
10
+ } from "./chunk-5XOMETBV.mjs";
11
11
  import {
12
12
  techMap
13
- } from "./chunk-LSUI3VI4.mjs";
13
+ } from "./chunk-2R4IRVBW.mjs";
14
14
  import {
15
15
  techDefinitions
16
- } from "./chunk-LB3L25FS.mjs";
16
+ } from "./chunk-RRAAD3VC.mjs";
17
17
  import {
18
18
  copyAssets,
19
19
  generateMarkdown,
package/dist/scan.d.mts CHANGED
@@ -2,7 +2,8 @@ interface SyncOptions {
2
2
  color?: string;
3
3
  copyAssets?: boolean;
4
4
  readme?: boolean;
5
+ out?: string;
5
6
  }
6
- declare function scan(options?: SyncOptions): Promise<void>;
7
+ declare function scan(targetPath?: string | object, optionsOrUndefined?: SyncOptions): Promise<void>;
7
8
 
8
9
  export { scan };
package/dist/scan.d.ts CHANGED
@@ -2,7 +2,8 @@ interface SyncOptions {
2
2
  color?: string;
3
3
  copyAssets?: boolean;
4
4
  readme?: boolean;
5
+ out?: string;
5
6
  }
6
- declare function scan(options?: SyncOptions): Promise<void>;
7
+ declare function scan(targetPath?: string | object, optionsOrUndefined?: SyncOptions): Promise<void>;
7
8
 
8
9
  export { scan };