@hitslop/shots 0.1.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.
- package/SKILL.md +536 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +113 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/auth.d.ts +7 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +106 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/crop.d.ts +5 -0
- package/dist/commands/crop.d.ts.map +1 -0
- package/dist/commands/crop.js +32 -0
- package/dist/commands/crop.js.map +1 -0
- package/dist/commands/default.d.ts +2 -0
- package/dist/commands/default.d.ts.map +1 -0
- package/dist/commands/default.js +142 -0
- package/dist/commands/default.js.map +1 -0
- package/dist/commands/feedback.d.ts +2 -0
- package/dist/commands/feedback.d.ts.map +1 -0
- package/dist/commands/feedback.js +6 -0
- package/dist/commands/feedback.js.map +1 -0
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +5 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +5 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +13 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/scrape.d.ts +5 -0
- package/dist/commands/scrape.d.ts.map +1 -0
- package/dist/commands/scrape.js +5 -0
- package/dist/commands/scrape.js.map +1 -0
- package/dist/commands/studio.d.ts +7 -0
- package/dist/commands/studio.d.ts.map +1 -0
- package/dist/commands/studio.js +351 -0
- package/dist/commands/studio.js.map +1 -0
- package/dist/commands/styles.d.ts +2 -0
- package/dist/commands/styles.d.ts.map +1 -0
- package/dist/commands/styles.js +25 -0
- package/dist/commands/styles.js.map +1 -0
- package/dist/commands/view.d.ts +2 -0
- package/dist/commands/view.d.ts.map +1 -0
- package/dist/commands/view.js +25 -0
- package/dist/commands/view.js.map +1 -0
- package/dist/core/crop-pipeline.d.ts +28 -0
- package/dist/core/crop-pipeline.d.ts.map +1 -0
- package/dist/core/crop-pipeline.js +82 -0
- package/dist/core/crop-pipeline.js.map +1 -0
- package/dist/core/generate.d.ts +20 -0
- package/dist/core/generate.d.ts.map +1 -0
- package/dist/core/generate.js +388 -0
- package/dist/core/generate.js.map +1 -0
- package/dist/core/init.d.ts +3 -0
- package/dist/core/init.d.ts.map +1 -0
- package/dist/core/init.js +77 -0
- package/dist/core/init.js.map +1 -0
- package/dist/core/mock-generator.d.ts +5 -0
- package/dist/core/mock-generator.d.ts.map +1 -0
- package/dist/core/mock-generator.js +42 -0
- package/dist/core/mock-generator.js.map +1 -0
- package/dist/core/prompt-builder.d.ts +15 -0
- package/dist/core/prompt-builder.d.ts.map +1 -0
- package/dist/core/prompt-builder.js +195 -0
- package/dist/core/prompt-builder.js.map +1 -0
- package/dist/core/providers/fal.d.ts +3 -0
- package/dist/core/providers/fal.d.ts.map +1 -0
- package/dist/core/providers/fal.js +53 -0
- package/dist/core/providers/fal.js.map +1 -0
- package/dist/core/providers/index.d.ts +3 -0
- package/dist/core/providers/index.d.ts.map +1 -0
- package/dist/core/providers/index.js +2 -0
- package/dist/core/providers/index.js.map +1 -0
- package/dist/core/providers/managed.d.ts +3 -0
- package/dist/core/providers/managed.d.ts.map +1 -0
- package/dist/core/providers/managed.js +132 -0
- package/dist/core/providers/managed.js.map +1 -0
- package/dist/core/providers/openai.d.ts +3 -0
- package/dist/core/providers/openai.d.ts.map +1 -0
- package/dist/core/providers/openai.js +40 -0
- package/dist/core/providers/openai.js.map +1 -0
- package/dist/core/providers/replicate.d.ts +3 -0
- package/dist/core/providers/replicate.d.ts.map +1 -0
- package/dist/core/providers/replicate.js +87 -0
- package/dist/core/providers/replicate.js.map +1 -0
- package/dist/core/providers/resolve.d.ts +3 -0
- package/dist/core/providers/resolve.d.ts.map +1 -0
- package/dist/core/providers/resolve.js +41 -0
- package/dist/core/providers/resolve.js.map +1 -0
- package/dist/core/providers/types.d.ts +29 -0
- package/dist/core/providers/types.d.ts.map +1 -0
- package/dist/core/providers/types.js +2 -0
- package/dist/core/providers/types.js.map +1 -0
- package/dist/core/scraper.d.ts +22 -0
- package/dist/core/scraper.d.ts.map +1 -0
- package/dist/core/scraper.js +138 -0
- package/dist/core/scraper.js.map +1 -0
- package/dist/core/walkthrough.d.ts +10 -0
- package/dist/core/walkthrough.d.ts.map +1 -0
- package/dist/core/walkthrough.js +116 -0
- package/dist/core/walkthrough.js.map +1 -0
- package/dist/schema/config.d.ts +45 -0
- package/dist/schema/config.d.ts.map +1 -0
- package/dist/schema/config.js +36 -0
- package/dist/schema/config.js.map +1 -0
- package/dist/schema/manifest.d.ts +43 -0
- package/dist/schema/manifest.d.ts.map +1 -0
- package/dist/schema/manifest.js +5 -0
- package/dist/schema/manifest.js.map +1 -0
- package/dist/schema/style-meta.d.ts +8 -0
- package/dist/schema/style-meta.d.ts.map +1 -0
- package/dist/schema/style-meta.js +2 -0
- package/dist/schema/style-meta.js.map +1 -0
- package/dist/styles/installer.d.ts +2 -0
- package/dist/styles/installer.d.ts.map +1 -0
- package/dist/styles/installer.js +43 -0
- package/dist/styles/installer.js.map +1 -0
- package/dist/styles/registry.d.ts +20 -0
- package/dist/styles/registry.d.ts.map +1 -0
- package/dist/styles/registry.js +96 -0
- package/dist/styles/registry.js.map +1 -0
- package/dist/util/auth-store.d.ts +12 -0
- package/dist/util/auth-store.d.ts.map +1 -0
- package/dist/util/auth-store.js +46 -0
- package/dist/util/auth-store.js.map +1 -0
- package/dist/util/id.d.ts +2 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +14 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/json.d.ts +3 -0
- package/dist/util/json.d.ts.map +1 -0
- package/dist/util/json.js +9 -0
- package/dist/util/json.js.map +1 -0
- package/dist/util/open.d.ts +2 -0
- package/dist/util/open.d.ts.map +1 -0
- package/dist/util/open.js +21 -0
- package/dist/util/open.js.map +1 -0
- package/dist/util/paths.d.ts +9 -0
- package/dist/util/paths.d.ts.map +1 -0
- package/dist/util/paths.js +21 -0
- package/dist/util/paths.js.map +1 -0
- package/package.json +37 -0
- package/studio/assets/index-BgiuT_Mv.css +1 -0
- package/studio/assets/index-DnN633_x.js +9 -0
- package/studio/index.html +13 -0
- package/styles/clean-premium/meta.json +7 -0
- package/styles/clean-premium/prompt.md +16 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createOpenAIProvider } from "./openai.js";
|
|
2
|
+
import { createFalProvider } from "./fal.js";
|
|
3
|
+
import { createReplicateProvider } from "./replicate.js";
|
|
4
|
+
import { createManagedProvider } from "./managed.js";
|
|
5
|
+
const PROVIDER_FACTORIES = {
|
|
6
|
+
openai: createOpenAIProvider,
|
|
7
|
+
fal: createFalProvider,
|
|
8
|
+
replicate: createReplicateProvider,
|
|
9
|
+
managed: createManagedProvider,
|
|
10
|
+
};
|
|
11
|
+
const AUTO_DETECT_ORDER = [
|
|
12
|
+
{ key: "OPENAI_API_KEY", provider: "openai" },
|
|
13
|
+
{ key: "FAL_KEY", provider: "fal" },
|
|
14
|
+
{ key: "REPLICATE_API_TOKEN", provider: "replicate" },
|
|
15
|
+
];
|
|
16
|
+
export function resolveProvider(explicit) {
|
|
17
|
+
if (explicit) {
|
|
18
|
+
const name = explicit;
|
|
19
|
+
const factory = PROVIDER_FACTORIES[name];
|
|
20
|
+
if (!factory) {
|
|
21
|
+
throw new Error(`Unknown provider "${explicit}". Valid options: ${Object.keys(PROVIDER_FACTORIES).join(", ")}`);
|
|
22
|
+
}
|
|
23
|
+
return factory();
|
|
24
|
+
}
|
|
25
|
+
// Auto-detect based on available env vars
|
|
26
|
+
for (const { key, provider } of AUTO_DETECT_ORDER) {
|
|
27
|
+
if (process.env[key]) {
|
|
28
|
+
console.log(`Auto-detected provider: ${provider} (${key} is set)`);
|
|
29
|
+
return PROVIDER_FACTORIES[provider]();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
throw new Error([
|
|
33
|
+
"No API key found. Set one of the following environment variables:",
|
|
34
|
+
" OPENAI_API_KEY — OpenAI (direct, exact dimensions)",
|
|
35
|
+
" FAL_KEY — fal.ai (proxy, exact dimensions, often cheaper)",
|
|
36
|
+
" REPLICATE_API_TOKEN — Replicate (proxy, aspect ratio presets)",
|
|
37
|
+
"",
|
|
38
|
+
"Or use --mock for testing without an API key.",
|
|
39
|
+
].join("\n"));
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/core/providers/resolve.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD,MAAM,kBAAkB,GAA8C;IACpE,MAAM,EAAE,oBAAoB;IAC5B,GAAG,EAAE,iBAAiB;IACtB,SAAS,EAAE,uBAAuB;IAClC,OAAO,EAAE,qBAAqB;CAC/B,CAAC;AAEF,MAAM,iBAAiB,GAAmD;IACxE,EAAE,GAAG,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,EAAE;IAC7C,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE;IACnC,EAAE,GAAG,EAAE,qBAAqB,EAAE,QAAQ,EAAE,WAAW,EAAE;CACtD,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,QAAiB;IAC/C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,QAAwB,CAAC;QACtC,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,qBAAqB,QAAQ,qBAAqB,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC/F,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,EAAE,CAAC;IACnB,CAAC;IAED,0CAA0C;IAC1C,KAAK,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,iBAAiB,EAAE,CAAC;QAClD,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,2BAA2B,QAAQ,KAAK,GAAG,UAAU,CAAC,CAAC;YACnE,OAAO,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxC,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CACb;QACE,mEAAmE;QACnE,yDAAyD;QACzD,uEAAuE;QACvE,iEAAiE;QACjE,EAAE;QACF,+CAA+C;KAChD,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type ProviderName = "openai" | "fal" | "replicate" | "managed";
|
|
2
|
+
export type ManagedBackendProvider = "openai" | "fal";
|
|
3
|
+
export interface ReferenceImage {
|
|
4
|
+
buffer: Buffer;
|
|
5
|
+
filename: string;
|
|
6
|
+
mimeType: string;
|
|
7
|
+
}
|
|
8
|
+
export interface GenerateInput {
|
|
9
|
+
prompt: string;
|
|
10
|
+
references: ReferenceImage[];
|
|
11
|
+
quality: "high" | "medium" | "low";
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
panelCount?: number;
|
|
15
|
+
platform?: "iphone" | "ipad" | "android";
|
|
16
|
+
managedProvider?: ManagedBackendProvider;
|
|
17
|
+
n: 1;
|
|
18
|
+
}
|
|
19
|
+
export interface GenerateOutput {
|
|
20
|
+
imageBuffer: Buffer;
|
|
21
|
+
actualWidth: number;
|
|
22
|
+
actualHeight: number;
|
|
23
|
+
provider: ProviderName;
|
|
24
|
+
}
|
|
25
|
+
export interface ImageProvider {
|
|
26
|
+
readonly name: ProviderName;
|
|
27
|
+
generate(input: GenerateInput): Promise<GenerateOutput>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/providers/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,KAAK,GAAG,WAAW,GAAG,SAAS,CAAC;AACtE,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEtD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IACzC,eAAe,CAAC,EAAE,sBAAsB,CAAC;IACzC,CAAC,EAAE,CAAC,CAAC;CACN;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACzD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/providers/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare function parseAppStoreId(url: string): number;
|
|
2
|
+
interface ScrapedApp {
|
|
3
|
+
title: string;
|
|
4
|
+
description: string;
|
|
5
|
+
icon: string;
|
|
6
|
+
genres: string[];
|
|
7
|
+
genreIds: string[];
|
|
8
|
+
developer: string;
|
|
9
|
+
version: string;
|
|
10
|
+
releaseNotes: string;
|
|
11
|
+
score: number;
|
|
12
|
+
reviews: number;
|
|
13
|
+
screenshots: string[];
|
|
14
|
+
url: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function scrapeAppStore(url: string, country?: string): Promise<ScrapedApp>;
|
|
17
|
+
export declare function scrapeAndUpdateConfig(url: string, options?: {
|
|
18
|
+
downloadScreenshots?: boolean;
|
|
19
|
+
country?: string;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=scraper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scraper.d.ts","sourceRoot":"","sources":["../../src/core/scraper.ts"],"names":[],"mappings":"AAwBA,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAInD;AAED,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAID,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,OAAO,SAAO,GACb,OAAO,CAAC,UAAU,CAAC,CA0CrB;AAyBD,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAChE,OAAO,CAAC,IAAI,CAAC,CAgFf"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { readJson, writeJson } from "../util/json.js";
|
|
4
|
+
import { shotsDir } from "../util/paths.js";
|
|
5
|
+
const ITUNES_LOOKUP = "https://itunes.apple.com/lookup";
|
|
6
|
+
export function parseAppStoreId(url) {
|
|
7
|
+
const match = url.match(/\/id(\d+)/);
|
|
8
|
+
if (!match)
|
|
9
|
+
throw new Error("Invalid App Store URL — expected /id{number}");
|
|
10
|
+
return parseInt(match[1], 10);
|
|
11
|
+
}
|
|
12
|
+
const SHOTS_API_URL = process.env.SHOTS_API_URL || "http://localhost:3000";
|
|
13
|
+
export async function scrapeAppStore(url, country = "us") {
|
|
14
|
+
const id = parseAppStoreId(url);
|
|
15
|
+
const app = await fetchiTunesLookup(id, country);
|
|
16
|
+
const result = {
|
|
17
|
+
title: app.trackName ?? "",
|
|
18
|
+
description: app.description ?? "",
|
|
19
|
+
icon: app.artworkUrl512 ?? "",
|
|
20
|
+
genres: app.genres ?? [],
|
|
21
|
+
genreIds: app.genreIds ?? [],
|
|
22
|
+
developer: app.artistName ?? "",
|
|
23
|
+
version: app.version ?? "",
|
|
24
|
+
releaseNotes: app.releaseNotes ?? "",
|
|
25
|
+
score: app.averageUserRating ?? 0,
|
|
26
|
+
reviews: app.userRatingCount ?? 0,
|
|
27
|
+
screenshots: app.screenshotUrls ?? [],
|
|
28
|
+
url: app.trackViewUrl ?? url,
|
|
29
|
+
};
|
|
30
|
+
// Fallback: if iTunes API returned no screenshots, try the web server endpoint.
|
|
31
|
+
if (result.screenshots.length === 0) {
|
|
32
|
+
try {
|
|
33
|
+
const apiUrl = `${SHOTS_API_URL}/api/screenshots/${id}?country=${country}`;
|
|
34
|
+
const fallbackRes = await fetch(apiUrl);
|
|
35
|
+
if (fallbackRes.ok) {
|
|
36
|
+
const fallbackData = (await fallbackRes.json());
|
|
37
|
+
if (fallbackData.screenshots?.length > 0) {
|
|
38
|
+
result.screenshots = fallbackData.screenshots;
|
|
39
|
+
console.log(`Fetched ${fallbackData.screenshots.length} screenshots from web server (iTunes API had none)`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Backend unreachable — continue with empty screenshots
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
async function fetchiTunesLookup(appId, country = "us") {
|
|
50
|
+
const params = new URLSearchParams({
|
|
51
|
+
id: String(appId),
|
|
52
|
+
country,
|
|
53
|
+
entity: "software",
|
|
54
|
+
});
|
|
55
|
+
const res = await fetch(`${ITUNES_LOOKUP}?${params}`);
|
|
56
|
+
if (!res.ok) {
|
|
57
|
+
throw new Error(`iTunes API returned HTTP ${res.status}`);
|
|
58
|
+
}
|
|
59
|
+
const data = (await res.json());
|
|
60
|
+
if (!data.results?.length) {
|
|
61
|
+
throw new Error(`App ${appId} not found in iTunes (country: ${country})`);
|
|
62
|
+
}
|
|
63
|
+
return data.results[0];
|
|
64
|
+
}
|
|
65
|
+
export async function scrapeAndUpdateConfig(url, options = {}) {
|
|
66
|
+
const dir = shotsDir();
|
|
67
|
+
const configPath = path.join(dir, "config.json");
|
|
68
|
+
let config;
|
|
69
|
+
try {
|
|
70
|
+
config = await readJson(configPath);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
console.error("Error: .shots/config.json not found. Run `npx -y @hitslop/shots@latest init` to initialize first.");
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
console.log(`Scraping App Store data for: ${url}\n`);
|
|
77
|
+
const app = await scrapeAppStore(url, options.country);
|
|
78
|
+
// Update config with scraped data
|
|
79
|
+
config.appName = app.title;
|
|
80
|
+
config.appStoreUrl = app.url;
|
|
81
|
+
config.aso = {
|
|
82
|
+
title: app.title.slice(0, 30),
|
|
83
|
+
subtitle: "",
|
|
84
|
+
description: app.description.slice(0, 4000),
|
|
85
|
+
keywords: "",
|
|
86
|
+
genres: app.genres,
|
|
87
|
+
developer: app.developer,
|
|
88
|
+
version: app.version,
|
|
89
|
+
releaseNotes: app.releaseNotes,
|
|
90
|
+
};
|
|
91
|
+
config.ratings = {
|
|
92
|
+
score: Math.round(app.score * 10) / 10,
|
|
93
|
+
reviewCount: app.reviews,
|
|
94
|
+
};
|
|
95
|
+
config.scrapedAssets = {
|
|
96
|
+
iconUrl: app.icon,
|
|
97
|
+
screenshotUrls: app.screenshots,
|
|
98
|
+
scrapedAt: new Date().toISOString(),
|
|
99
|
+
};
|
|
100
|
+
await writeJson(configPath, config);
|
|
101
|
+
// Print summary
|
|
102
|
+
console.log(`App: ${app.title}`);
|
|
103
|
+
console.log(`Developer: ${app.developer}`);
|
|
104
|
+
console.log(`Version: ${app.version}`);
|
|
105
|
+
console.log(`Rating: ${config.ratings.score}/5 (${app.reviews.toLocaleString()} reviews)`);
|
|
106
|
+
console.log(`Genres: ${app.genres.join(", ")}`);
|
|
107
|
+
console.log(`Screenshots: ${app.screenshots.length} found`);
|
|
108
|
+
console.log("");
|
|
109
|
+
console.log("ASO field char counts:");
|
|
110
|
+
console.log(` Title: ${config.aso.title.length}/30`);
|
|
111
|
+
console.log(` Description: ${config.aso.description.length}/4000`);
|
|
112
|
+
console.log("");
|
|
113
|
+
// Download screenshots if requested
|
|
114
|
+
if (options.downloadScreenshots && app.screenshots.length > 0) {
|
|
115
|
+
const screenshotDir = path.join(dir, "app-screenshots");
|
|
116
|
+
await fs.mkdir(screenshotDir, { recursive: true });
|
|
117
|
+
console.log("Downloading screenshots...");
|
|
118
|
+
for (let i = 0; i < app.screenshots.length; i++) {
|
|
119
|
+
const screenshotUrl = app.screenshots[i];
|
|
120
|
+
try {
|
|
121
|
+
const response = await fetch(screenshotUrl);
|
|
122
|
+
if (!response.ok)
|
|
123
|
+
throw new Error(`HTTP ${response.status}`);
|
|
124
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
125
|
+
const ext = path.extname(new URL(screenshotUrl).pathname) || ".png";
|
|
126
|
+
const filename = `app-screenshot-${i + 1}${ext}`;
|
|
127
|
+
await fs.writeFile(path.join(screenshotDir, filename), buffer);
|
|
128
|
+
console.log(` Downloaded: ${filename}`);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
console.warn(` Failed to download screenshot ${i + 1}: ${err}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
console.log("");
|
|
135
|
+
}
|
|
136
|
+
console.log("Config updated: .shots/config.json");
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=scraper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scraper.js","sourceRoot":"","sources":["../../src/core/scraper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Config } from "../schema/config.js";
|
|
2
|
+
export interface WalkthroughResult {
|
|
3
|
+
config: Partial<Config>;
|
|
4
|
+
downloadScreenshots: boolean;
|
|
5
|
+
screenshotCount: number;
|
|
6
|
+
featuresToHighlight: string;
|
|
7
|
+
aestheticGuidance: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function runWalkthrough(): Promise<WalkthroughResult>;
|
|
10
|
+
//# sourceMappingURL=walkthrough.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walkthrough.d.ts","sourceRoot":"","sources":["../../src/core/walkthrough.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAUD,wBAAsB,cAAc,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAmIjE"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import readline from "node:readline/promises";
|
|
2
|
+
import { stdin, stdout } from "node:process";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { scrapeAppStore } from "./scraper.js";
|
|
5
|
+
async function ask(rl, question) {
|
|
6
|
+
const answer = await rl.question(chalk.cyan(question) + " ");
|
|
7
|
+
return answer.trim();
|
|
8
|
+
}
|
|
9
|
+
export async function runWalkthrough() {
|
|
10
|
+
const rl = readline.createInterface({ input: stdin, output: stdout });
|
|
11
|
+
try {
|
|
12
|
+
console.log(chalk.bold("\nWelcome to Shots!\n"));
|
|
13
|
+
console.log(chalk.dim("Let's set up your project.\n"));
|
|
14
|
+
// 0. Ensure OPENAI_API_KEY is available (needed for image generation)
|
|
15
|
+
if (!process.env.OPENAI_API_KEY) {
|
|
16
|
+
console.log(chalk.yellow(" OPENAI_API_KEY not found in environment."));
|
|
17
|
+
console.log(chalk.dim(" This key is needed to generate screenshots with OpenAI GPT Image."));
|
|
18
|
+
console.log(chalk.dim(" Get one at https://platform.openai.com/api-keys\n"));
|
|
19
|
+
const key = await ask(rl, "OPENAI_API_KEY (or Enter to skip):");
|
|
20
|
+
if (key) {
|
|
21
|
+
process.env.OPENAI_API_KEY = key;
|
|
22
|
+
console.log(chalk.green(" Key set for this session.\n"));
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.log(chalk.dim(" Skipped — you can still use --mock for testing.\n"));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// 1. App name (required)
|
|
29
|
+
let appName = "";
|
|
30
|
+
while (!appName) {
|
|
31
|
+
appName = await ask(rl, "App name:");
|
|
32
|
+
if (!appName) {
|
|
33
|
+
console.log(chalk.yellow(" App name is required."));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// 2. App Store URL (optional)
|
|
37
|
+
const appStoreUrl = await ask(rl, "App Store URL (leave blank to skip):");
|
|
38
|
+
const config = { appName };
|
|
39
|
+
let downloadScreenshots = false;
|
|
40
|
+
if (appStoreUrl) {
|
|
41
|
+
// Scrape App Store data
|
|
42
|
+
console.log(chalk.dim("\nScraping App Store data...\n"));
|
|
43
|
+
try {
|
|
44
|
+
const app = await scrapeAppStore(appStoreUrl);
|
|
45
|
+
config.appName = app.title || appName;
|
|
46
|
+
config.appStoreUrl = app.url;
|
|
47
|
+
config.aso = {
|
|
48
|
+
title: app.title.slice(0, 30),
|
|
49
|
+
subtitle: "",
|
|
50
|
+
description: app.description.slice(0, 4000),
|
|
51
|
+
keywords: "",
|
|
52
|
+
genres: app.genres,
|
|
53
|
+
developer: app.developer,
|
|
54
|
+
version: app.version,
|
|
55
|
+
releaseNotes: app.releaseNotes,
|
|
56
|
+
};
|
|
57
|
+
config.ratings = {
|
|
58
|
+
score: Math.round(app.score * 10) / 10,
|
|
59
|
+
reviewCount: app.reviews,
|
|
60
|
+
};
|
|
61
|
+
config.scrapedAssets = {
|
|
62
|
+
iconUrl: app.icon,
|
|
63
|
+
screenshotUrls: app.screenshots,
|
|
64
|
+
scrapedAt: new Date().toISOString(),
|
|
65
|
+
};
|
|
66
|
+
console.log(` ${chalk.bold(app.title)} by ${app.developer}`);
|
|
67
|
+
console.log(` ${config.ratings.score}/5 (${app.reviews.toLocaleString()} reviews)`);
|
|
68
|
+
console.log(` ${app.screenshots.length} screenshots found`);
|
|
69
|
+
if (app.screenshots.length > 0) {
|
|
70
|
+
downloadScreenshots = true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
console.log(chalk.yellow(` Could not scrape: ${err.message}`));
|
|
75
|
+
console.log(chalk.dim(" You can run `npx -y @hitslop/shots@latest scrape <url>` later.\n"));
|
|
76
|
+
config.appStoreUrl = appStoreUrl;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Always ask positioning questions (optional — press Enter to skip)
|
|
80
|
+
const positioning = await ask(rl, "What makes your app different? (optional)");
|
|
81
|
+
const targetAudience = await ask(rl, "Who is your app for? (optional)");
|
|
82
|
+
if (positioning)
|
|
83
|
+
config.positioning = positioning;
|
|
84
|
+
if (targetAudience)
|
|
85
|
+
config.targetAudience = targetAudience;
|
|
86
|
+
// Screenshot count
|
|
87
|
+
const countRaw = await ask(rl, "How many screenshots? (1-10, default 3):");
|
|
88
|
+
let screenshotCount = 3;
|
|
89
|
+
if (countRaw) {
|
|
90
|
+
const parsed = parseInt(countRaw, 10);
|
|
91
|
+
if (parsed >= 1 && parsed <= 10) {
|
|
92
|
+
screenshotCount = parsed;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
console.log(chalk.yellow(" Invalid number — using default (3)."));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Features to highlight
|
|
99
|
+
const featuresToHighlight = await ask(rl, "What features or screens should we highlight? (optional)");
|
|
100
|
+
// Aesthetic guidance
|
|
101
|
+
const aestheticGuidance = await ask(rl, "Any visual style or aesthetic guidance? (optional)");
|
|
102
|
+
if (aestheticGuidance)
|
|
103
|
+
config.visualTone = aestheticGuidance;
|
|
104
|
+
return {
|
|
105
|
+
config,
|
|
106
|
+
downloadScreenshots,
|
|
107
|
+
screenshotCount,
|
|
108
|
+
featuresToHighlight,
|
|
109
|
+
aestheticGuidance,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
rl.close();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=walkthrough.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walkthrough.js","sourceRoot":"","sources":["../../src/core/walkthrough.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export interface Benefit {
|
|
2
|
+
headline: string;
|
|
3
|
+
subtitle: string;
|
|
4
|
+
approach: "moment" | "outcome" | "pain";
|
|
5
|
+
panelType: string;
|
|
6
|
+
feature: string;
|
|
7
|
+
arcPosition: "hero" | "differentiator" | "core" | "trust" | "closer";
|
|
8
|
+
}
|
|
9
|
+
export interface Config {
|
|
10
|
+
appName: string;
|
|
11
|
+
appStoreUrl: string;
|
|
12
|
+
devices?: Array<"iphone" | "ipad" | "android">;
|
|
13
|
+
positioning: string;
|
|
14
|
+
targetAudience: string;
|
|
15
|
+
visualTone: string;
|
|
16
|
+
brandColors: {
|
|
17
|
+
primary: string;
|
|
18
|
+
secondary: string;
|
|
19
|
+
accent: string;
|
|
20
|
+
text: string;
|
|
21
|
+
};
|
|
22
|
+
aso: {
|
|
23
|
+
title: string;
|
|
24
|
+
subtitle: string;
|
|
25
|
+
description: string;
|
|
26
|
+
keywords: string;
|
|
27
|
+
genres: string[];
|
|
28
|
+
developer: string;
|
|
29
|
+
version: string;
|
|
30
|
+
releaseNotes: string;
|
|
31
|
+
};
|
|
32
|
+
ratings: {
|
|
33
|
+
score: number;
|
|
34
|
+
reviewCount: number;
|
|
35
|
+
};
|
|
36
|
+
scrapedAssets: {
|
|
37
|
+
iconUrl: string;
|
|
38
|
+
screenshotUrls: string[];
|
|
39
|
+
scrapedAt: string;
|
|
40
|
+
};
|
|
41
|
+
activeStyle: string;
|
|
42
|
+
benefits: Benefit[];
|
|
43
|
+
}
|
|
44
|
+
export declare const DEFAULT_CONFIG: Config;
|
|
45
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/schema/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;CACtE;AAED,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,GAAG,EAAE;QACH,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,aAAa,EAAE;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,eAAO,MAAM,cAAc,EAAE,MAkC5B,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const DEFAULT_CONFIG = {
|
|
2
|
+
appName: "My App",
|
|
3
|
+
appStoreUrl: "",
|
|
4
|
+
devices: ["iphone"],
|
|
5
|
+
positioning: "",
|
|
6
|
+
targetAudience: "",
|
|
7
|
+
visualTone: "clean, modern, premium",
|
|
8
|
+
brandColors: {
|
|
9
|
+
primary: "#1a1a2e",
|
|
10
|
+
secondary: "#16213e",
|
|
11
|
+
accent: "#0f969c",
|
|
12
|
+
text: "#f5f5f5",
|
|
13
|
+
},
|
|
14
|
+
aso: {
|
|
15
|
+
title: "",
|
|
16
|
+
subtitle: "",
|
|
17
|
+
description: "",
|
|
18
|
+
keywords: "",
|
|
19
|
+
genres: [],
|
|
20
|
+
developer: "",
|
|
21
|
+
version: "",
|
|
22
|
+
releaseNotes: "",
|
|
23
|
+
},
|
|
24
|
+
ratings: {
|
|
25
|
+
score: 0,
|
|
26
|
+
reviewCount: 0,
|
|
27
|
+
},
|
|
28
|
+
scrapedAssets: {
|
|
29
|
+
iconUrl: "",
|
|
30
|
+
screenshotUrls: [],
|
|
31
|
+
scrapedAt: "",
|
|
32
|
+
},
|
|
33
|
+
activeStyle: "",
|
|
34
|
+
benefits: [],
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/schema/config.ts"],"names":[],"mappings":"AA6CA,MAAM,CAAC,MAAM,cAAc,GAAW;IACpC,OAAO,EAAE,QAAQ;IACjB,WAAW,EAAE,EAAE;IACf,OAAO,EAAE,CAAC,QAAQ,CAAC;IACnB,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,EAAE;IAClB,UAAU,EAAE,wBAAwB;IACpC,WAAW,EAAE;QACX,OAAO,EAAE,SAAS;QAClB,SAAS,EAAE,SAAS;QACpB,MAAM,EAAE,SAAS;QACjB,IAAI,EAAE,SAAS;KAChB;IACD,GAAG,EAAE;QACH,KAAK,EAAE,EAAE;QACT,QAAQ,EAAE,EAAE;QACZ,WAAW,EAAE,EAAE;QACf,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,EAAE;QACV,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;QACX,YAAY,EAAE,EAAE;KACjB;IACD,OAAO,EAAE;QACP,KAAK,EAAE,CAAC;QACR,WAAW,EAAE,CAAC;KACf;IACD,aAAa,EAAE;QACb,OAAO,EAAE,EAAE;QACX,cAAc,EAAE,EAAE;QAClB,SAAS,EAAE,EAAE;KACd;IACD,WAAW,EAAE,EAAE;IACf,QAAQ,EAAE,EAAE;CACb,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface FeedbackEntry {
|
|
2
|
+
from: "user" | "agent";
|
|
3
|
+
text: string;
|
|
4
|
+
at: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ShotDimensions {
|
|
7
|
+
platform?: "iphone" | "ipad" | "android";
|
|
8
|
+
compositeWidth: number;
|
|
9
|
+
compositeHeight: number;
|
|
10
|
+
targetWidth: number;
|
|
11
|
+
targetHeight: number;
|
|
12
|
+
}
|
|
13
|
+
export interface Shot {
|
|
14
|
+
id: string;
|
|
15
|
+
compositeFile: string;
|
|
16
|
+
screenshotFiles: string[];
|
|
17
|
+
prompt: string;
|
|
18
|
+
userPrompt?: string;
|
|
19
|
+
runDir?: string;
|
|
20
|
+
promptFile?: string;
|
|
21
|
+
referencesFile?: string;
|
|
22
|
+
feedbackFile?: string;
|
|
23
|
+
metadataFile?: string;
|
|
24
|
+
model: string;
|
|
25
|
+
quality: string;
|
|
26
|
+
referenceImages: string[];
|
|
27
|
+
feedback: FeedbackEntry[];
|
|
28
|
+
parentId: string | null;
|
|
29
|
+
provider?: string;
|
|
30
|
+
managedProvider?: "openai" | "fal";
|
|
31
|
+
mode?: string;
|
|
32
|
+
styleName?: string;
|
|
33
|
+
setName?: string;
|
|
34
|
+
panelCount?: number;
|
|
35
|
+
dimensions?: ShotDimensions;
|
|
36
|
+
createdAt: string;
|
|
37
|
+
}
|
|
38
|
+
export interface Manifest {
|
|
39
|
+
version: number;
|
|
40
|
+
shots: Shot[];
|
|
41
|
+
}
|
|
42
|
+
export declare const DEFAULT_MANIFEST: Manifest;
|
|
43
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/schema/manifest.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,eAAO,MAAM,gBAAgB,EAAE,QAG9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/schema/manifest.ts"],"names":[],"mappings":"AA6CA,MAAM,CAAC,MAAM,gBAAgB,GAAa;IACxC,OAAO,EAAE,CAAC;IACV,KAAK,EAAE,EAAE;CACV,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style-meta.d.ts","sourceRoot":"","sources":["../../src/schema/style-meta.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style-meta.js","sourceRoot":"","sources":["../../src/schema/style-meta.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/styles/installer.ts"],"names":[],"mappings":"AAoBA,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BnE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { readJson, writeJson } from "../util/json.js";
|
|
4
|
+
import { shotsDir, bundledStylesPath } from "../util/paths.js";
|
|
5
|
+
async function copyDir(src, dest) {
|
|
6
|
+
await fs.mkdir(dest, { recursive: true });
|
|
7
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
8
|
+
for (const entry of entries) {
|
|
9
|
+
const srcPath = path.join(src, entry.name);
|
|
10
|
+
const destPath = path.join(dest, entry.name);
|
|
11
|
+
if (entry.isDirectory()) {
|
|
12
|
+
await copyDir(srcPath, destPath);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
await fs.copyFile(srcPath, destPath);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function installStyle(styleName) {
|
|
20
|
+
const dir = shotsDir();
|
|
21
|
+
const bundledDir = path.join(bundledStylesPath(), styleName);
|
|
22
|
+
const destDir = path.join(dir, "styles", styleName);
|
|
23
|
+
// Verify bundled style exists
|
|
24
|
+
try {
|
|
25
|
+
await fs.access(bundledDir);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw new Error(`Style "${styleName}" not found in bundled styles. Run \`npx -y @hitslop/shots@latest styles\` to see available styles.`);
|
|
29
|
+
}
|
|
30
|
+
// Copy to .shots/styles/
|
|
31
|
+
await copyDir(bundledDir, destDir);
|
|
32
|
+
// Update activeStyle in config
|
|
33
|
+
const configPath = path.join(dir, "config.json");
|
|
34
|
+
try {
|
|
35
|
+
const config = await readJson(configPath);
|
|
36
|
+
config.activeStyle = styleName;
|
|
37
|
+
await writeJson(configPath, config);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Config doesn't exist yet — that's okay
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/styles/installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE/D,KAAK,UAAU,OAAO,CAAC,GAAW,EAAE,IAAY;IAC9C,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAiB;IAClD,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IACvB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,SAAS,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAEpD,8BAA8B;IAC9B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,UAAU,SAAS,qGAAqG,CACzH,CAAC;IACJ,CAAC;IAED,yBAAyB;IACzB,MAAM,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAEnC,+BAA+B;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAS,UAAU,CAAC,CAAC;QAClD,MAAM,CAAC,WAAW,GAAG,SAAS,CAAC;QAC/B,MAAM,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,yCAAyC;IAC3C,CAAC;AACH,CAAC"}
|