shadertown 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/LICENSE +21 -0
- package/README.md +20 -0
- package/cli/cli.mjs +341 -0
- package/cli/shadertown.mjs +8 -0
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -0
- package/dist/export.d.ts +30 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +234 -0
- package/dist/export.js.map +1 -0
- package/dist/generated/sources.d.ts +22 -0
- package/dist/generated/sources.d.ts.map +1 -0
- package/dist/generated/sources.js +24 -0
- package/dist/generated/sources.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/params.d.ts +24 -0
- package/dist/params.d.ts.map +1 -0
- package/dist/params.js +105 -0
- package/dist/params.js.map +1 -0
- package/dist/react.d.ts +41 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +127 -0
- package/dist/react.js.map +1 -0
- package/dist/registry.d.ts +1930 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +1067 -0
- package/dist/registry.js.map +1 -0
- package/dist/renderer.d.ts +31 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +144 -0
- package/dist/renderer.js.map +1 -0
- package/dist/stage.d.ts +39 -0
- package/dist/stage.d.ts.map +1 -0
- package/dist/stage.js +79 -0
- package/dist/stage.js.map +1 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +85 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 shadertown
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# shadertown
|
|
2
|
+
|
|
3
|
+
Production WebGPU shader backgrounds for the web, drawn by
|
|
4
|
+
[vgpu](https://vgpu.sh).
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npm install shadertown
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
import { ShaderCanvas } from "shadertown/react";
|
|
12
|
+
|
|
13
|
+
<ShaderCanvas shader="aurora" params={{ speed: 0.4 }} play="visible" />;
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
No WGSL loader, no bundler plugin: shader sources ship as strings. Every
|
|
17
|
+
renderer on a page shares one GPU context and one frame loop, and the loop stops
|
|
18
|
+
when nothing is animating.
|
|
19
|
+
|
|
20
|
+
Full documentation: https://www.shadertown.com/docs
|
package/cli/cli.mjs
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile, access, chmod, rm } from "node:fs/promises";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
|
|
6
|
+
const DEFAULT_REGISTRY = process.env.SHADERTOWN_REGISTRY ?? "https://www.shadertown.com";
|
|
7
|
+
const DEFAULT_OUT = "src/shaders";
|
|
8
|
+
|
|
9
|
+
const esc = (code, text) => `\u001b[${code}m${text}\u001b[0m`;
|
|
10
|
+
const c = {
|
|
11
|
+
dim: (s) => esc(2, s),
|
|
12
|
+
bold: (s) => esc(1, s),
|
|
13
|
+
green: (s) => esc(32, s),
|
|
14
|
+
cyan: (s) => esc(36, s),
|
|
15
|
+
yellow: (s) => esc(33, s),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export async function run(argv) {
|
|
19
|
+
const [command, ...rest] = argv;
|
|
20
|
+
switch (command) {
|
|
21
|
+
case "add":
|
|
22
|
+
return add(rest);
|
|
23
|
+
case "list":
|
|
24
|
+
return list(rest);
|
|
25
|
+
case "init":
|
|
26
|
+
return init();
|
|
27
|
+
case "login":
|
|
28
|
+
return login(rest);
|
|
29
|
+
case "logout":
|
|
30
|
+
return logout();
|
|
31
|
+
case "whoami":
|
|
32
|
+
return whoami();
|
|
33
|
+
case undefined:
|
|
34
|
+
case "help":
|
|
35
|
+
case "--help":
|
|
36
|
+
case "-h":
|
|
37
|
+
return help();
|
|
38
|
+
case "--version":
|
|
39
|
+
case "-v":
|
|
40
|
+
return version();
|
|
41
|
+
default:
|
|
42
|
+
throw new Error(`Unknown command "${command}". Run \`shadertown help\`.`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function parseFlags(args) {
|
|
47
|
+
const flags = {};
|
|
48
|
+
const positional = [];
|
|
49
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
50
|
+
const arg = args[i];
|
|
51
|
+
if (arg.startsWith("--")) {
|
|
52
|
+
const key = arg.slice(2);
|
|
53
|
+
if (key === "force") {
|
|
54
|
+
flags.force = true;
|
|
55
|
+
} else {
|
|
56
|
+
flags[key] = args[i + 1];
|
|
57
|
+
i += 1;
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
positional.push(arg);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return { flags, positional };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Reads shadertown.config.ts without executing it - only the fields we need. */
|
|
67
|
+
async function readProjectConfig(cwd) {
|
|
68
|
+
for (const file of ["shadertown.config.ts", "shadertown.config.js", "shadertown.config.mjs"]) {
|
|
69
|
+
try {
|
|
70
|
+
const source = await readFile(join(cwd, file), "utf8");
|
|
71
|
+
const pick = (key) => source.match(new RegExp(`${key}\\s*:\\s*["\'\`]([^"\'\`]+)`))?.[1];
|
|
72
|
+
return { outDir: pick("outDir"), registry: pick("registry"), license: pick("license") };
|
|
73
|
+
} catch {
|
|
74
|
+
// Try the next candidate.
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// --- credentials ----------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
const CREDENTIALS_PATH = join(homedir(), ".shadertown", "credentials.json");
|
|
83
|
+
|
|
84
|
+
async function readToken() {
|
|
85
|
+
// An explicit environment variable wins, so CI needs no interactive login.
|
|
86
|
+
if (process.env.SHADERTOWN_TOKEN) return process.env.SHADERTOWN_TOKEN;
|
|
87
|
+
try {
|
|
88
|
+
const raw = await readFile(CREDENTIALS_PATH, "utf8");
|
|
89
|
+
return JSON.parse(raw).token ?? undefined;
|
|
90
|
+
} catch {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function writeToken(token, licensee, registry) {
|
|
96
|
+
await mkdir(dirname(CREDENTIALS_PATH), { recursive: true });
|
|
97
|
+
await writeFile(CREDENTIALS_PATH, JSON.stringify({ token, licensee, registry }, null, 2));
|
|
98
|
+
// The token is a bearer credential; keep it off other accounts on the box.
|
|
99
|
+
await chmod(CREDENTIALS_PATH, 0o600);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function openBrowser(url) {
|
|
103
|
+
const command =
|
|
104
|
+
process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
105
|
+
try {
|
|
106
|
+
spawn(command, [url], { stdio: "ignore", detached: true }).unref();
|
|
107
|
+
} catch {
|
|
108
|
+
// Printing the URL is the fallback, and it is always printed anyway.
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
113
|
+
|
|
114
|
+
async function login(args) {
|
|
115
|
+
const { flags } = parseFlags(args);
|
|
116
|
+
const config = await readProjectConfig(process.cwd());
|
|
117
|
+
const registry = flags.registry ?? config.registry ?? DEFAULT_REGISTRY;
|
|
118
|
+
|
|
119
|
+
const startResponse = await fetch(new URL("/api/device/start", registry), { method: "POST" });
|
|
120
|
+
if (!startResponse.ok) {
|
|
121
|
+
throw new Error(`${registry} did not start a login (${startResponse.status}).`);
|
|
122
|
+
}
|
|
123
|
+
const flow = await startResponse.json();
|
|
124
|
+
|
|
125
|
+
console.log(`\n ${c.bold("shadertown")} ${c.dim(`- ${registry}`)}\n`);
|
|
126
|
+
console.log(` Open ${c.cyan(flow.verification_uri)}`);
|
|
127
|
+
console.log(` Code ${c.bold(flow.user_code)}\n`);
|
|
128
|
+
console.log(` ${c.dim("Waiting for approval...")}`);
|
|
129
|
+
|
|
130
|
+
if (!flags["no-browser"]) openBrowser(flow.verification_uri_complete ?? flow.verification_uri);
|
|
131
|
+
|
|
132
|
+
const deadline = Date.now() + (flow.expires_in ?? 600) * 1000;
|
|
133
|
+
let interval = (flow.interval ?? 2) * 1000;
|
|
134
|
+
|
|
135
|
+
while (Date.now() < deadline) {
|
|
136
|
+
await sleep(interval);
|
|
137
|
+
const response = await fetch(new URL("/api/device/poll", registry), {
|
|
138
|
+
method: "POST",
|
|
139
|
+
headers: { "content-type": "application/json" },
|
|
140
|
+
body: JSON.stringify({ device_code: flow.device_code }),
|
|
141
|
+
});
|
|
142
|
+
const body = await response.json().catch(() => ({}));
|
|
143
|
+
|
|
144
|
+
if (response.ok && body.access_token) {
|
|
145
|
+
await writeToken(body.access_token, body.licensee, registry);
|
|
146
|
+
console.log(`\n ${c.green("ok")} Signed in as ${c.bold(body.licensee ?? "your account")}`);
|
|
147
|
+
console.log(` ${c.dim(`Token stored in ${CREDENTIALS_PATH}`)}\n`);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (body.error === "slow_down") interval = (body.interval ?? 4) * 1000;
|
|
151
|
+
if (body.error === "expired_token") break;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
throw new Error("That login expired before it was approved. Run `shadertown login` again.");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function logout() {
|
|
158
|
+
await rm(CREDENTIALS_PATH, { force: true });
|
|
159
|
+
console.log(`\n ${c.green("ok")} Signed out.\n`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async function whoami() {
|
|
163
|
+
const token = await readToken();
|
|
164
|
+
if (!token) {
|
|
165
|
+
console.log(`\n ${c.dim("Not signed in. Run `shadertown login`.")}\n`);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
const raw = await readFile(CREDENTIALS_PATH, "utf8");
|
|
170
|
+
const saved = JSON.parse(raw);
|
|
171
|
+
console.log(`\n ${c.bold(saved.licensee ?? "signed in")} ${c.dim(`- ${saved.registry ?? DEFAULT_REGISTRY}`)}\n`);
|
|
172
|
+
} catch {
|
|
173
|
+
console.log(`\n ${c.dim("Signed in via SHADERTOWN_TOKEN.")}\n`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async function fetchJson(url, key) {
|
|
178
|
+
const response = await fetch(url, {
|
|
179
|
+
headers: key ? { authorization: `Bearer ${key}` } : undefined,
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
if (response.status === 402) {
|
|
183
|
+
const body = await response.json().catch(() => ({}));
|
|
184
|
+
const lines = [
|
|
185
|
+
body.message ?? "This shader requires a licence.",
|
|
186
|
+
body.reason ? c.dim(body.reason) : null,
|
|
187
|
+
body.hint ? c.dim(body.hint) : null,
|
|
188
|
+
body.upgrade ? c.cyan(body.upgrade) : null,
|
|
189
|
+
].filter(Boolean);
|
|
190
|
+
throw new Error(lines.join("\n "));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!response.ok) {
|
|
194
|
+
const body = await response.json().catch(() => ({}));
|
|
195
|
+
throw new Error(body.message ?? `${url} responded ${response.status}`);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return response.json();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function exists(path) {
|
|
202
|
+
try {
|
|
203
|
+
await access(path);
|
|
204
|
+
return true;
|
|
205
|
+
} catch {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async function add(args) {
|
|
211
|
+
const { flags, positional } = parseFlags(args);
|
|
212
|
+
if (positional.length === 0) {
|
|
213
|
+
throw new Error("Give at least one shader slug. Try `shadertown list`.");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const cwd = process.cwd();
|
|
217
|
+
const config = await readProjectConfig(cwd);
|
|
218
|
+
const registry = flags.registry ?? config.registry ?? DEFAULT_REGISTRY;
|
|
219
|
+
const outDir = resolve(cwd, flags.out ?? config.outDir ?? DEFAULT_OUT);
|
|
220
|
+
const key = await readToken();
|
|
221
|
+
|
|
222
|
+
console.log(`\n ${c.bold("shadertown")} ${c.dim(`- ${registry}`)}\n`);
|
|
223
|
+
|
|
224
|
+
for (const slug of positional) {
|
|
225
|
+
const url = new URL(`/r/${slug}.json`, registry);
|
|
226
|
+
if (flags.params) {
|
|
227
|
+
for (const [k, v] of new URLSearchParams(flags.params)) url.searchParams.set(k, v);
|
|
228
|
+
}
|
|
229
|
+
if (flags.licensee) url.searchParams.set("licensee", flags.licensee);
|
|
230
|
+
|
|
231
|
+
const item = await fetchJson(url.toString(), key);
|
|
232
|
+
await mkdir(outDir, { recursive: true });
|
|
233
|
+
|
|
234
|
+
let written = 0;
|
|
235
|
+
let skipped = 0;
|
|
236
|
+
for (const file of item.files) {
|
|
237
|
+
const target = join(outDir, file.path);
|
|
238
|
+
if ((await exists(target)) && !flags.force) {
|
|
239
|
+
skipped += 1;
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
await mkdir(dirname(target), { recursive: true });
|
|
243
|
+
await writeFile(target, file.content);
|
|
244
|
+
written += 1;
|
|
245
|
+
console.log(` ${c.green("add")} ${relative(cwd, target)}`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (skipped > 0) {
|
|
249
|
+
console.log(` ${c.yellow("skip")} ${skipped} existing file(s) ${c.dim("- pass --force to overwrite")}`);
|
|
250
|
+
}
|
|
251
|
+
console.log(` ${c.dim(`${item.name} - ${item.tagline}`)}`);
|
|
252
|
+
if (written > 0) {
|
|
253
|
+
console.log(` ${c.dim(`Read ${slug}/README.md for every control.`)}`);
|
|
254
|
+
}
|
|
255
|
+
console.log("");
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
console.log(` ${c.dim("Next: import the preset and pass it to <ShaderCanvas preset={...} />")}\n`);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async function list(args) {
|
|
262
|
+
const { flags } = parseFlags(args);
|
|
263
|
+
const config = await readProjectConfig(process.cwd());
|
|
264
|
+
const registry = flags.registry ?? config.registry ?? DEFAULT_REGISTRY;
|
|
265
|
+
const index = await fetchJson(new URL("/r/", registry).toString());
|
|
266
|
+
|
|
267
|
+
console.log(`\n ${c.bold("shadertown")} ${c.dim(`- ${index.items.length} shaders`)}\n`);
|
|
268
|
+
const width = Math.max(...index.items.map((item) => item.slug.length));
|
|
269
|
+
let free = 0;
|
|
270
|
+
for (const item of index.items) {
|
|
271
|
+
const isFree = item.tier === "free";
|
|
272
|
+
if (isFree) free += 1;
|
|
273
|
+
// Only free is marked. Professional is the default, so marking it would
|
|
274
|
+
// put a badge on almost every row and say nothing.
|
|
275
|
+
const gate = isFree ? c.green(" free") : " ";
|
|
276
|
+
console.log(` ${item.slug.padEnd(width)}${gate} ${c.dim(item.tagline)}`);
|
|
277
|
+
}
|
|
278
|
+
if (free < index.items.length) {
|
|
279
|
+
console.log(
|
|
280
|
+
`\n ${c.dim("Unmarked shaders need the Professional plan for their source. Tuning is free on all of them.")}`,
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
console.log("");
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async function init() {
|
|
287
|
+
const target = resolve(process.cwd(), "shadertown.config.ts");
|
|
288
|
+
if (await exists(target)) throw new Error("shadertown.config.ts already exists.");
|
|
289
|
+
|
|
290
|
+
await writeFile(
|
|
291
|
+
target,
|
|
292
|
+
`import { defineShadertownConfig } from "shadertown";
|
|
293
|
+
|
|
294
|
+
export default defineShadertownConfig({
|
|
295
|
+
outDir: "${DEFAULT_OUT}",
|
|
296
|
+
registry: "${DEFAULT_REGISTRY}",
|
|
297
|
+
// Name of the environment variable holding your key - never the key itself.
|
|
298
|
+
license: "SHADERTOWN_KEY",
|
|
299
|
+
});
|
|
300
|
+
`,
|
|
301
|
+
);
|
|
302
|
+
console.log(`\n ${c.green("add")} shadertown.config.ts\n`);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function relative(from, to) {
|
|
306
|
+
return to.startsWith(from) ? to.slice(from.length + 1) : to;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function help() {
|
|
310
|
+
console.log(`
|
|
311
|
+
${c.bold("shadertown")} - vendor WebGPU shaders into your codebase
|
|
312
|
+
|
|
313
|
+
${c.dim("Usage")}
|
|
314
|
+
npx shadertown <command> [options]
|
|
315
|
+
|
|
316
|
+
${c.dim("Commands")}
|
|
317
|
+
login Connect this terminal to your shadertown account
|
|
318
|
+
logout Forget the stored token
|
|
319
|
+
whoami Show who this terminal is signed in as
|
|
320
|
+
add <slug...> Write a shader's WGSL and typed preset into your repo
|
|
321
|
+
list Print the catalogue
|
|
322
|
+
init Create shadertown.config.ts
|
|
323
|
+
|
|
324
|
+
${c.dim("Options")}
|
|
325
|
+
--out <dir> Output directory ${c.dim(`(default: ${DEFAULT_OUT})`)}
|
|
326
|
+
--params <query> Tuned values from a detail page URL
|
|
327
|
+
--registry <url> Registry base URL ${c.dim(`(default: ${DEFAULT_REGISTRY})`)}
|
|
328
|
+
--licensee <name> Name to issue the LICENSE to
|
|
329
|
+
--force Overwrite existing files
|
|
330
|
+
|
|
331
|
+
${c.dim("Examples")}
|
|
332
|
+
npx shadertown add aurora
|
|
333
|
+
npx shadertown add aurora --params "speed=0.42&exposure=1.6"
|
|
334
|
+
npx shadertown add voronoi tunnel --out app/shaders
|
|
335
|
+
`);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async function version() {
|
|
339
|
+
const pkg = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8"));
|
|
340
|
+
console.log(pkg.version);
|
|
341
|
+
}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ShaderName, ShaderParams } from "./registry.js";
|
|
2
|
+
import type { PlayMode, QualityOptions } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* A tuned shader, ready to hand to `<ShaderCanvas />` or `createShaderRenderer`.
|
|
5
|
+
* This object is the thing you actually author: the slider positions you
|
|
6
|
+
* settled on, in a form your editor can type-check.
|
|
7
|
+
*/
|
|
8
|
+
export interface ShaderConfig<K extends ShaderName = ShaderName> {
|
|
9
|
+
readonly shader: K;
|
|
10
|
+
readonly params?: ShaderParams<K>;
|
|
11
|
+
readonly quality?: QualityOptions;
|
|
12
|
+
readonly play?: PlayMode;
|
|
13
|
+
/** Free-text note, kept so exported presets can explain themselves. */
|
|
14
|
+
readonly note?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Identity at runtime; it exists so `params` is checked against `shader`. */
|
|
17
|
+
export declare function defineShader<const K extends ShaderName>(config: ShaderConfig<K>): ShaderConfig<K>;
|
|
18
|
+
export interface ShadertownConfig {
|
|
19
|
+
/** Where `shadertown add` writes vendored shaders. */
|
|
20
|
+
readonly outDir?: string;
|
|
21
|
+
/** Registry base URL. Point this at a fork to serve your own catalogue. */
|
|
22
|
+
readonly registry?: string;
|
|
23
|
+
/** License key, or the name of the env var holding it. */
|
|
24
|
+
readonly license?: string;
|
|
25
|
+
/** Named presets, so a project refers to `presets.hero` rather than a slug. */
|
|
26
|
+
readonly presets?: Readonly<Record<string, ShaderConfig>>;
|
|
27
|
+
}
|
|
28
|
+
export declare function defineShadertownConfig(config: ShadertownConfig): ShadertownConfig;
|
|
29
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU;IAC7D,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnB,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;IACzB,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,UAAU,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAEjG;AAED,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;CAC3D;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAEjF"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAiBA,8EAA8E;AAC9E,MAAM,UAAU,YAAY,CAA6B,MAAuB;IAC9E,OAAO,MAAM,CAAC;AAChB,CAAC;AAaD,MAAM,UAAU,sBAAsB,CAAC,MAAwB;IAC7D,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/export.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ShaderName, type ShaderParams } from "./registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Only the values that differ from the registry defaults. Exported snippets
|
|
4
|
+
* stay short, and a shader's defaults can improve later without silently
|
|
5
|
+
* changing anyone's pinned look.
|
|
6
|
+
*/
|
|
7
|
+
export declare function diffParams<K extends ShaderName>(name: K, params: ShaderParams<K>): Record<string, number | string>;
|
|
8
|
+
/** A `shader.config.ts` module: the tuned preset, typed against the registry. */
|
|
9
|
+
export declare function toConfigSource<K extends ShaderName>(name: K, params: ShaderParams<K>): string;
|
|
10
|
+
/** A drop-in React usage snippet for the current settings. */
|
|
11
|
+
export declare function toReactSource<K extends ShaderName>(name: K, params: ShaderParams<K>): string;
|
|
12
|
+
/** The imperative form, for codebases that are not React. */
|
|
13
|
+
export declare function toVanillaSource<K extends ShaderName>(name: K, params: ShaderParams<K>): string;
|
|
14
|
+
/** The complete, self-contained WGSL for this shader. */
|
|
15
|
+
export declare function toWgslSource<K extends ShaderName>(name: K): string;
|
|
16
|
+
export declare function toInstallCommand<K extends ShaderName>(name: K): string;
|
|
17
|
+
/** A paste-ready component wired with the tuned parameters. */
|
|
18
|
+
export declare function toExampleSource<K extends ShaderName>(name: K, params: ShaderParams<K>): string;
|
|
19
|
+
/**
|
|
20
|
+
* Per-shader documentation, generated from the registry rather than written by
|
|
21
|
+
* hand — the control table cannot drift out of date with the shader.
|
|
22
|
+
*/
|
|
23
|
+
export declare function toReadme<K extends ShaderName>(name: K, params: ShaderParams<K>): string;
|
|
24
|
+
export interface LicenceHolder {
|
|
25
|
+
readonly name?: string;
|
|
26
|
+
readonly order?: string;
|
|
27
|
+
}
|
|
28
|
+
/** The licence that ships with a purchased shader, issued to the buyer. */
|
|
29
|
+
export declare function toLicense<K extends ShaderName>(name: K, holder?: LicenceHolder): string;
|
|
30
|
+
//# sourceMappingURL=export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEnF;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,UAAU,EAC7C,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GACtB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAQjC;AAgBD,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CAW7F;AAED,8DAA8D;AAC9D,wBAAgB,aAAa,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CAoB5F;AAED,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CAkB9F;AAED,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,CAElE;AAED,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,CAEtE;AAOD,+DAA+D;AAC/D,wBAAgB,eAAe,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CAwB9F;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CA6FvF;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,GAAE,aAAkB,GAAG,MAAM,CAwB3F"}
|