gooseworks 0.2.2 → 0.2.5
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/.claude-plugin/plugin.json +4 -2
- package/README.md +31 -4
- package/dist/agents/claude.d.ts.map +1 -1
- package/dist/agents/claude.js +4 -3
- package/dist/agents/claude.js.map +1 -1
- package/dist/agents/codex.d.ts.map +1 -1
- package/dist/agents/codex.js +4 -3
- package/dist/agents/codex.js.map +1 -1
- package/dist/auth/oauth-server.d.ts.map +1 -1
- package/dist/auth/oauth-server.js +27 -19
- package/dist/auth/oauth-server.js.map +1 -1
- package/dist/commands/formats.d.ts +3 -0
- package/dist/commands/formats.d.ts.map +1 -0
- package/dist/commands/formats.js +155 -0
- package/dist/commands/formats.js.map +1 -0
- package/dist/commands/graphics/get-flow.d.ts +30 -0
- package/dist/commands/graphics/get-flow.d.ts.map +1 -0
- package/dist/commands/graphics/get-flow.js +212 -0
- package/dist/commands/graphics/get-flow.js.map +1 -0
- package/dist/commands/graphics/publish-flow.d.ts +28 -0
- package/dist/commands/graphics/publish-flow.d.ts.map +1 -0
- package/dist/commands/graphics/publish-flow.js +178 -0
- package/dist/commands/graphics/publish-flow.js.map +1 -0
- package/dist/commands/graphics/shared.d.ts +48 -0
- package/dist/commands/graphics/shared.d.ts.map +1 -0
- package/dist/commands/graphics/shared.js +181 -0
- package/dist/commands/graphics/shared.js.map +1 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +29 -1
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/styles.d.ts +3 -0
- package/dist/commands/styles.d.ts.map +1 -0
- package/dist/commands/styles.js +157 -0
- package/dist/commands/styles.js.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/graphics-api.d.ts +106 -0
- package/dist/lib/graphics-api.d.ts.map +1 -0
- package/dist/lib/graphics-api.js +289 -0
- package/dist/lib/graphics-api.js.map +1 -0
- package/dist/lib/graphics-cache.d.ts +31 -0
- package/dist/lib/graphics-cache.d.ts.map +1 -0
- package/dist/lib/graphics-cache.js +126 -0
- package/dist/lib/graphics-cache.js.map +1 -0
- package/dist/lib/graphics-manifest.d.ts +96 -0
- package/dist/lib/graphics-manifest.d.ts.map +1 -0
- package/dist/lib/graphics-manifest.js +289 -0
- package/dist/lib/graphics-manifest.js.map +1 -0
- package/dist/skills/installer.d.ts +7 -0
- package/dist/skills/installer.d.ts.map +1 -1
- package/dist/skills/installer.js +114 -2
- package/dist/skills/installer.js.map +1 -1
- package/dist/skills/names.d.ts +2 -0
- package/dist/skills/names.d.ts.map +1 -0
- package/dist/skills/names.js +7 -0
- package/dist/skills/names.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HTTP client for the Gooseworks graphics API.
|
|
4
|
+
*
|
|
5
|
+
* Uses the global fetch (Node 18+) and FormData/Blob for multipart uploads.
|
|
6
|
+
* Endpoint shapes are documented in gooseworks-app GOOSE-1468.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.NetworkError = exports.ApiError = void 0;
|
|
43
|
+
exports.listStyles = listStyles;
|
|
44
|
+
exports.listFormats = listFormats;
|
|
45
|
+
exports.getStyleRecord = getStyleRecord;
|
|
46
|
+
exports.getFormatRecord = getFormatRecord;
|
|
47
|
+
exports.getStyleDesignMd = getStyleDesignMd;
|
|
48
|
+
exports.getFormatSpecMd = getFormatSpecMd;
|
|
49
|
+
exports.publishStyle = publishStyle;
|
|
50
|
+
exports.updateStyle = updateStyle;
|
|
51
|
+
exports.deleteStyle = deleteStyle;
|
|
52
|
+
exports.publishFormat = publishFormat;
|
|
53
|
+
exports.updateFormat = updateFormat;
|
|
54
|
+
exports.deleteFormat = deleteFormat;
|
|
55
|
+
exports.downloadBytes = downloadBytes;
|
|
56
|
+
const fs = __importStar(require("fs"));
|
|
57
|
+
const path = __importStar(require("path"));
|
|
58
|
+
class ApiError extends Error {
|
|
59
|
+
status;
|
|
60
|
+
code;
|
|
61
|
+
body;
|
|
62
|
+
constructor(status, code, message, body) {
|
|
63
|
+
super(message);
|
|
64
|
+
this.status = status;
|
|
65
|
+
this.code = code;
|
|
66
|
+
this.body = body;
|
|
67
|
+
this.name = 'ApiError';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.ApiError = ApiError;
|
|
71
|
+
class NetworkError extends Error {
|
|
72
|
+
cause;
|
|
73
|
+
constructor(message, cause) {
|
|
74
|
+
super(message);
|
|
75
|
+
this.cause = cause;
|
|
76
|
+
this.name = 'NetworkError';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.NetworkError = NetworkError;
|
|
80
|
+
function authHeaders(apiKey) {
|
|
81
|
+
return apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
|
|
82
|
+
}
|
|
83
|
+
async function readJsonSafe(res) {
|
|
84
|
+
const text = await res.text();
|
|
85
|
+
if (!text)
|
|
86
|
+
return null;
|
|
87
|
+
try {
|
|
88
|
+
return JSON.parse(text);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return text;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function extractMessage(body, fallback) {
|
|
95
|
+
if (body && typeof body === 'object') {
|
|
96
|
+
const env = body;
|
|
97
|
+
if (typeof env.message === 'string')
|
|
98
|
+
return env.message;
|
|
99
|
+
if (typeof env.error === 'string')
|
|
100
|
+
return env.error;
|
|
101
|
+
}
|
|
102
|
+
return fallback;
|
|
103
|
+
}
|
|
104
|
+
async function asApiError(res, defaultMessage) {
|
|
105
|
+
const body = await readJsonSafe(res);
|
|
106
|
+
let code = null;
|
|
107
|
+
if (body && typeof body === 'object' && typeof body.error === 'string') {
|
|
108
|
+
code = body.error || null;
|
|
109
|
+
}
|
|
110
|
+
return new ApiError(res.status, code, extractMessage(body, defaultMessage), body);
|
|
111
|
+
}
|
|
112
|
+
async function safeFetch(url, init) {
|
|
113
|
+
try {
|
|
114
|
+
return await fetch(url, init);
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
118
|
+
throw new NetworkError(message, err);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function buildQuery(q) {
|
|
122
|
+
const params = new URLSearchParams();
|
|
123
|
+
if (q.q)
|
|
124
|
+
params.set('q', q.q);
|
|
125
|
+
if (q.mood)
|
|
126
|
+
params.set('mood', q.mood);
|
|
127
|
+
if (q.tag)
|
|
128
|
+
params.set('tag', q.tag);
|
|
129
|
+
if (q.featured)
|
|
130
|
+
params.set('featured', 'true');
|
|
131
|
+
if (q.limit !== undefined)
|
|
132
|
+
params.set('limit', String(q.limit));
|
|
133
|
+
if (q.offset !== undefined)
|
|
134
|
+
params.set('offset', String(q.offset));
|
|
135
|
+
const s = params.toString();
|
|
136
|
+
return s ? `?${s}` : '';
|
|
137
|
+
}
|
|
138
|
+
async function getJsonEnvelope(url, apiKey) {
|
|
139
|
+
const res = await safeFetch(url, {
|
|
140
|
+
method: 'GET',
|
|
141
|
+
headers: { Accept: 'application/json', ...authHeaders(apiKey) },
|
|
142
|
+
});
|
|
143
|
+
if (!res.ok)
|
|
144
|
+
throw await asApiError(res, `request failed (${res.status})`);
|
|
145
|
+
const body = (await readJsonSafe(res));
|
|
146
|
+
if (!body || body.status !== 'success') {
|
|
147
|
+
throw new ApiError(res.status, null, 'unexpected response shape', body);
|
|
148
|
+
}
|
|
149
|
+
return body;
|
|
150
|
+
}
|
|
151
|
+
async function listStyles(opts, query = {}) {
|
|
152
|
+
const url = `${opts.apiBase}/api/graphics/styles${buildQuery(query)}`;
|
|
153
|
+
return getJsonEnvelope(url, opts.apiKey);
|
|
154
|
+
}
|
|
155
|
+
async function listFormats(opts, query = {}) {
|
|
156
|
+
const url = `${opts.apiBase}/api/graphics/formats${buildQuery(query)}`;
|
|
157
|
+
return getJsonEnvelope(url, opts.apiKey);
|
|
158
|
+
}
|
|
159
|
+
async function fetchRecord(url, apiKey, etag) {
|
|
160
|
+
const headers = {
|
|
161
|
+
Accept: 'application/json',
|
|
162
|
+
...authHeaders(apiKey),
|
|
163
|
+
};
|
|
164
|
+
if (etag)
|
|
165
|
+
headers['If-None-Match'] = etag;
|
|
166
|
+
const res = await safeFetch(url, { method: 'GET', headers });
|
|
167
|
+
if (res.status === 304) {
|
|
168
|
+
return { status: 304, envelope: null, etag };
|
|
169
|
+
}
|
|
170
|
+
if (!res.ok)
|
|
171
|
+
throw await asApiError(res, `request failed (${res.status})`);
|
|
172
|
+
const body = (await readJsonSafe(res));
|
|
173
|
+
if (!body || body.status !== 'success') {
|
|
174
|
+
throw new ApiError(res.status, null, 'unexpected response shape', body);
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
status: 200,
|
|
178
|
+
envelope: body,
|
|
179
|
+
etag: res.headers.get('etag'),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
async function getStyleRecord(opts, slug, etag = null) {
|
|
183
|
+
const url = `${opts.apiBase}/api/graphics/styles/${encodeURIComponent(slug)}`;
|
|
184
|
+
return fetchRecord(url, opts.apiKey, etag);
|
|
185
|
+
}
|
|
186
|
+
async function getFormatRecord(opts, slug, etag = null) {
|
|
187
|
+
const url = `${opts.apiBase}/api/graphics/formats/${encodeURIComponent(slug)}`;
|
|
188
|
+
return fetchRecord(url, opts.apiKey, etag);
|
|
189
|
+
}
|
|
190
|
+
async function fetchMarkdown(url, apiKey, etag) {
|
|
191
|
+
const headers = {
|
|
192
|
+
Accept: 'text/plain',
|
|
193
|
+
...authHeaders(apiKey),
|
|
194
|
+
};
|
|
195
|
+
if (etag)
|
|
196
|
+
headers['If-None-Match'] = etag;
|
|
197
|
+
const res = await safeFetch(url, { method: 'GET', headers });
|
|
198
|
+
if (res.status === 304) {
|
|
199
|
+
return { status: 304, body: null, etag };
|
|
200
|
+
}
|
|
201
|
+
if (!res.ok)
|
|
202
|
+
throw await asApiError(res, `request failed (${res.status})`);
|
|
203
|
+
const body = await res.text();
|
|
204
|
+
return { status: 200, body, etag: res.headers.get('etag') };
|
|
205
|
+
}
|
|
206
|
+
async function getStyleDesignMd(opts, slug, etag = null) {
|
|
207
|
+
const url = `${opts.apiBase}/api/graphics/styles/${encodeURIComponent(slug)}/design.md`;
|
|
208
|
+
return fetchMarkdown(url, opts.apiKey, etag);
|
|
209
|
+
}
|
|
210
|
+
async function getFormatSpecMd(opts, slug, etag = null) {
|
|
211
|
+
const url = `${opts.apiBase}/api/graphics/formats/${encodeURIComponent(slug)}/spec.md`;
|
|
212
|
+
return fetchMarkdown(url, opts.apiKey, etag);
|
|
213
|
+
}
|
|
214
|
+
function buildMultipart(manifest, files) {
|
|
215
|
+
const fd = new FormData();
|
|
216
|
+
fd.append('manifest', JSON.stringify(manifest));
|
|
217
|
+
for (const f of files) {
|
|
218
|
+
const buf = fs.readFileSync(f.absolutePath);
|
|
219
|
+
// Node's Blob accepts a Uint8Array. We use the file's basename as the
|
|
220
|
+
// filename, but the field name carries the manifest reference (with "./"
|
|
221
|
+
// stripped) so the server can match it back to the manifest entry.
|
|
222
|
+
const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
223
|
+
const blob = new Blob([ab]);
|
|
224
|
+
fd.append(f.fieldName, blob, path.basename(f.absolutePath));
|
|
225
|
+
}
|
|
226
|
+
return fd;
|
|
227
|
+
}
|
|
228
|
+
async function readWriteResponse(res) {
|
|
229
|
+
const body = (await readJsonSafe(res));
|
|
230
|
+
if (!body || body.status !== 'success' || !body.data?.slug || !body.data.id) {
|
|
231
|
+
throw new ApiError(res.status, null, 'unexpected write response shape', body);
|
|
232
|
+
}
|
|
233
|
+
return { slug: body.data.slug, id: body.data.id };
|
|
234
|
+
}
|
|
235
|
+
async function postMultipart(url, apiKey, manifest, files, method) {
|
|
236
|
+
const fd = buildMultipart(manifest, files);
|
|
237
|
+
const res = await safeFetch(url, {
|
|
238
|
+
method,
|
|
239
|
+
headers: authHeaders(apiKey),
|
|
240
|
+
body: fd,
|
|
241
|
+
});
|
|
242
|
+
if (!res.ok)
|
|
243
|
+
throw await asApiError(res, `${method} ${url} failed (${res.status})`);
|
|
244
|
+
return readWriteResponse(res);
|
|
245
|
+
}
|
|
246
|
+
async function publishStyle(opts, manifest, files) {
|
|
247
|
+
const url = `${opts.apiBase}/api/graphics/styles`;
|
|
248
|
+
return postMultipart(url, opts.apiKey, manifest, files, 'POST');
|
|
249
|
+
}
|
|
250
|
+
async function updateStyle(opts, slug, manifest, files) {
|
|
251
|
+
const url = `${opts.apiBase}/api/graphics/styles/${encodeURIComponent(slug)}`;
|
|
252
|
+
return postMultipart(url, opts.apiKey, manifest, files, 'PATCH');
|
|
253
|
+
}
|
|
254
|
+
async function deleteStyle(opts, slug) {
|
|
255
|
+
const url = `${opts.apiBase}/api/graphics/styles/${encodeURIComponent(slug)}`;
|
|
256
|
+
const res = await safeFetch(url, {
|
|
257
|
+
method: 'DELETE',
|
|
258
|
+
headers: authHeaders(opts.apiKey),
|
|
259
|
+
});
|
|
260
|
+
if (!res.ok)
|
|
261
|
+
throw await asApiError(res, `DELETE ${url} failed (${res.status})`);
|
|
262
|
+
}
|
|
263
|
+
async function publishFormat(opts, manifest, files) {
|
|
264
|
+
const url = `${opts.apiBase}/api/graphics/formats`;
|
|
265
|
+
return postMultipart(url, opts.apiKey, manifest, files, 'POST');
|
|
266
|
+
}
|
|
267
|
+
async function updateFormat(opts, slug, manifest, files) {
|
|
268
|
+
const url = `${opts.apiBase}/api/graphics/formats/${encodeURIComponent(slug)}`;
|
|
269
|
+
return postMultipart(url, opts.apiKey, manifest, files, 'PATCH');
|
|
270
|
+
}
|
|
271
|
+
async function deleteFormat(opts, slug) {
|
|
272
|
+
const url = `${opts.apiBase}/api/graphics/formats/${encodeURIComponent(slug)}`;
|
|
273
|
+
const res = await safeFetch(url, {
|
|
274
|
+
method: 'DELETE',
|
|
275
|
+
headers: authHeaders(opts.apiKey),
|
|
276
|
+
});
|
|
277
|
+
if (!res.ok)
|
|
278
|
+
throw await asApiError(res, `DELETE ${url} failed (${res.status})`);
|
|
279
|
+
}
|
|
280
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
281
|
+
// Example PNG download (for `get --include-examples`)
|
|
282
|
+
async function downloadBytes(url) {
|
|
283
|
+
const res = await safeFetch(url, { method: 'GET' });
|
|
284
|
+
if (!res.ok)
|
|
285
|
+
throw await asApiError(res, `download failed (${res.status})`);
|
|
286
|
+
const ab = await res.arrayBuffer();
|
|
287
|
+
return Buffer.from(ab);
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=graphics-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphics-api.js","sourceRoot":"","sources":["../../src/lib/graphics-api.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4JH,gCAMC;AAED,kCAMC;AA4CD,wCAOC;AAED,0CAOC;AA6BD,4CAOC;AAED,0CAOC;AA0DD,oCAOC;AAED,kCAQC;AAED,kCAUC;AAED,sCAOC;AAED,oCAQC;AAED,oCAUC;AAKD,sCAKC;AAjZD,uCAAyB;AACzB,2CAA6B;AAc7B,MAAa,QAAS,SAAQ,KAAK;IAEf;IACA;IAEA;IAJlB,YACkB,MAAc,EACd,IAAmB,EACnC,OAAe,EACC,IAAc;QAE9B,KAAK,CAAC,OAAO,CAAC,CAAC;QALC,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAe;QAEnB,SAAI,GAAJ,IAAI,CAAU;QAG9B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAVD,4BAUC;AAED,MAAa,YAAa,SAAQ,KAAK;IACQ;IAA7C,YAAY,OAAe,EAAkB,KAAe;QAC1D,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,UAAK,GAAL,KAAK,CAAU;QAE1D,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AALD,oCAKC;AAWD,SAAS,WAAW,CAAC,MAAsB;IACzC,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7D,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,GAAa;IACvC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,IAAa,EAAE,QAAgB;IACrD,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAqB,CAAC;QAClC,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,OAAO,CAAC;QACxD,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,KAAK,CAAC;IACtD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,GAAa,EAAE,cAAsB;IAC7D,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,IAAI,GAAkB,IAAI,CAAC;IAC/B,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAQ,IAAsB,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC1F,IAAI,GAAI,IAAsB,CAAC,KAAK,IAAI,IAAI,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC;AACpF,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,IAAiB;IACrD,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAcD,SAAS,UAAU,CAAC,CAAY;IAC9B,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,IAAI,CAAC,CAAC,CAAC;QAAE,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,CAAC,IAAI;QAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,CAAC,GAAG;QAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,CAAC,CAAC,QAAQ;QAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC/C,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAChE,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;QAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACnE,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC5B,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1B,CAAC;AAgCD,KAAK,UAAU,eAAe,CAC5B,GAAW,EACX,MAAsB;IAEtB,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;QAC/B,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,EAAE;KAChE,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,mBAAmB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3E,MAAM,IAAI,GAAG,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,CAAwC,CAAC;IAC9E,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACvC,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,2BAA2B,EAAE,IAAI,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,IAAS,CAAC;AACnB,CAAC;AAEM,KAAK,UAAU,UAAU,CAC9B,IAAsB,EACtB,QAAmB,EAAE;IAErB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,uBAAuB,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;IACtE,OAAO,eAAe,CAAoC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AAC9E,CAAC;AAEM,KAAK,UAAU,WAAW,CAC/B,IAAsB,EACtB,QAAmB,EAAE;IAErB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,wBAAwB,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;IACvE,OAAO,eAAe,CAAqC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/E,CAAC;AAiBD,KAAK,UAAU,WAAW,CACxB,GAAW,EACX,MAAiC,EACjC,IAAmB;IAEnB,MAAM,OAAO,GAA2B;QACtC,MAAM,EAAE,kBAAkB;QAC1B,GAAG,WAAW,CAAC,MAAM,CAAC;KACvB,CAAC;IACF,IAAI,IAAI;QAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;IAE1C,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IAC7D,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC/C,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,mBAAmB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3E,MAAM,IAAI,GAAG,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,CAAwC,CAAC;IAC9E,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACvC,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,2BAA2B,EAAE,IAAI,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO;QACL,MAAM,EAAE,GAAG;QACX,QAAQ,EAAE,IAAuB;QACjC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;KAC9B,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,cAAc,CAClC,IAAsB,EACtB,IAAY,EACZ,OAAsB,IAAI;IAE1B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,wBAAwB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;IAC9E,OAAO,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AAEM,KAAK,UAAU,eAAe,CACnC,IAAsB,EACtB,IAAY,EACZ,OAAsB,IAAI;IAE1B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,yBAAyB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;IAC/E,OAAO,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AASD,KAAK,UAAU,aAAa,CAC1B,GAAW,EACX,MAAiC,EACjC,IAAmB;IAEnB,MAAM,OAAO,GAA2B;QACtC,MAAM,EAAE,YAAY;QACpB,GAAG,WAAW,CAAC,MAAM,CAAC;KACvB,CAAC;IACF,IAAI,IAAI;QAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;IAE1C,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IAC7D,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3C,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,mBAAmB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3E,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;AAC9D,CAAC;AAEM,KAAK,UAAU,gBAAgB,CACpC,IAAsB,EACtB,IAAY,EACZ,OAAsB,IAAI;IAE1B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,wBAAwB,kBAAkB,CAAC,IAAI,CAAC,YAAY,CAAC;IACxF,OAAO,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC;AAEM,KAAK,UAAU,eAAe,CACnC,IAAsB,EACtB,IAAY,EACZ,OAAsB,IAAI;IAE1B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,yBAAyB,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC;IACvF,OAAO,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC;AAUD,SAAS,cAAc,CACrB,QAAiB,EACjB,KAA4B;IAE5B,MAAM,EAAE,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC1B,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QAC5C,sEAAsE;QACtE,yEAAyE;QACzE,mEAAmE;QACnE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CACzB,GAAG,CAAC,UAAU,EACd,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU,CACjB,CAAC;QACjB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,GAAa;IAC5C,MAAM,IAAI,GAAG,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,CAE7B,CAAC;IACT,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QAC5E,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,iCAAiC,EAAE,IAAI,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;AACpD,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,GAAW,EACX,MAAc,EACd,QAAiB,EACjB,KAA4B,EAC5B,MAAwB;IAExB,MAAM,EAAE,GAAG,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;QAC/B,MAAM;QACN,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC;QAC5B,IAAI,EAAE,EAAE;KACT,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,GAAG,MAAM,IAAI,GAAG,YAAY,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACpF,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAEM,KAAK,UAAU,YAAY,CAChC,IAA4B,EAC5B,QAAiB,EACjB,KAA4B;IAE5B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,sBAAsB,CAAC;IAClD,OAAO,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAClE,CAAC;AAEM,KAAK,UAAU,WAAW,CAC/B,IAA4B,EAC5B,IAAY,EACZ,QAAiB,EACjB,KAA4B;IAE5B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,wBAAwB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;IAC9E,OAAO,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AACnE,CAAC;AAEM,KAAK,UAAU,WAAW,CAC/B,IAA4B,EAC5B,IAAY;IAEZ,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,wBAAwB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;IAC9E,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;QAC/B,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;KAClC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,UAAU,GAAG,YAAY,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;AACnF,CAAC;AAEM,KAAK,UAAU,aAAa,CACjC,IAA4B,EAC5B,QAAiB,EACjB,KAA4B;IAE5B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,uBAAuB,CAAC;IACnD,OAAO,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAClE,CAAC;AAEM,KAAK,UAAU,YAAY,CAChC,IAA4B,EAC5B,IAAY,EACZ,QAAiB,EACjB,KAA4B;IAE5B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,yBAAyB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;IAC/E,OAAO,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AACnE,CAAC;AAEM,KAAK,UAAU,YAAY,CAChC,IAA4B,EAC5B,IAAY;IAEZ,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,yBAAyB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;IAC/E,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;QAC/B,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;KAClC,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,UAAU,GAAG,YAAY,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;AACnF,CAAC;AAED,gFAAgF;AAChF,sDAAsD;AAE/C,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,oBAAoB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5E,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ETag-keyed disk cache for the graphics design.md/spec.md endpoints.
|
|
3
|
+
*
|
|
4
|
+
* Layout:
|
|
5
|
+
* ~/.gooseworks/cache/graphics/styles/<slug>.md
|
|
6
|
+
* ~/.gooseworks/cache/graphics/styles/<slug>.md.etag
|
|
7
|
+
* ~/.gooseworks/cache/graphics/styles/<slug>.json
|
|
8
|
+
* ~/.gooseworks/cache/graphics/styles/<slug>.json.etag
|
|
9
|
+
* ~/.gooseworks/cache/graphics/formats/<slug>.md
|
|
10
|
+
* …
|
|
11
|
+
*
|
|
12
|
+
* Freshness is implicit (HTTP ETag handles it); there's no fixed TTL.
|
|
13
|
+
*/
|
|
14
|
+
export type Resource = 'styles' | 'formats';
|
|
15
|
+
export type Variant = 'md' | 'json';
|
|
16
|
+
export interface CacheEntry {
|
|
17
|
+
body: string;
|
|
18
|
+
etag: string | null;
|
|
19
|
+
}
|
|
20
|
+
export declare function readCache(resource: Resource, slug: string, variant: Variant): CacheEntry | null;
|
|
21
|
+
/**
|
|
22
|
+
* Atomically writes the cache body and (optionally) etag. Each file is
|
|
23
|
+
* written via a PID-suffixed temp file then renamed, so a crash mid-write
|
|
24
|
+
* never leaves a torn body file readable. Concurrent writers can still
|
|
25
|
+
* race on body-vs-etag consistency, but that race is self-healing on the
|
|
26
|
+
* next fetch (mismatched etag → 200 with fresh body → both rewritten).
|
|
27
|
+
*/
|
|
28
|
+
export declare function writeCache(resource: Resource, slug: string, variant: Variant, body: string, etag: string | null): void;
|
|
29
|
+
/** Test seam — exposes the resolved cache root for unit tests. */
|
|
30
|
+
export declare function getCacheRoot(): string;
|
|
31
|
+
//# sourceMappingURL=graphics-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphics-cache.d.ts","sourceRoot":"","sources":["../../src/lib/graphics-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC5C,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG,MAAM,CAAC;AAsBpC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,wBAAgB,SAAS,CACvB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,GACf,UAAU,GAAG,IAAI,CAcnB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,IAAI,GAClB,IAAI,CAeN;AAQD,kEAAkE;AAClE,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ETag-keyed disk cache for the graphics design.md/spec.md endpoints.
|
|
4
|
+
*
|
|
5
|
+
* Layout:
|
|
6
|
+
* ~/.gooseworks/cache/graphics/styles/<slug>.md
|
|
7
|
+
* ~/.gooseworks/cache/graphics/styles/<slug>.md.etag
|
|
8
|
+
* ~/.gooseworks/cache/graphics/styles/<slug>.json
|
|
9
|
+
* ~/.gooseworks/cache/graphics/styles/<slug>.json.etag
|
|
10
|
+
* ~/.gooseworks/cache/graphics/formats/<slug>.md
|
|
11
|
+
* …
|
|
12
|
+
*
|
|
13
|
+
* Freshness is implicit (HTTP ETag handles it); there's no fixed TTL.
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.readCache = readCache;
|
|
50
|
+
exports.writeCache = writeCache;
|
|
51
|
+
exports.getCacheRoot = getCacheRoot;
|
|
52
|
+
const fs = __importStar(require("fs"));
|
|
53
|
+
const path = __importStar(require("path"));
|
|
54
|
+
const os = __importStar(require("os"));
|
|
55
|
+
const graphics_manifest_1 = require("./graphics-manifest");
|
|
56
|
+
function getCacheRootInternal() {
|
|
57
|
+
return (process.env.GOOSEWORKS_GRAPHICS_CACHE_DIR ||
|
|
58
|
+
path.join(os.homedir(), '.gooseworks', 'cache', 'graphics'));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Returns the cache file path for a slug, or null if the slug fails the
|
|
62
|
+
* public grammar. Returning null instead of throwing means a malformed user
|
|
63
|
+
* arg falls through to the network layer (which will reject it with a
|
|
64
|
+
* normal 404), rather than crashing the CLI before any request is made.
|
|
65
|
+
* The check also blocks path traversal via slugs sourced from server JSON.
|
|
66
|
+
*/
|
|
67
|
+
function pathFor(resource, slug, variant) {
|
|
68
|
+
if (!graphics_manifest_1.SLUG_RE.test(slug))
|
|
69
|
+
return null;
|
|
70
|
+
const ext = variant === 'md' ? '.md' : '.json';
|
|
71
|
+
return path.join(getCacheRootInternal(), resource, `${slug}${ext}`);
|
|
72
|
+
}
|
|
73
|
+
function readCache(resource, slug, variant) {
|
|
74
|
+
const bodyPath = pathFor(resource, slug, variant);
|
|
75
|
+
if (!bodyPath)
|
|
76
|
+
return null;
|
|
77
|
+
if (!fs.existsSync(bodyPath))
|
|
78
|
+
return null;
|
|
79
|
+
try {
|
|
80
|
+
const body = fs.readFileSync(bodyPath, 'utf-8');
|
|
81
|
+
const etagPath = `${bodyPath}.etag`;
|
|
82
|
+
const etag = fs.existsSync(etagPath)
|
|
83
|
+
? fs.readFileSync(etagPath, 'utf-8').trim() || null
|
|
84
|
+
: null;
|
|
85
|
+
return { body, etag };
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Atomically writes the cache body and (optionally) etag. Each file is
|
|
93
|
+
* written via a PID-suffixed temp file then renamed, so a crash mid-write
|
|
94
|
+
* never leaves a torn body file readable. Concurrent writers can still
|
|
95
|
+
* race on body-vs-etag consistency, but that race is self-healing on the
|
|
96
|
+
* next fetch (mismatched etag → 200 with fresh body → both rewritten).
|
|
97
|
+
*/
|
|
98
|
+
function writeCache(resource, slug, variant, body, etag) {
|
|
99
|
+
const bodyPath = pathFor(resource, slug, variant);
|
|
100
|
+
if (!bodyPath)
|
|
101
|
+
return;
|
|
102
|
+
fs.mkdirSync(path.dirname(bodyPath), { recursive: true });
|
|
103
|
+
atomicWrite(bodyPath, body);
|
|
104
|
+
const etagPath = `${bodyPath}.etag`;
|
|
105
|
+
if (etag) {
|
|
106
|
+
atomicWrite(etagPath, etag);
|
|
107
|
+
}
|
|
108
|
+
else if (fs.existsSync(etagPath)) {
|
|
109
|
+
try {
|
|
110
|
+
fs.unlinkSync(etagPath);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// best effort
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function atomicWrite(target, contents) {
|
|
118
|
+
const tmp = `${target}.tmp.${process.pid}.${Date.now()}`;
|
|
119
|
+
fs.writeFileSync(tmp, contents, 'utf-8');
|
|
120
|
+
fs.renameSync(tmp, target);
|
|
121
|
+
}
|
|
122
|
+
/** Test seam — exposes the resolved cache root for unit tests. */
|
|
123
|
+
function getCacheRoot() {
|
|
124
|
+
return getCacheRootInternal();
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=graphics-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphics-cache.js","sourceRoot":"","sources":["../../src/lib/graphics-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side validators for gooseworks-style.json and gooseworks-format.json.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the server-side Zod schema in gooseworks-app:
|
|
5
|
+
* backend/src/schemas/graphics-manifest.ts
|
|
6
|
+
*
|
|
7
|
+
* If the server schema changes, update this file to match. The CLI runs
|
|
8
|
+
* pre-flight validation here for fast feedback before uploading bytes.
|
|
9
|
+
*/
|
|
10
|
+
export interface StyleExample {
|
|
11
|
+
format: string;
|
|
12
|
+
isHero?: boolean;
|
|
13
|
+
file: string;
|
|
14
|
+
caption?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface PaletteEntry {
|
|
17
|
+
hex: string;
|
|
18
|
+
role?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface StyleManifest {
|
|
21
|
+
name: string;
|
|
22
|
+
slug?: string;
|
|
23
|
+
description: string;
|
|
24
|
+
designMd: string;
|
|
25
|
+
moodGroup?: string;
|
|
26
|
+
tags?: string[];
|
|
27
|
+
palette?: PaletteEntry[];
|
|
28
|
+
examples: StyleExample[];
|
|
29
|
+
}
|
|
30
|
+
export interface FormatExample {
|
|
31
|
+
file: string;
|
|
32
|
+
styleSlug?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface FormatManifest {
|
|
35
|
+
name: string;
|
|
36
|
+
slug?: string;
|
|
37
|
+
description: string;
|
|
38
|
+
width: number;
|
|
39
|
+
height: number;
|
|
40
|
+
contentRulesMd: string;
|
|
41
|
+
tags?: string[];
|
|
42
|
+
examples: FormatExample[];
|
|
43
|
+
}
|
|
44
|
+
export declare const VALID_MOOD_GROUPS: readonly ["Dark & Moody", "Light & Editorial", "Organic & Warm", "Bold & Energetic", "Retro & Cinematic", "Structural & Technical", "Friendly Corporate"];
|
|
45
|
+
export declare const STYLE_MANIFEST_FILENAME = "gooseworks-style.json";
|
|
46
|
+
export declare const FORMAT_MANIFEST_FILENAME = "gooseworks-format.json";
|
|
47
|
+
export interface ValidationResult {
|
|
48
|
+
ok: boolean;
|
|
49
|
+
errors: string[];
|
|
50
|
+
}
|
|
51
|
+
export declare const SLUG_RE: RegExp;
|
|
52
|
+
/**
|
|
53
|
+
* Throws if the string does not match the public slug grammar. Use before
|
|
54
|
+
* interpolating any externally-sourced slug (CLI arg, server response) into
|
|
55
|
+
* a filesystem path.
|
|
56
|
+
*/
|
|
57
|
+
export declare function assertSafeSlug(slug: string, source?: string): void;
|
|
58
|
+
export declare function validateStyleManifest(m: unknown): ValidationResult;
|
|
59
|
+
export declare function validateFormatManifest(m: unknown): ValidationResult;
|
|
60
|
+
/**
|
|
61
|
+
* Read a manifest file from disk. Returns the parsed object or throws a
|
|
62
|
+
* ManifestParseError with a clear message.
|
|
63
|
+
*/
|
|
64
|
+
export declare class ManifestParseError extends Error {
|
|
65
|
+
constructor(message: string);
|
|
66
|
+
}
|
|
67
|
+
export declare class ManifestMissingFileError extends Error {
|
|
68
|
+
readonly missing: string;
|
|
69
|
+
constructor(missing: string);
|
|
70
|
+
}
|
|
71
|
+
export declare class ManifestEscapingPathError extends Error {
|
|
72
|
+
readonly ref: string;
|
|
73
|
+
constructor(ref: string);
|
|
74
|
+
}
|
|
75
|
+
export declare function readManifestFile(filePath: string): unknown;
|
|
76
|
+
export interface ResolvedExampleFile {
|
|
77
|
+
/** The relative path as referenced in the manifest, e.g. "./poster.png". */
|
|
78
|
+
manifestRef: string;
|
|
79
|
+
/**
|
|
80
|
+
* Field name to use in multipart upload. Always a forward-slash relative
|
|
81
|
+
* path within the manifest directory — no `..`, no leading slash, no
|
|
82
|
+
* absolute paths. Safe to send to the server as a multipart field name.
|
|
83
|
+
*/
|
|
84
|
+
fieldName: string;
|
|
85
|
+
/** Absolute path on disk. */
|
|
86
|
+
absolutePath: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Resolve example file references against the publish directory. Throws
|
|
90
|
+
* ManifestMissingFileError if a referenced file doesn't exist, and
|
|
91
|
+
* ManifestEscapingPathError if it resolves outside `manifestDir`.
|
|
92
|
+
*/
|
|
93
|
+
export declare function resolveExampleFiles(manifestDir: string, examples: ReadonlyArray<{
|
|
94
|
+
file: string;
|
|
95
|
+
}>): ResolvedExampleFile[];
|
|
96
|
+
//# sourceMappingURL=graphics-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphics-manifest.d.ts","sourceRoot":"","sources":["../../src/lib/graphics-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,iBAAiB,2JAQpB,CAAC;AAEX,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAC/D,eAAO,MAAM,wBAAwB,2BAA2B,CAAC;AAEjE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,eAAO,MAAM,OAAO,QAAiB,CAAC;AAGtC;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAS,GAAG,IAAI,CAIlE;AAUD,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,GAAG,gBAAgB,CA+FlE;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAmEnE;AAED;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,wBAAyB,SAAQ,KAAK;aACrB,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM;CAI5C;AAED,qBAAa,yBAA0B,SAAQ,KAAK;aACtB,GAAG,EAAE,MAAM;gBAAX,GAAG,EAAE,MAAM;CAIxC;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAmB1D;AAED,MAAM,WAAW,mBAAmB;IAClC,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GACxC,mBAAmB,EAAE,CAkBvB"}
|