@tydung26/product-kit 1.4.0 → 1.5.0

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 (30) hide show
  1. package/dist/scripts/market-intel/search-app-store.d.ts +7 -0
  2. package/dist/scripts/market-intel/search-app-store.d.ts.map +1 -0
  3. package/dist/scripts/market-intel/search-app-store.js +91 -0
  4. package/dist/scripts/market-intel/search-app-store.js.map +1 -0
  5. package/dist/scripts/market-intel/search-google-play.d.ts +7 -0
  6. package/dist/scripts/market-intel/search-google-play.d.ts.map +1 -0
  7. package/dist/scripts/market-intel/search-google-play.js +195 -0
  8. package/dist/scripts/market-intel/search-google-play.js.map +1 -0
  9. package/dist/scripts/market-intel/search-product-hunt.d.ts +7 -0
  10. package/dist/scripts/market-intel/search-product-hunt.d.ts.map +1 -0
  11. package/dist/scripts/market-intel/search-product-hunt.js +236 -0
  12. package/dist/scripts/market-intel/search-product-hunt.js.map +1 -0
  13. package/dist/scripts/market-intel/search-yc-launch.d.ts +7 -0
  14. package/dist/scripts/market-intel/search-yc-launch.d.ts.map +1 -0
  15. package/dist/scripts/market-intel/search-yc-launch.js +229 -0
  16. package/dist/scripts/market-intel/search-yc-launch.js.map +1 -0
  17. package/dist/scripts/market-intel/shared-types.d.ts +44 -0
  18. package/dist/scripts/market-intel/shared-types.d.ts.map +1 -0
  19. package/dist/scripts/market-intel/shared-types.js +63 -0
  20. package/dist/scripts/market-intel/shared-types.js.map +1 -0
  21. package/package.json +8 -9
  22. package/skills/market-intel/SKILL.md +184 -61
  23. package/skills/market-intel/scripts/search-app-store.py +117 -0
  24. package/skills/market-intel/scripts/search-google-play.py +179 -0
  25. package/skills/market-intel/scripts/search-product-hunt.py +194 -0
  26. package/skills/market-intel/scripts/search-yc-launch.py +160 -0
  27. package/dist/commands/config/index.d.ts +0 -3
  28. package/dist/commands/config/index.d.ts.map +0 -1
  29. package/dist/commands/config/index.js +0 -34
  30. package/dist/commands/config/index.js.map +0 -1
