@maravilla-labs/adapter-core 3.0.2 → 3.2.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/dist/transforms/compile.d.ts +1 -1
- package/dist/transforms/compile.d.ts.map +1 -1
- package/dist/transforms/compile.js +123 -12
- package/dist/transforms/compile.js.map +1 -1
- package/dist/transforms/index.d.ts +1 -1
- package/dist/transforms/index.d.ts.map +1 -1
- package/dist/transforms/index.js.map +1 -1
- package/dist/transforms/types.d.ts +35 -0
- package/dist/transforms/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -45,7 +45,7 @@ export declare function compileTransforms(transforms: TransformsConfig | undefin
|
|
|
45
45
|
* directly with a hand-constructed call list.
|
|
46
46
|
*/
|
|
47
47
|
export interface TransformCall {
|
|
48
|
-
method: 'transcode' | 'thumbnail' | 'resize' | 'ocr';
|
|
48
|
+
method: 'detectFaces' | 'transcode' | 'thumbnail' | 'resize' | 'ocr';
|
|
49
49
|
/** Opts object (serialized as JSON into the generated code). `null` skips the second arg. */
|
|
50
50
|
opts: unknown;
|
|
51
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/transforms/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,sBAAsB,EAEvB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/transforms/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,sBAAsB,EAEvB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAMV,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AAEpB,2FAA2F;AAC3F,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,WAAW,EAAE,sBAAsB,EAAE,CAAC;IACtC;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,gBAAgB,GAAG,SAAS,GACvC,kBAAkB,GAAG,IAAI,CA0C3B;AAID;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,aAAa,GAAG,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,KAAK,CAAC;IACrE,6FAA6F;IAC7F,IAAI,EAAE,OAAO,CAAC;CACf;AA2LD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,aAAa,EAAE,GACrB,MAAM,CA0ER"}
|
|
@@ -31,11 +31,11 @@ export function compileTransforms(transforms) {
|
|
|
31
31
|
for (const pattern of patterns) {
|
|
32
32
|
const spec = transforms[pattern];
|
|
33
33
|
if (!spec || typeof spec !== 'object') {
|
|
34
|
-
throw new Error(`[maravilla] transforms["${pattern}"] must be an object with at least one of: transcode, thumbnail, resize, variants, ocr`);
|
|
34
|
+
throw new Error(`[maravilla] transforms["${pattern}"] must be an object with at least one of: detectFaces, transcode, thumbnail, resize, variants, ocr`);
|
|
35
35
|
}
|
|
36
36
|
const calls = collectCalls(pattern, spec);
|
|
37
37
|
if (calls.length === 0) {
|
|
38
|
-
throw new Error(`[maravilla] transforms["${pattern}"] declares no operations — add at least one of: transcode, thumbnail, resize, variants, ocr`);
|
|
38
|
+
throw new Error(`[maravilla] transforms["${pattern}"] declares no operations — add at least one of: detectFaces, transcode, thumbnail, resize, variants, ocr`);
|
|
39
39
|
}
|
|
40
40
|
const id = uniqueId(slugify(pattern), usedIds);
|
|
41
41
|
usedIds.add(id);
|
|
@@ -56,6 +56,11 @@ export function compileTransforms(transforms) {
|
|
|
56
56
|
}
|
|
57
57
|
function collectCalls(pattern, spec) {
|
|
58
58
|
const out = [];
|
|
59
|
+
// Face detection is emitted first: it persists the focal point that any
|
|
60
|
+
// `crop: 'focal'` resize below depends on.
|
|
61
|
+
if (spec.detectFaces !== undefined && spec.detectFaces !== false) {
|
|
62
|
+
out.push({ method: 'detectFaces', opts: normalizeDetectFaces(pattern, spec.detectFaces) });
|
|
63
|
+
}
|
|
59
64
|
for (const opts of asArray(spec.transcode)) {
|
|
60
65
|
validateTranscode(pattern, opts);
|
|
61
66
|
out.push({ method: 'transcode', opts });
|
|
@@ -118,6 +123,57 @@ function validateResize(pattern, opts) {
|
|
|
118
123
|
if (opts.width === undefined && opts.height === undefined) {
|
|
119
124
|
throw new Error(`[maravilla] transforms["${pattern}"].resize/variants entries need at least one of width / height`);
|
|
120
125
|
}
|
|
126
|
+
if (opts.crop !== undefined) {
|
|
127
|
+
if (opts.crop !== 'focal' && opts.crop !== 'center') {
|
|
128
|
+
throw new Error(`[maravilla] transforms["${pattern}"].resize/variants entries: crop must be 'focal' or 'center', got ${JSON.stringify(opts.crop)}`);
|
|
129
|
+
}
|
|
130
|
+
if (opts.width === undefined || opts.height === undefined) {
|
|
131
|
+
throw new Error(`[maravilla] transforms["${pattern}"].resize/variants entries: crop requires both width and height`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (opts.zoom !== undefined) {
|
|
135
|
+
if (typeof opts.zoom !== 'number' || Number.isNaN(opts.zoom)) {
|
|
136
|
+
throw new Error(`[maravilla] transforms["${pattern}"].resize/variants entries: zoom must be a number`);
|
|
137
|
+
}
|
|
138
|
+
if (opts.crop !== 'focal') {
|
|
139
|
+
throw new Error(`[maravilla] transforms["${pattern}"].resize/variants entries: zoom requires crop: 'focal'`);
|
|
140
|
+
}
|
|
141
|
+
if (opts.zoom < 1 || opts.zoom > 100) {
|
|
142
|
+
throw new Error(`[maravilla] transforms["${pattern}"].resize/variants entries: zoom must be in 1.0..=100.0, got ${opts.zoom}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Normalize a `detectFaces` config value into the wire opts object. `true`
|
|
148
|
+
* means "detector defaults" → `{}`; an object is validated and passed through
|
|
149
|
+
* (config fields are already the snake_case wire field names).
|
|
150
|
+
*/
|
|
151
|
+
function normalizeDetectFaces(pattern, value) {
|
|
152
|
+
if (value === true)
|
|
153
|
+
return {};
|
|
154
|
+
if (!value || typeof value !== 'object') {
|
|
155
|
+
throw new Error(`[maravilla] transforms["${pattern}"].detectFaces must be true or an options object`);
|
|
156
|
+
}
|
|
157
|
+
const out = {};
|
|
158
|
+
if (value.min_score !== undefined) {
|
|
159
|
+
if (typeof value.min_score !== 'number') {
|
|
160
|
+
throw new Error(`[maravilla] transforms["${pattern}"].detectFaces.min_score must be a number`);
|
|
161
|
+
}
|
|
162
|
+
out.min_score = value.min_score;
|
|
163
|
+
}
|
|
164
|
+
if (value.max_faces !== undefined) {
|
|
165
|
+
if (typeof value.max_faces !== 'number') {
|
|
166
|
+
throw new Error(`[maravilla] transforms["${pattern}"].detectFaces.max_faces must be a number`);
|
|
167
|
+
}
|
|
168
|
+
out.max_faces = value.max_faces;
|
|
169
|
+
}
|
|
170
|
+
if (value.fast !== undefined) {
|
|
171
|
+
if (typeof value.fast !== 'boolean') {
|
|
172
|
+
throw new Error(`[maravilla] transforms["${pattern}"].detectFaces.fast must be a boolean`);
|
|
173
|
+
}
|
|
174
|
+
out.fast = value.fast;
|
|
175
|
+
}
|
|
176
|
+
return out;
|
|
121
177
|
}
|
|
122
178
|
function validateOcr(pattern, opts) {
|
|
123
179
|
if (opts !== null && typeof opts !== 'object') {
|
|
@@ -156,16 +212,10 @@ function uniqueId(base, used) {
|
|
|
156
212
|
* Exported for testing — most callers want {@link compileTransforms}.
|
|
157
213
|
*/
|
|
158
214
|
export function generateHandler(id, pattern, calls) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
// Declaration order is preserved in the array so the dispatch order is
|
|
162
|
-
// still predictable when the worker picks them up.
|
|
163
|
-
const callList = calls
|
|
164
|
-
.map((c) => ` transforms.${c.method}(srcKey${c.opts === null || c.opts === undefined ? '' : ', ' + JSON.stringify(c.opts)}),`)
|
|
165
|
-
.join('\n');
|
|
166
|
-
return `// pattern: ${JSON.stringify(pattern)}
|
|
215
|
+
const trigger = JSON.stringify({ kind: 'storage', keyPattern: pattern, op: 'put' });
|
|
216
|
+
const preamble = `// pattern: ${JSON.stringify(pattern)}
|
|
167
217
|
export const ${id} = {
|
|
168
|
-
__maravilla_trigger: ${
|
|
218
|
+
__maravilla_trigger: ${trigger},
|
|
169
219
|
handler: async (event, ctx) => {
|
|
170
220
|
const transforms = ctx?.platform?.media?.transforms;
|
|
171
221
|
if (!transforms) {
|
|
@@ -174,13 +224,74 @@ export const ${id} = {
|
|
|
174
224
|
const srcKey = event && event.key;
|
|
175
225
|
if (typeof srcKey !== 'string' || !srcKey) {
|
|
176
226
|
throw new Error('[transforms] storage.put event missing key');
|
|
177
|
-
}
|
|
227
|
+
}`;
|
|
228
|
+
// Focal crops depend on the detect job's persisted focal point, so when the
|
|
229
|
+
// pattern declares BOTH detectFaces and at least one `crop: 'focal'` resize
|
|
230
|
+
// we must sequence: enqueue detect, wait for it to reach a terminal state,
|
|
231
|
+
// then enqueue the focal crops. Everything else still fans out in parallel.
|
|
232
|
+
const detectCall = calls.find((c) => c.method === 'detectFaces');
|
|
233
|
+
const focalCrops = calls.filter((c) => c.method === 'resize' && isFocalCrop(c.opts));
|
|
234
|
+
const needsOrdering = detectCall !== undefined && focalCrops.length > 0;
|
|
235
|
+
if (!needsOrdering) {
|
|
236
|
+
// Each variant is enqueued independently — fan them out in parallel via
|
|
237
|
+
// Promise.all so a slow ffmpeg job doesn't gate the next call to start.
|
|
238
|
+
// Declaration order is preserved in the array so the dispatch order is
|
|
239
|
+
// still predictable when the worker picks them up.
|
|
240
|
+
const callList = calls.map((c) => ` ${callExpr(c)},`).join('\n');
|
|
241
|
+
return `${preamble}
|
|
178
242
|
await Promise.all([
|
|
179
243
|
${callList}
|
|
180
244
|
]);
|
|
181
245
|
},
|
|
182
246
|
};
|
|
183
247
|
`;
|
|
248
|
+
}
|
|
249
|
+
// Ordered path. The eager calls (detect + everything that isn't a focal crop)
|
|
250
|
+
// start immediately; we then poll the detect job to a terminal state before
|
|
251
|
+
// enqueuing the focal crops. A failed or timed-out detect does NOT block the
|
|
252
|
+
// crops — they proceed and fall back to center cropping server-side.
|
|
253
|
+
const eagerCalls = calls.filter((c) => c !== detectCall && !focalCrops.includes(c));
|
|
254
|
+
const eagerList = eagerCalls.map((c) => ` ${callExpr(c)},`).join('\n');
|
|
255
|
+
const focalList = focalCrops.map((c) => ` ${callExpr(c)},`).join('\n');
|
|
256
|
+
return `${preamble}
|
|
257
|
+
// Enqueue face detection first — focal crops below depend on its result.
|
|
258
|
+
const __detect = await ${callExpr(detectCall)};
|
|
259
|
+
// Fire the transforms that don't depend on the focal point right away.
|
|
260
|
+
const __pending = [
|
|
261
|
+
${eagerList}
|
|
262
|
+
];
|
|
263
|
+
// Wait (bounded) for detection to reach a terminal state before enqueuing
|
|
264
|
+
// focal crops; on timeout / failure we proceed anyway (server falls back
|
|
265
|
+
// to center crop).
|
|
266
|
+
const __deadline = Date.now() + 30000;
|
|
267
|
+
while (Date.now() < __deadline) {
|
|
268
|
+
let __st;
|
|
269
|
+
try {
|
|
270
|
+
__st = await transforms.job(__detect.id);
|
|
271
|
+
} catch {
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
if (__st && (__st.status === 'complete' || __st.status === 'failed')) break;
|
|
275
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
276
|
+
}
|
|
277
|
+
__pending.push(
|
|
278
|
+
${focalList}
|
|
279
|
+
);
|
|
280
|
+
await Promise.all(__pending);
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
`;
|
|
284
|
+
}
|
|
285
|
+
/** Render a single `transforms.<method>(srcKey[, opts])` call expression. */
|
|
286
|
+
function callExpr(c) {
|
|
287
|
+
const optsArg = c.opts === null || c.opts === undefined ? '' : `, ${JSON.stringify(c.opts)}`;
|
|
288
|
+
return `transforms.${c.method}(srcKey${optsArg})`;
|
|
289
|
+
}
|
|
290
|
+
/** Whether a resize call's opts request focal cropping. */
|
|
291
|
+
function isFocalCrop(opts) {
|
|
292
|
+
return (typeof opts === 'object' &&
|
|
293
|
+
opts !== null &&
|
|
294
|
+
opts.crop === 'focal');
|
|
184
295
|
}
|
|
185
296
|
function renderModule(handlerSnippets) {
|
|
186
297
|
return `// Maravilla — auto-generated storage.put handlers from \`transforms\` config.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/transforms/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/transforms/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* See `./types.ts` for the user-facing config shape and `./compile.ts`
|
|
4
4
|
* for the build-time pipeline (`compileTransforms`, `generateHandler`).
|
|
5
5
|
*/
|
|
6
|
-
export type { TransformsConfig, TransformsPatternSpec, TransformVideoFormat, TransformImageFormat, TransformTranscodeOpts, TransformThumbnailOpts, TransformResizeOpts, TransformOcrOpts, } from './types.js';
|
|
6
|
+
export type { TransformsConfig, TransformsPatternSpec, TransformVideoFormat, TransformImageFormat, TransformTranscodeOpts, TransformThumbnailOpts, TransformResizeOpts, TransformOcrOpts, TransformDetectFacesOpts, } from './types.js';
|
|
7
7
|
export { compileTransforms, generateHandler } from './compile.js';
|
|
8
8
|
export type { CompiledTransforms } from './compile.js';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transforms/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transforms/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAClE,YAAY,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transforms/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transforms/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -63,6 +63,33 @@ export interface TransformResizeOpts {
|
|
|
63
63
|
format: TransformImageFormat;
|
|
64
64
|
quality?: number;
|
|
65
65
|
strip_metadata?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Crop strategy — requires BOTH `width` and `height`. `'focal'` crops
|
|
68
|
+
* around the source's stored focal point (from `detectFaces`, falling back
|
|
69
|
+
* to center when none exists); `'center'` crops around the geometric
|
|
70
|
+
* center. Omit for the default aspect-preserving fit (no crop).
|
|
71
|
+
*/
|
|
72
|
+
crop?: 'focal' | 'center';
|
|
73
|
+
/**
|
|
74
|
+
* Face-box-relative crop zoom, `1.0..=100.0`. Only valid with `crop: 'focal'`.
|
|
75
|
+
* `1.0` frames tightly around the detected face(s); larger pulls back for more
|
|
76
|
+
* context; large enough values saturate to the plain scale-to-cover crop.
|
|
77
|
+
* Requires the source to have stored face data (run `detectFaces` first).
|
|
78
|
+
*/
|
|
79
|
+
zoom?: number;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Options for `platform.media.transforms.detectFaces`, as declared in the
|
|
83
|
+
* config `detectFaces` block. Mirrors the wire `DetectFacesOpts` — snake_case
|
|
84
|
+
* to match the rest of the config surface.
|
|
85
|
+
*/
|
|
86
|
+
export interface TransformDetectFacesOpts {
|
|
87
|
+
/** Minimum detector confidence to keep a face, `0..=1`. Defaults to `0.6` server-side. */
|
|
88
|
+
min_score?: number;
|
|
89
|
+
/** Cap on retained faces (highest-scoring first). Defaults to `32` server-side. */
|
|
90
|
+
max_faces?: number;
|
|
91
|
+
/** Trade accuracy for latency. Defaults to `false` server-side. */
|
|
92
|
+
fast?: boolean;
|
|
66
93
|
}
|
|
67
94
|
/** Options for `platform.media.transforms.ocr`. */
|
|
68
95
|
export interface TransformOcrOpts {
|
|
@@ -77,6 +104,8 @@ export interface TransformOcrOpts {
|
|
|
77
104
|
* handler and run sequentially).
|
|
78
105
|
* - `variants` is an alias for `resize` arrays — convenient for the
|
|
79
106
|
* common "image → multiple resized renditions" case.
|
|
107
|
+
* - `detectFaces` runs face detection first and persists a focal point so
|
|
108
|
+
* `resize`/`variants` entries with `crop: 'focal'` crop around faces.
|
|
80
109
|
*/
|
|
81
110
|
export interface TransformsPatternSpec {
|
|
82
111
|
transcode?: TransformTranscodeOpts | TransformTranscodeOpts[];
|
|
@@ -85,6 +114,12 @@ export interface TransformsPatternSpec {
|
|
|
85
114
|
/** Sugar for `resize` arrays — same shape, same semantics. */
|
|
86
115
|
variants?: TransformResizeOpts[];
|
|
87
116
|
ocr?: TransformOcrOpts | TransformOcrOpts[];
|
|
117
|
+
/**
|
|
118
|
+
* Detect faces on matching uploads and persist a focal point. Pass `true`
|
|
119
|
+
* for detector defaults, or an object to tune detection. Emitted before the
|
|
120
|
+
* other transforms; focal-crop resizes wait for it to finish.
|
|
121
|
+
*/
|
|
122
|
+
detectFaces?: boolean | TransformDetectFacesOpts;
|
|
88
123
|
}
|
|
89
124
|
/**
|
|
90
125
|
* Top-level `transforms` block. Keys are glob path patterns — values
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/transforms/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,+CAA+C;AAC/C,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,MAAM,CAAC;AAElD,4CAA4C;AAC5C,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAE1D,yDAAyD;AACzD,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,yDAAyD;AACzD,MAAM,WAAW,sBAAsB;IACrC,kFAAkF;IAClF,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,sDAAsD;AACtD,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/transforms/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,+CAA+C;AAC/C,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,MAAM,CAAC;AAElD,4CAA4C;AAC5C,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAE1D,yDAAyD;AACzD,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,yDAAyD;AACzD,MAAM,WAAW,sBAAsB;IACrC,kFAAkF;IAClF,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,sDAAsD;AACtD,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAC/B,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,sBAAsB,GAAG,sBAAsB,EAAE,CAAC;IAC9D,SAAS,CAAC,EAAE,sBAAsB,GAAG,sBAAsB,EAAE,CAAC;IAC9D,MAAM,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,CAAC;IACrD,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACjC,GAAG,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;IAC5C;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,wBAAwB,CAAC;CAClD;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC"}
|