@@ -0,0 +1,7 @@
1
+ /**
2
+ * App Store crawler via iTunes Search API.
3
+ * Usage: node search-app-store.mjs "<keywords>" [limit]
4
+ * Output: JSON CrawlResult to stdout
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=search-app-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-app-store.d.ts","sourceRoot":"","sources":["../../../src/scripts/market-intel/search-app-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ /**
3
+ * App Store crawler via iTunes Search API.
4
+ * Usage: node search-app-store.mjs "<keywords>" [limit]
5
+ * Output: JSON CrawlResult to stdout
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ const shared_types_js_1 = require("./shared-types.js");
9
+ async function fetchReviews(trackId) {
10
+ try {
11
+ const url = `https://itunes.apple.com/rss/customerreviews/id=${trackId}/sortBy=mostRecent/json`;
12
+ const res = await (0, shared_types_js_1.safeFetch)(url);
13
+ if (!res.ok)
14
+ return [];
15
+ const data = await res.json();
16
+ const entries = data?.feed?.entry || [];
17
+ // first entry is often metadata, skip it
18
+ return entries
19
+ .filter((e) => e.content?.label && e["im:rating"]?.label)
20
+ .slice(0, 6)
21
+ .map((e) => {
22
+ const rating = parseInt(e["im:rating"].label, 10);
23
+ return {
24
+ text: (0, shared_types_js_1.truncate)(e.content.label, 300),
25
+ rating,
26
+ sentiment: rating >= 4 ? "positive" : rating <= 2 ? "negative" : "neutral",
27
+ };
28
+ });
29
+ }
30
+ catch {
31
+ return [];
32
+ }
33
+ }
34
+ /** Parse pricing from iTunes price + formattedPrice fields */
35
+ function parsePricing(app) {
36
+ const isFree = app.price === 0;
37
+ return {
38
+ free: isFree,
39
+ monthly: undefined,
40
+ yearly: undefined,
41
+ other: isFree ? undefined : app.formattedPrice,
42
+ };
43
+ }
44
+ async function main() {
45
+ const { query, limit } = (0, shared_types_js_1.parseArgs)();
46
+ const errors = [];
47
+ // Search iTunes API
48
+ const searchUrl = `https://itunes.apple.com/search?term=${encodeURIComponent(query)}&entity=software&limit=${limit}&country=us`;
49
+ let searchData;
50
+ try {
51
+ const res = await (0, shared_types_js_1.safeFetch)(searchUrl);
52
+ if (!res.ok) {
53
+ return (0, shared_types_js_1.outputError)("app_store", query, `iTunes API returned ${res.status}`);
54
+ }
55
+ searchData = await res.json();
56
+ }
57
+ catch (err) {
58
+ return (0, shared_types_js_1.outputError)("app_store", query, `Failed to fetch iTunes API: ${err instanceof Error ? err.message : String(err)}`);
59
+ }
60
+ if (!searchData.results?.length) {
61
+ return (0, shared_types_js_1.outputError)("app_store", query, "No results found");
62
+ }
63
+ // Process each app
64
+ const results = [];
65
+ for (const app of searchData.results) {
66
+ const reviews = await fetchReviews(app.trackId);
67
+ results.push({
68
+ name: app.trackName,
69
+ url: app.trackViewUrl,
70
+ description: (0, shared_types_js_1.truncate)(app.description),
71
+ tagline: undefined,
72
+ rating: app.averageUserRating
73
+ ? Math.round(app.averageUserRating * 10) / 10
74
+ : undefined,
75
+ reviewCount: app.userRatingCount,
76
+ pricing: parsePricing(app),
77
+ features: [], // iTunes API doesn't expose feature lists
78
+ reviews,
79
+ });
80
+ }
81
+ const result = {
82
+ platform: "app_store",
83
+ query,
84
+ timestamp: new Date().toISOString(),
85
+ results,
86
+ errors,
87
+ };
88
+ (0, shared_types_js_1.outputResult)(result);
89
+ }
90
+ main();
91
+ //# sourceMappingURL=search-app-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-app-store.js","sourceRoot":"","sources":["../../../src/scripts/market-intel/search-app-store.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAEH,uDAS2B;AAqB3B,KAAK,UAAU,YAAY,CAAC,OAAe;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,mDAAmD,OAAO,yBAAyB,CAAC;QAChG,MAAM,GAAG,GAAG,MAAM,IAAA,2BAAS,EAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAmB,IAAI,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;QACxD,yCAAyC;QACzC,OAAO,OAAO;aACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC;aACxD,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACT,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAClD,OAAO;gBACL,IAAI,EAAE,IAAA,0BAAQ,EAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;gBACpC,MAAM;gBACN,SAAS,EACP,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;aAClE,CAAC;QACJ,CAAC,CAAC,CAAC;IACP,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8DAA8D;AAC9D,SAAS,YAAY,CAAC,GAAiB;IACrC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC;IAC/B,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,SAAS;QAClB,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc;KAC/C,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAA,2BAAS,GAAE,CAAC;IACrC,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,oBAAoB;IACpB,MAAM,SAAS,GAAG,wCAAwC,kBAAkB,CAAC,KAAK,CAAC,0BAA0B,KAAK,aAAa,CAAC;IAEhI,IAAI,UAAuC,CAAC;IAC5C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAA,2BAAS,EAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,IAAA,6BAAW,EAAC,WAAW,EAAE,KAAK,EAAE,uBAAuB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,UAAU,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,IAAA,6BAAW,EAChB,WAAW,EACX,KAAK,EACL,+BAA+B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAClF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAChC,OAAO,IAAA,6BAAW,EAAC,WAAW,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAC7D,CAAC;IAED,mBAAmB;IACnB,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,KAAK,MAAM,GAAG,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEhD,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,GAAG,CAAC,SAAS;YACnB,GAAG,EAAE,GAAG,CAAC,YAAY;YACrB,WAAW,EAAE,IAAA,0BAAQ,EAAC,GAAG,CAAC,WAAW,CAAC;YACtC,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,GAAG,CAAC,iBAAiB;gBAC3B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,GAAG,EAAE,CAAC,GAAG,EAAE;gBAC7C,CAAC,CAAC,SAAS;YACb,WAAW,EAAE,GAAG,CAAC,eAAe;YAChC,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC;YAC1B,QAAQ,EAAE,EAAE,EAAE,0CAA0C;YACxD,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAgB;QAC1B,QAAQ,EAAE,WAAW;QACrB,KAAK;QACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,OAAO;QACP,MAAM;KACP,CAAC;IAEF,IAAA,8BAAY,EAAC,MAAM,CAAC,CAAC;AACvB,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Google Play Store crawler via HTML scraping.
3
+ * Usage: node search-google-play.mjs "<keywords>" [limit]
4
+ * Output: JSON CrawlResult to stdout
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=search-google-play.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-google-play.d.ts","sourceRoot":"","sources":["../../../src/scripts/market-intel/search-google-play.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ /**
3
+ * Google Play Store crawler via HTML scraping.
4
+ * Usage: node search-google-play.mjs "<keywords>" [limit]
5
+ * Output: JSON CrawlResult to stdout
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ const cheerio = __importStar(require("cheerio"));
42
+ const shared_types_js_1 = require("./shared-types.js");
43
+ /** Extract app URLs from Google Play search results page */
44
+ function extractAppUrls($) {
45
+ const urls = [];
46
+ // Google Play search results link to /store/apps/details?id=...
47
+ $('a[href*="/store/apps/details"]').each((_, el) => {
48
+ const href = $(el).attr("href");
49
+ if (href && !urls.includes(href)) {
50
+ const fullUrl = href.startsWith("http")
51
+ ? href
52
+ : `https://play.google.com${href}`;
53
+ // Normalize to just the id parameter
54
+ const match = fullUrl.match(/id=([^&]+)/);
55
+ if (match) {
56
+ const normalized = `https://play.google.com/store/apps/details?id=${match[1]}`;
57
+ if (!urls.includes(normalized))
58
+ urls.push(normalized);
59
+ }
60
+ }
61
+ });
62
+ return urls;
63
+ }
64
+ /** Extract structured data from an app detail page */
65
+ function extractAppDetails($, url) {
66
+ // Try JSON-LD first (most reliable)
67
+ let name = "";
68
+ let description = "";
69
+ let rating;
70
+ let reviewCount;
71
+ $('script[type="application/ld+json"]').each((_, el) => {
72
+ try {
73
+ const data = JSON.parse($(el).html() || "");
74
+ if (data["@type"] === "SoftwareApplication" || data.name) {
75
+ name = data.name || "";
76
+ description = data.description || "";
77
+ if (data.aggregateRating) {
78
+ rating = parseFloat(data.aggregateRating.ratingValue);
79
+ reviewCount = parseInt(data.aggregateRating.ratingCount, 10);
80
+ }
81
+ }
82
+ }
83
+ catch {
84
+ // ignore malformed JSON-LD
85
+ }
86
+ });
87
+ // Fallback to meta tags
88
+ if (!name) {
89
+ name =
90
+ $('meta[property="og:title"]').attr("content") ||
91
+ $("h1").first().text().trim() ||
92
+ "";
93
+ }
94
+ if (!description) {
95
+ description =
96
+ $('meta[property="og:description"]').attr("content") ||
97
+ $('meta[name="description"]').attr("content") ||
98
+ "";
99
+ }
100
+ if (!name)
101
+ return null;
102
+ // Extract pricing from page text
103
+ const priceText = $('[itemprop="price"]').attr("content") ||
104
+ $('[class*="price"]').first().text().trim() ||
105
+ "";
106
+ const isFree = priceText === "0" ||
107
+ priceText.toLowerCase().includes("free") ||
108
+ !priceText;
109
+ // Extract reviews from the page
110
+ const reviews = [];
111
+ $('[class*="review"] [class*="body"], [data-review-id] [class*="content"]')
112
+ .slice(0, 6)
113
+ .each((_, el) => {
114
+ const text = $(el).text().trim();
115
+ if (text.length > 20) {
116
+ reviews.push({
117
+ text: (0, shared_types_js_1.truncate)(text, 300),
118
+ sentiment: "neutral",
119
+ });
120
+ }
121
+ });
122
+ return {
123
+ name,
124
+ url,
125
+ description: (0, shared_types_js_1.truncate)(description),
126
+ rating: rating ? Math.round(rating * 10) / 10 : undefined,
127
+ reviewCount: reviewCount || undefined,
128
+ pricing: {
129
+ free: isFree,
130
+ other: isFree ? undefined : priceText || undefined,
131
+ },
132
+ features: [],
133
+ reviews,
134
+ };
135
+ }
136
+ async function main() {
137
+ const { query, limit } = (0, shared_types_js_1.parseArgs)();
138
+ const errors = [];
139
+ // Fetch search results page
140
+ const searchUrl = `https://play.google.com/store/search?q=${encodeURIComponent(query)}&c=apps&hl=en&gl=us`;
141
+ let searchHtml;
142
+ try {
143
+ const res = await (0, shared_types_js_1.safeFetch)(searchUrl);
144
+ if (!res.ok) {
145
+ return (0, shared_types_js_1.outputError)("google_play", query, `Google Play search returned ${res.status}`);
146
+ }
147
+ searchHtml = await res.text();
148
+ }
149
+ catch (err) {
150
+ return (0, shared_types_js_1.outputError)("google_play", query, `Failed to fetch Google Play: ${err instanceof Error ? err.message : String(err)}`);
151
+ }
152
+ const $ = cheerio.load(searchHtml);
153
+ const appUrls = extractAppUrls($).slice(0, limit);
154
+ if (appUrls.length === 0) {
155
+ errors.push("No app URLs found in search results — page may be JS-rendered");
156
+ // Try to extract what we can from search page itself
157
+ const result = {
158
+ platform: "google_play",
159
+ query,
160
+ timestamp: new Date().toISOString(),
161
+ results: [],
162
+ errors,
163
+ };
164
+ return (0, shared_types_js_1.outputResult)(result);
165
+ }
166
+ // Fetch each app detail page
167
+ const results = [];
168
+ for (const url of appUrls) {
169
+ try {
170
+ const res = await (0, shared_types_js_1.safeFetch)(url);
171
+ if (!res.ok) {
172
+ errors.push(`Failed to fetch ${url}: ${res.status}`);
173
+ continue;
174
+ }
175
+ const html = await res.text();
176
+ const page$ = cheerio.load(html);
177
+ const entry = extractAppDetails(page$, url);
178
+ if (entry)
179
+ results.push(entry);
180
+ }
181
+ catch (err) {
182
+ errors.push(`Error fetching ${url}: ${err instanceof Error ? err.message : String(err)}`);
183
+ }
184
+ }
185
+ const result = {
186
+ platform: "google_play",
187
+ query,
188
+ timestamp: new Date().toISOString(),
189
+ results,
190
+ errors,
191
+ };
192
+ (0, shared_types_js_1.outputResult)(result);
193
+ }
194
+ main();
195
+ //# sourceMappingURL=search-google-play.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-google-play.js","sourceRoot":"","sources":["../../../src/scripts/market-intel/search-google-play.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Product Hunt crawler via HTML scraping + __NEXT_DATA__ extraction.
3
+ * Usage: node search-product-hunt.mjs "<keywords>" [limit]
4
+ * Output: JSON CrawlResult to stdout
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=search-product-hunt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-product-hunt.d.ts","sourceRoot":"","sources":["../../../src/scripts/market-intel/search-product-hunt.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ /**
3
+ * Product Hunt crawler via HTML scraping + __NEXT_DATA__ extraction.
4
+ * Usage: node search-product-hunt.mjs "<keywords>" [limit]
5
+ * Output: JSON CrawlResult to stdout
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ const cheerio = __importStar(require("cheerio"));
42
+ const shared_types_js_1 = require("./shared-types.js");
43
+ /** Extract product URLs from search results page */
44
+ function extractPostUrls($) {
45
+ const urls = [];
46
+ // Product Hunt post links: /posts/<slug>
47
+ $('a[href*="/posts/"]').each((_, el) => {
48
+ const href = $(el).attr("href");
49
+ if (href) {
50
+ const fullUrl = href.startsWith("http")
51
+ ? href
52
+ : `https://www.producthunt.com${href}`;
53
+ // Deduplicate and filter out non-post pages
54
+ if (fullUrl.includes("/posts/") && !urls.includes(fullUrl)) {
55
+ urls.push(fullUrl);
56
+ }
57
+ }
58
+ });
59
+ return urls;
60
+ }
61
+ /** Try to extract __NEXT_DATA__ JSON from page */
62
+ function extractNextData($) {
63
+ const script = $("#__NEXT_DATA__").html();
64
+ if (!script)
65
+ return null;
66
+ try {
67
+ return JSON.parse(script);
68
+ }
69
+ catch {
70
+ return null;
71
+ }
72
+ }
73
+ /** Deep search an object for a key matching a predicate (max 10 levels) */
74
+ function deepFind(obj, predicate, depth = 0) {
75
+ if (!obj || typeof obj !== "object" || depth > 10)
76
+ return null;
77
+ for (const [key, value] of Object.entries(obj)) {
78
+ if (predicate(key, value))
79
+ return value;
80
+ const found = deepFind(value, predicate, depth + 1);
81
+ if (found)
82
+ return found;
83
+ }
84
+ return null;
85
+ }
86
+ /** Extract post details from a Product Hunt post page */
87
+ function extractPostFromPage($, url) {
88
+ // Strategy 1: __NEXT_DATA__ (most reliable)
89
+ const nextData = extractNextData($);
90
+ if (nextData) {
91
+ // Find the post object in the nested data
92
+ const post = deepFind(nextData, (key, val) => key === "post" &&
93
+ typeof val === "object" &&
94
+ val !== null &&
95
+ "name" in val);
96
+ if (post) {
97
+ return {
98
+ name: post.name,
99
+ url,
100
+ description: (0, shared_types_js_1.truncate)(post.description || ""),
101
+ tagline: post.tagline,
102
+ rating: post.reviewsRating
103
+ ? Math.round(post.reviewsRating * 10) / 10
104
+ : undefined,
105
+ reviewCount: post.reviewsCount || post.votesCount,
106
+ pricing: {
107
+ free: true, // default assumption, PH doesn't always expose pricing
108
+ other: post.pricing || undefined,
109
+ },
110
+ features: post.topics?.map((t) => t.name).filter(Boolean).slice(0, 5) || [],
111
+ reviews: [],
112
+ };
113
+ }
114
+ }
115
+ // Strategy 2: HTML meta tags fallback
116
+ const name = $('meta[property="og:title"]').attr("content")?.replace(" | Product Hunt", "") ||
117
+ $("h1").first().text().trim() ||
118
+ "";
119
+ const description = $('meta[property="og:description"]').attr("content") || "";
120
+ if (!name)
121
+ return null;
122
+ return {
123
+ name,
124
+ url,
125
+ description: (0, shared_types_js_1.truncate)(description),
126
+ tagline: $('meta[name="twitter:description"]').attr("content") || undefined,
127
+ pricing: { free: true },
128
+ features: [],
129
+ reviews: [],
130
+ };
131
+ }
132
+ /** Extract reviews/comments from post page */
133
+ function extractComments($) {
134
+ const reviews = [];
135
+ // Product Hunt comments are typically in divs with specific data attributes
136
+ $('[class*="comment"] p, [data-test="comment-body"], [class*="CommentBody"]')
137
+ .slice(0, 6)
138
+ .each((_, el) => {
139
+ const text = $(el).text().trim();
140
+ if (text.length > 20) {
141
+ reviews.push({
142
+ text: (0, shared_types_js_1.truncate)(text, 300),
143
+ sentiment: "neutral",
144
+ });
145
+ }
146
+ });
147
+ return reviews;
148
+ }
149
+ async function main() {
150
+ const { query, limit } = (0, shared_types_js_1.parseArgs)();
151
+ const errors = [];
152
+ // Fetch search results page
153
+ const searchUrl = `https://www.producthunt.com/search?q=${encodeURIComponent(query)}`;
154
+ let searchHtml;
155
+ try {
156
+ const res = await (0, shared_types_js_1.safeFetch)(searchUrl);
157
+ if (!res.ok) {
158
+ return (0, shared_types_js_1.outputError)("product_hunt", query, `Product Hunt search returned ${res.status}`);
159
+ }
160
+ searchHtml = await res.text();
161
+ }
162
+ catch (err) {
163
+ return (0, shared_types_js_1.outputError)("product_hunt", query, `Failed to fetch Product Hunt: ${err instanceof Error ? err.message : String(err)}`);
164
+ }
165
+ const $ = cheerio.load(searchHtml);
166
+ let postUrls = extractPostUrls($).slice(0, limit);
167
+ // Try extracting from __NEXT_DATA__ on the search page itself
168
+ if (postUrls.length === 0) {
169
+ const nextData = extractNextData($);
170
+ if (nextData) {
171
+ // Search for post objects in __NEXT_DATA__
172
+ const posts = [];
173
+ const findPosts = (obj) => {
174
+ if (!obj || typeof obj !== "object")
175
+ return;
176
+ if (Array.isArray(obj)) {
177
+ for (const item of obj)
178
+ findPosts(item);
179
+ return;
180
+ }
181
+ const record = obj;
182
+ if (record.slug && record.name && typeof record.name === "string") {
183
+ posts.push(record);
184
+ }
185
+ for (const value of Object.values(record)) {
186
+ findPosts(value);
187
+ }
188
+ };
189
+ findPosts(nextData);
190
+ postUrls = posts
191
+ .slice(0, limit)
192
+ .map((p) => `https://www.producthunt.com/posts/${p.slug}`);
193
+ }
194
+ }
195
+ if (postUrls.length === 0) {
196
+ errors.push("No post URLs found — page may require JS rendering");
197
+ return (0, shared_types_js_1.outputResult)({
198
+ platform: "product_hunt",
199
+ query,
200
+ timestamp: new Date().toISOString(),
201
+ results: [],
202
+ errors,
203
+ });
204
+ }
205
+ // Fetch each post page
206
+ const results = [];
207
+ for (const url of postUrls) {
208
+ try {
209
+ const res = await (0, shared_types_js_1.safeFetch)(url);
210
+ if (!res.ok) {
211
+ errors.push(`Failed to fetch ${url}: ${res.status}`);
212
+ continue;
213
+ }
214
+ const html = await res.text();
215
+ const page$ = cheerio.load(html);
216
+ const entry = extractPostFromPage(page$, url);
217
+ if (entry) {
218
+ entry.reviews = extractComments(page$);
219
+ results.push(entry);
220
+ }
221
+ }
222
+ catch (err) {
223
+ errors.push(`Error fetching ${url}: ${err instanceof Error ? err.message : String(err)}`);
224
+ }
225
+ }
226
+ const result = {
227
+ platform: "product_hunt",
228
+ query,
229
+ timestamp: new Date().toISOString(),
230
+ results,
231
+ errors,
232
+ };
233
+ (0, shared_types_js_1.outputResult)(result);
234
+ }
235
+ main();
236
+ //# sourceMappingURL=search-product-hunt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-product-hunt.js","sourceRoot":"","sources":["../../../src/scripts/market-intel/search-product-hunt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * YC Launch (Y Combinator) crawler via HTML scraping.
3
+ * Usage: node search-yc-launch.mjs "<keywords>" [limit]
4
+ * Output: JSON CrawlResult to stdout
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=search-yc-launch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-yc-launch.d.ts","sourceRoot":"","sources":["../../../src/scripts/market-intel/search-yc-launch.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}