@bscotch/sprite-source 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE.md +29 -0
  2. package/README.md +84 -0
  3. package/dist/SpriteCache.d.ts +67 -0
  4. package/dist/SpriteCache.d.ts.map +1 -0
  5. package/dist/SpriteCache.js +139 -0
  6. package/dist/SpriteCache.js.map +1 -0
  7. package/dist/SpriteCache.schemas.d.ts +74 -0
  8. package/dist/SpriteCache.schemas.d.ts.map +1 -0
  9. package/dist/SpriteCache.schemas.js +51 -0
  10. package/dist/SpriteCache.schemas.js.map +1 -0
  11. package/dist/SpriteDest.actions.d.ts +18 -0
  12. package/dist/SpriteDest.actions.d.ts.map +1 -0
  13. package/dist/SpriteDest.actions.js +163 -0
  14. package/dist/SpriteDest.actions.js.map +1 -0
  15. package/dist/SpriteDest.d.ts +35 -0
  16. package/dist/SpriteDest.d.ts.map +1 -0
  17. package/dist/SpriteDest.js +359 -0
  18. package/dist/SpriteDest.js.map +1 -0
  19. package/dist/SpriteDest.schemas.d.ts +45 -0
  20. package/dist/SpriteDest.schemas.d.ts.map +1 -0
  21. package/dist/SpriteDest.schemas.js +33 -0
  22. package/dist/SpriteDest.schemas.js.map +1 -0
  23. package/dist/SpriteDir.d.ts +39 -0
  24. package/dist/SpriteDir.d.ts.map +1 -0
  25. package/dist/SpriteDir.js +240 -0
  26. package/dist/SpriteDir.js.map +1 -0
  27. package/dist/SpriteFrame.d.ts +36 -0
  28. package/dist/SpriteFrame.d.ts.map +1 -0
  29. package/dist/SpriteFrame.js +225 -0
  30. package/dist/SpriteFrame.js.map +1 -0
  31. package/dist/SpriteSource.d.ts +60 -0
  32. package/dist/SpriteSource.d.ts.map +1 -0
  33. package/dist/SpriteSource.js +153 -0
  34. package/dist/SpriteSource.js.map +1 -0
  35. package/dist/SpriteSource.schemas.d.ts +56 -0
  36. package/dist/SpriteSource.schemas.d.ts.map +1 -0
  37. package/dist/SpriteSource.schemas.js +54 -0
  38. package/dist/SpriteSource.schemas.js.map +1 -0
  39. package/dist/checksum.d.ts +4 -0
  40. package/dist/checksum.d.ts.map +1 -0
  41. package/dist/checksum.js +28 -0
  42. package/dist/checksum.js.map +1 -0
  43. package/dist/cli.d.mts +3 -0
  44. package/dist/cli.d.mts.map +1 -0
  45. package/dist/cli.mjs +113 -0
  46. package/dist/cli.mjs.map +1 -0
  47. package/dist/constants.d.ts +8 -0
  48. package/dist/constants.d.ts.map +1 -0
  49. package/dist/constants.js +10 -0
  50. package/dist/constants.js.map +1 -0
  51. package/dist/index.d.ts +9 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +8 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/safeFs.d.ts +5 -0
  56. package/dist/safeFs.d.ts.map +1 -0
  57. package/dist/safeFs.js +34 -0
  58. package/dist/safeFs.js.map +1 -0
  59. package/dist/types.d.ts +25 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +2 -0
  62. package/dist/types.js.map +1 -0
  63. package/dist/utility.d.ts +25 -0
  64. package/dist/utility.d.ts.map +1 -0
  65. package/dist/utility.js +101 -0
  66. package/dist/utility.js.map +1 -0
  67. package/package.json +58 -0
@@ -0,0 +1,153 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { existsSafe, pathy } from '@bscotch/pathy';
3
+ import { sequential } from '@bscotch/utility';
4
+ import { SpriteCache } from './SpriteCache.js';
5
+ import { spriteSourceConfigSchema, } from './SpriteSource.schemas.js';
6
+ import { FIO_RETRY_DELAY, MAX_FIO_RETRIES, retryOptions } from './constants.js';
7
+ import { SpriteSourceError, assert, deletePngChildren, getDirs, rethrow, } from './utility.js';
8
+ export class SpriteSource extends SpriteCache {
9
+ get configFile() {
10
+ return this.stitchDir
11
+ .join('sprites.source.json')
12
+ .withValidator(spriteSourceConfigSchema);
13
+ }
14
+ async resolveStaged(staging) {
15
+ const dir = pathy(staging.dir, this.spritesRoot);
16
+ if (!(await existsSafe(dir, retryOptions))) {
17
+ this.issues.push(new SpriteSourceError(`Staging directory does not exist: ${dir}`));
18
+ return;
19
+ }
20
+ // Identify all "SpriteDirs". Stored as a set so we
21
+ // can remove the ones we process.
22
+ const spriteDirs = new Set(await this.getSpriteDirs(await getDirs(dir.absolute)));
23
+ for (const transform of staging.transforms) {
24
+ // filter to matching sprites
25
+ const pattern = transform.include
26
+ ? new RegExp(transform.include)
27
+ : undefined;
28
+ const sprites = [];
29
+ for (const sprite of spriteDirs) {
30
+ if (!pattern || sprite.path.relative.match(pattern)) {
31
+ sprites.push(sprite);
32
+ spriteDirs.delete(sprite);
33
+ }
34
+ }
35
+ const waits = [];
36
+ for (const sprite of sprites) {
37
+ let outDirPath = sprite.path.relative;
38
+ if (transform.renames) {
39
+ for (const rename of transform.renames) {
40
+ outDirPath = outDirPath.replace(new RegExp(rename.from), rename.to);
41
+ }
42
+ }
43
+ const outDir = pathy(outDirPath, this.spritesRoot);
44
+ // Crop it!
45
+ const cropWait = transform.crop ? sprite.crop() : Promise.resolve();
46
+ // Bleed it!
47
+ const bleedWait = cropWait.then(() => transform.bleed ? sprite.bleed() : Promise.resolve());
48
+ // Purge the output location!
49
+ const deleteWait = bleedWait.then(() => transform.synced
50
+ ? deletePngChildren(outDir).then((deleted) => {
51
+ this.logs.push(...deleted.map((path) => ({
52
+ action: 'deleted',
53
+ path: path.absolute,
54
+ })));
55
+ })
56
+ : Promise.resolve());
57
+ // Save to destination (including renames)
58
+ const moveWait = deleteWait.then(() => sprite.moveTo(outDir));
59
+ waits.push(moveWait);
60
+ }
61
+ await Promise.allSettled(waits);
62
+ // Delete any folders-of-empty-folders
63
+ const dirs = await getDirs(dir.absolute);
64
+ for (const dir of dirs) {
65
+ if ((await dir.exists()) && (await dir.isEmptyDirectory())) {
66
+ await dir.delete({
67
+ recursive: true,
68
+ force: true,
69
+ retryDelay: FIO_RETRY_DELAY,
70
+ maxRetries: MAX_FIO_RETRIES,
71
+ });
72
+ }
73
+ }
74
+ }
75
+ }
76
+ async loadConfig(overrides = {}) {
77
+ // Validate options. Show error out if invalid.
78
+ try {
79
+ overrides = spriteSourceConfigSchema.parse(overrides);
80
+ }
81
+ catch (err) {
82
+ rethrow(err, 'Invalid SpriteSource options');
83
+ }
84
+ assert(await this.spritesRoot.isDirectory(), 'Source must be an existing directory.');
85
+ // Update the config
86
+ await this.stitchDir.ensureDirectory();
87
+ const config = await this.configFile.read({
88
+ fallback: {},
89
+ maxRetries: MAX_FIO_RETRIES,
90
+ retryDelayMillis: FIO_RETRY_DELAY,
91
+ });
92
+ const snapshot = JSON.stringify(config);
93
+ if (overrides?.ignore !== undefined) {
94
+ config.ignore = overrides.ignore;
95
+ }
96
+ if (overrides?.staging !== undefined) {
97
+ config.staging = overrides.staging;
98
+ }
99
+ if (snapshot !== JSON.stringify(config)) {
100
+ try {
101
+ await this.configFile.write(config, {
102
+ maxRetries: MAX_FIO_RETRIES,
103
+ retryDelayMillis: FIO_RETRY_DELAY,
104
+ });
105
+ }
106
+ catch (err) {
107
+ console.error(err);
108
+ }
109
+ }
110
+ return config;
111
+ }
112
+ /**
113
+ * Transform any staged sprites and add them to the source,
114
+ * and compute updated sprite info.
115
+ */
116
+ async update(
117
+ /** Optionally override config options */
118
+ options) {
119
+ const config = await this.loadConfig(options);
120
+ // Process any staging folders
121
+ for (const staging of config.staging ?? []) {
122
+ // Do them sequentially since later patterns could overlap earlier ones
123
+ await this.resolveStaged(staging);
124
+ }
125
+ // Update the sprite info cache
126
+ const info = await this.updateSpriteInfo(config.ignore);
127
+ return info;
128
+ }
129
+ /**
130
+ * @param options If specified, creates/overwrites the config file with these options.
131
+ */
132
+ static async from(spritesRoot, options) {
133
+ // Ensure the spritesRoot exists
134
+ assert(await existsSafe(spritesRoot, retryOptions), `Sprites root does not exist: ${spritesRoot}`);
135
+ const source = new SpriteSource(spritesRoot);
136
+ // Ensure a config file
137
+ await source.loadConfig(options);
138
+ return source;
139
+ }
140
+ }
141
+ __decorate([
142
+ sequential,
143
+ __metadata("design:type", Function),
144
+ __metadata("design:paramtypes", [Object]),
145
+ __metadata("design:returntype", Promise)
146
+ ], SpriteSource.prototype, "loadConfig", null);
147
+ __decorate([
148
+ sequential,
149
+ __metadata("design:type", Function),
150
+ __metadata("design:paramtypes", [Object]),
151
+ __metadata("design:returntype", Promise)
152
+ ], SpriteSource.prototype, "update", null);
153
+ //# sourceMappingURL=SpriteSource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpriteSource.js","sourceRoot":"","sources":["../src/SpriteSource.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import { z } from 'zod';
2
+ export type SpriteSourceStage = z.infer<typeof spriteStagingSchema>;
3
+ declare const spriteStagingSchema: z.ZodObject<{
4
+ dir: z.ZodString;
5
+ transforms: z.ZodArray<z.ZodObject<{
6
+ include: z.ZodOptional<z.ZodString>;
7
+ bleed: z.ZodOptional<z.ZodBoolean>;
8
+ crop: z.ZodOptional<z.ZodBoolean>;
9
+ synced: z.ZodOptional<z.ZodBoolean>;
10
+ renames: z.ZodOptional<z.ZodArray<z.ZodObject<{
11
+ from: z.ZodString;
12
+ to: z.ZodString;
13
+ }, z.core.$loose>>>;
14
+ }, z.core.$loose>>;
15
+ }, z.core.$loose>;
16
+ export type SpriteSourceConfig = z.infer<typeof spriteSourceConfigSchema>;
17
+ export declare const spriteSourceConfigSchema: z.ZodObject<{
18
+ $schema: z.ZodOptional<z.ZodDefault<z.ZodString>>;
19
+ staging: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
20
+ dir: z.ZodString;
21
+ transforms: z.ZodArray<z.ZodObject<{
22
+ include: z.ZodOptional<z.ZodString>;
23
+ bleed: z.ZodOptional<z.ZodBoolean>;
24
+ crop: z.ZodOptional<z.ZodBoolean>;
25
+ synced: z.ZodOptional<z.ZodBoolean>;
26
+ renames: z.ZodOptional<z.ZodArray<z.ZodObject<{
27
+ from: z.ZodString;
28
+ to: z.ZodString;
29
+ }, z.core.$loose>>>;
30
+ }, z.core.$loose>>;
31
+ }, z.core.$loose>>>>;
32
+ ignore: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
33
+ }, z.core.$loose>;
34
+ export declare const spriteSourceConfigInfo: {
35
+ schema: z.ZodObject<{
36
+ $schema: z.ZodOptional<z.ZodDefault<z.ZodString>>;
37
+ staging: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
38
+ dir: z.ZodString;
39
+ transforms: z.ZodArray<z.ZodObject<{
40
+ include: z.ZodOptional<z.ZodString>;
41
+ bleed: z.ZodOptional<z.ZodBoolean>;
42
+ crop: z.ZodOptional<z.ZodBoolean>;
43
+ synced: z.ZodOptional<z.ZodBoolean>;
44
+ renames: z.ZodOptional<z.ZodArray<z.ZodObject<{
45
+ from: z.ZodString;
46
+ to: z.ZodString;
47
+ }, z.core.$loose>>>;
48
+ }, z.core.$loose>>;
49
+ }, z.core.$loose>>>>;
50
+ ignore: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
51
+ }, z.core.$loose>;
52
+ name: string;
53
+ filename: string;
54
+ };
55
+ export {};
56
+ //# sourceMappingURL=SpriteSource.schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpriteSource.schemas.d.ts","sourceRoot":"","sources":["../src/SpriteSource.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAqCxB,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACpE,QAAA,MAAM,mBAAmB;;;;;;;;;;;;iBAWvB,CAAC;AAIH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC1E,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;iBAgBnC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;CAIlC,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { z } from 'zod';
2
+ import { jsonSchemaRemoteDir } from './constants.js';
3
+ const spriteSourceTransformSchema = z.looseObject({
4
+ include: z
5
+ .string()
6
+ .optional()
7
+ .describe('Pattern to match against the folder path (relative to the staging root, using POSIX seps) for it to be included. If omitted, all sprites are included. Converted to a regex with `new RegExp(include)`.'),
8
+ bleed: z.boolean().optional().describe('Whether to bleed the image.'),
9
+ crop: z.boolean().optional().describe('Whether to crop the image.'),
10
+ synced: z
11
+ .boolean()
12
+ .optional()
13
+ .describe('Whether to sync the target folder to the staging folder, by deleting any files in the target folder that are not in the staging folder.'),
14
+ renames: z
15
+ .array(z.looseObject({
16
+ from: z
17
+ .string()
18
+ .describe('Regex pattern to match against the filename, for use as the 1st arg in the JavaScript `String.replace` function.'),
19
+ to: z
20
+ .string()
21
+ .describe('Replacement string for the filename, for use as the 2nd arg in the JavaScript `String.replace` function.'),
22
+ }))
23
+ .optional()
24
+ .describe('Rules for renaming when moving to the SpriteSource directory.'),
25
+ });
26
+ const spriteStagingSchema = z.looseObject({
27
+ dir: z
28
+ .string()
29
+ .describe('Path to the folder containing the raw images. Either relative to the SpriteSource root or absolute.'),
30
+ transforms: z
31
+ .array(spriteSourceTransformSchema)
32
+ .describe('Transformations to apply to the raw images while moving them to the SpriteSource directory. Images are removed after a matching transform, and any images not matching any transforms are left alone.'),
33
+ });
34
+ const schemaFilename = 'stitch.sprite-source.schema.json';
35
+ const remoteFilename = `${jsonSchemaRemoteDir}/${schemaFilename}`;
36
+ export const spriteSourceConfigSchema = z.looseObject({
37
+ $schema: z.string().default(remoteFilename).optional(),
38
+ staging: z
39
+ .array(spriteStagingSchema)
40
+ .nullable()
41
+ .describe('List of folders containing raw images to be imported into a GameMaker project, along with transformation options for those images to apply during import.')
42
+ .optional(),
43
+ ignore: z
44
+ .array(z.string())
45
+ .nullable()
46
+ .optional()
47
+ .describe('List of ignore patterns for sprites that should be excluded from caching and importing. Will be converted to a regex with `new RegExp()` and checked against the spritefolder path (relative to the SpritSource root, using POSIX seps).'),
48
+ });
49
+ export const spriteSourceConfigInfo = {
50
+ schema: spriteSourceConfigSchema,
51
+ name: 'Sprite Source Configuration',
52
+ filename: schemaFilename,
53
+ };
54
+ //# sourceMappingURL=SpriteSource.schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpriteSource.schemas.js","sourceRoot":"","sources":["../src/SpriteSource.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,2BAA2B,GAAG,CAAC,CAAC,WAAW,CAAC;IAChD,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,yMAAyM,CAC1M;IACH,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IACrE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;IACnE,MAAM,EAAE,CAAC;SACN,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,yIAAyI,CAC1I;IACH,OAAO,EAAE,CAAC;SACP,KAAK,CACJ,CAAC,CAAC,WAAW,CAAC;QACZ,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,CACP,kHAAkH,CACnH;QACH,EAAE,EAAE,CAAC;aACF,MAAM,EAAE;aACR,QAAQ,CACP,0GAA0G,CAC3G;KACJ,CAAC,CACH;SACA,QAAQ,EAAE;SACV,QAAQ,CAAC,+DAA+D,CAAC;CAC7E,CAAC,CAAC;AAGH,MAAM,mBAAmB,GAAG,CAAC,CAAC,WAAW,CAAC;IACxC,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,QAAQ,CACP,qGAAqG,CACtG;IACH,UAAU,EAAE,CAAC;SACV,KAAK,CAAC,2BAA2B,CAAC;SAClC,QAAQ,CACP,uMAAuM,CACxM;CACJ,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,kCAAkC,CAAC;AAC1D,MAAM,cAAc,GAAG,GAAG,mBAAmB,IAAI,cAAc,EAAE,CAAC;AAElE,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,WAAW,CAAC;IACpD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE;IACtD,OAAO,EAAE,CAAC;SACP,KAAK,CAAC,mBAAmB,CAAC;SAC1B,QAAQ,EAAE;SACV,QAAQ,CACP,2JAA2J,CAC5J;SACA,QAAQ,EAAE;IACb,MAAM,EAAE,CAAC;SACN,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,EAAE;SACV,QAAQ,CACP,0OAA0O,CAC3O;CACJ,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,MAAM,EAAE,wBAAwB;IAChC,IAAI,EAAE,6BAA6B;IACnC,QAAQ,EAAE,cAAc;CACzB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function computeFileChecksum(filePath: string): Promise<string>;
2
+ export declare function computeFilesChecksum(paths: string[]): Promise<string>;
3
+ export declare function computeStringChecksum(str: string): string;
4
+ //# sourceMappingURL=checksum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checksum.d.ts","sourceRoot":"","sources":["../src/checksum.ts"],"names":[],"mappings":"AAcA,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK3E;AAED,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAG3E;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIzD"}
@@ -0,0 +1,28 @@
1
+ import { computePngChecksum } from '@bscotch/pixel-checksum';
2
+ import crypto from 'node:crypto';
3
+ import fsp from 'node:fs/promises';
4
+ /**
5
+ * A quick checksum for arbitrary text-based file types
6
+ * (like JSON or atlas), where newlines are first normalized.
7
+ */
8
+ async function textFileChecksum(filePath) {
9
+ const content = await fsp.readFile(filePath, 'utf8');
10
+ const normalized = content.replace(/\r/g, '').trim();
11
+ return computeStringChecksum(normalized);
12
+ }
13
+ export async function computeFileChecksum(filePath) {
14
+ if (!filePath.match(/\.png$/i)) {
15
+ return await textFileChecksum(filePath);
16
+ }
17
+ return computePngChecksum(filePath);
18
+ }
19
+ export async function computeFilesChecksum(paths) {
20
+ const checksums = await Promise.all(paths.map(computeFileChecksum));
21
+ return computeStringChecksum(checksums.join('-'));
22
+ }
23
+ export function computeStringChecksum(str) {
24
+ const hash = crypto.createHash('md5');
25
+ hash.update(str);
26
+ return hash.digest('hex');
27
+ }
28
+ //# sourceMappingURL=checksum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checksum.js","sourceRoot":"","sources":["../src/checksum.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,GAAG,MAAM,kBAAkB,CAAC;AAEnC;;;GAGG;AACH,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IAC9C,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrD,OAAO,qBAAqB,CAAC,UAAU,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,QAAgB;IACxD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,OAAO,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAe;IACxD,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;IACpE,OAAO,qBAAqB,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC"}
package/dist/cli.d.mts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.mts","sourceRoot":"","sources":["../src/cli.mts"],"names":[],"mappings":""}
package/dist/cli.mjs ADDED
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env node
2
+ import { pathy } from '@bscotch/pathy';
3
+ import { defineCommand, runMain } from 'citty';
4
+ import { pathToFileURL } from 'node:url';
5
+ import meta from '../package.json' with { type: 'json' };
6
+ import { SpriteDest } from './SpriteDest.js';
7
+ import { SpriteSource } from './SpriteSource.js';
8
+ const main = defineCommand({
9
+ meta: {
10
+ name: 'spsrc',
11
+ version: meta.version,
12
+ description: 'sprite-source pipeline utilities',
13
+ },
14
+ subCommands: {
15
+ 'add-source': defineCommand({
16
+ meta: {
17
+ name: 'add-source',
18
+ description: `ensure that a sprite source directory is initialized and use it in a destination GameMaker project (doesn't overwrite your configs if they're already set up)`,
19
+ },
20
+ args: {
21
+ source: {
22
+ type: 'positional',
23
+ description: 'a directory serving as a sprite source root',
24
+ required: true,
25
+ valueHint: '.',
26
+ },
27
+ project: {
28
+ type: 'positional',
29
+ description: 'path to the .yyp file for the target GameMaker project (or folder containing that file) into which the sprites should be imported',
30
+ valueHint: 'path/to/project.yyp',
31
+ },
32
+ },
33
+ async run(context) {
34
+ const src = await SpriteSource.from(context.args.source);
35
+ const srcConfig = await src.loadConfig();
36
+ // Ensure a source config with a default stage
37
+ if (!srcConfig.staging?.length) {
38
+ srcConfig.staging = [{ dir: '.', transforms: [] }];
39
+ await src.loadConfig(srcConfig);
40
+ }
41
+ console.log('Edit your source config at');
42
+ console.log(pathToFileURL(src.configFile.relative).toString());
43
+ console.log();
44
+ // Ensure a dest config that imports it
45
+ let projectYypPath = pathy(context.args.project);
46
+ if (!projectYypPath.hasExtension('yyp')) {
47
+ // Assume it's a directory containing a yyp file and find it
48
+ projectYypPath = (await pathy(projectYypPath).findChild(/\.yyp$/));
49
+ if (!projectYypPath) {
50
+ console.error('Provided project path was neither a yyp file nor a folder containing one.');
51
+ process.exit(1);
52
+ }
53
+ }
54
+ const dest = await SpriteDest.from(projectYypPath);
55
+ const destConfig = await dest.loadConfig();
56
+ destConfig.sources ||= [];
57
+ const relativeSourcePath = dest.yypPath
58
+ .up()
59
+ .relativeTo(src.spritesRoot);
60
+ if (!destConfig.sources.find((src) => pathy(src.source).equals(relativeSourcePath))) {
61
+ destConfig.sources.push({
62
+ source: relativeSourcePath,
63
+ });
64
+ // Reload with this new config as an override
65
+ await dest.loadConfig(destConfig);
66
+ }
67
+ console.log('Edit your project config at');
68
+ console.log(pathToFileURL(dest.configFile.relative).toString());
69
+ console.log();
70
+ },
71
+ }),
72
+ import: defineCommand({
73
+ meta: {
74
+ name: 'import',
75
+ description: 'import new/updated sprites from any configured sprite sources into a GameMaker project',
76
+ },
77
+ args: {
78
+ project: {
79
+ type: 'positional',
80
+ default: '.',
81
+ description: 'path to the GameMaker project, either the yyp file or the folder containing it',
82
+ required: false,
83
+ },
84
+ },
85
+ async run(context) {
86
+ // Find the project
87
+ let projectYypPath = pathy(context.args.project || '.');
88
+ if (!projectYypPath.hasExtension('yyp')) {
89
+ // Assume it's a directory containing a yyp file and find it
90
+ projectYypPath = (await pathy(projectYypPath).findChild(/\.yyp$/));
91
+ if (!projectYypPath) {
92
+ console.error('Provided project path was neither a yyp file nor a folder containing one.');
93
+ process.exit(1);
94
+ }
95
+ }
96
+ const dest = await SpriteDest.from(projectYypPath);
97
+ console.log('Importing new and updated sprites...');
98
+ const results = await dest.import();
99
+ for (const result of results || []) {
100
+ console.log(' ✅', result.resource.name);
101
+ }
102
+ if (!results?.length) {
103
+ console.log(' No changes found.');
104
+ }
105
+ else {
106
+ console.log('Import complete!');
107
+ }
108
+ },
109
+ }),
110
+ },
111
+ });
112
+ runMain(main);
113
+ //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.mjs","sourceRoot":"","sources":["../src/cli.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { FileRetryOptions } from '@bscotch/pathy';
2
+ export declare const MAX_FIO_RETRIES = 20;
3
+ export declare const FIO_RETRY_DELAY = 100;
4
+ export declare const retryOptions: FileRetryOptions;
5
+ export declare const spriteDestConfigFilename = "sprites.import.json";
6
+ export declare const spriteCacheFilename = "sprites.info.json";
7
+ export declare const jsonSchemaRemoteDir = "https://raw.githubusercontent.com/bscotch/stitch/refs/heads/develop/packages/sprite-source/schemas";
8
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC,eAAO,MAAM,YAAY,EAAE,gBAG1B,CAAC;AAEF,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAE9D,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD,eAAO,MAAM,mBAAmB,uGACsE,CAAC"}
@@ -0,0 +1,10 @@
1
+ export const MAX_FIO_RETRIES = 20;
2
+ export const FIO_RETRY_DELAY = 100;
3
+ export const retryOptions = {
4
+ maxRetries: MAX_FIO_RETRIES,
5
+ retryDelayMillis: FIO_RETRY_DELAY,
6
+ };
7
+ export const spriteDestConfigFilename = 'sprites.import.json';
8
+ export const spriteCacheFilename = 'sprites.info.json';
9
+ export const jsonSchemaRemoteDir = 'https://raw.githubusercontent.com/bscotch/stitch/refs/heads/develop/packages/sprite-source/schemas';
10
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAClC,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAEnC,MAAM,CAAC,MAAM,YAAY,GAAqB;IAC5C,UAAU,EAAE,eAAe;IAC3B,gBAAgB,EAAE,eAAe;CAClC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,qBAAqB,CAAC;AAE9D,MAAM,CAAC,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEvD,MAAM,CAAC,MAAM,mBAAmB,GAC9B,oGAAoG,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { spritesInfoSchema, type SpritesInfo } from './SpriteCache.schemas.js';
2
+ export * from './SpriteDest.actions.js';
3
+ export { SpriteDest } from './SpriteDest.js';
4
+ export { spriteDestConfigSchema, type SpriteDestConfig, type SpriteDestSource, } from './SpriteDest.schemas.js';
5
+ export { SpriteDir } from './SpriteDir.js';
6
+ export { SpriteSource } from './SpriteSource.js';
7
+ export { spriteSourceConfigSchema, type SpriteSourceConfig, type SpriteSourceStage, } from './SpriteSource.schemas.js';
8
+ export type { Issue, Log } from './types.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC/E,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export { spritesInfoSchema } from './SpriteCache.schemas.js';
2
+ export * from './SpriteDest.actions.js';
3
+ export { SpriteDest } from './SpriteDest.js';
4
+ export { spriteDestConfigSchema, } from './SpriteDest.schemas.js';
5
+ export { SpriteDir } from './SpriteDir.js';
6
+ export { SpriteSource } from './SpriteSource.js';
7
+ export { spriteSourceConfigSchema, } from './SpriteSource.schemas.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,0BAA0B,CAAC;AAC/E,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EACL,sBAAsB,GAGvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EACL,wBAAwB,GAGzB,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { Pathy } from '@bscotch/pathy';
2
+ import type { Dirent } from 'node:fs';
3
+ export declare function readdirSafe(dir: string | Pathy): Promise<string[]>;
4
+ export declare function readdirSafeWithFileTypes(dir: string | Pathy): Promise<Dirent[]>;
5
+ //# sourceMappingURL=safeFs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safeFs.d.ts","sourceRoot":"","sources":["../src/safeFs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAgCtC,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAExE;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,GAAG,KAAK,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB"}
package/dist/safeFs.js ADDED
@@ -0,0 +1,34 @@
1
+ import fsp from 'node:fs/promises';
2
+ import { FIO_RETRY_DELAY, MAX_FIO_RETRIES } from './constants.js';
3
+ import { SpriteSourceError } from './utility.js';
4
+ /**
5
+ * A wrapper around `fs.readdir` that retries a few times and
6
+ * uses the `withFileTypes` option.
7
+ */
8
+ async function _readdirSafe(dir, withFileTypes) {
9
+ let retries = 0;
10
+ let files = [];
11
+ let error = null;
12
+ while (retries < MAX_FIO_RETRIES) {
13
+ error = null;
14
+ try {
15
+ // @ts-expect-error withFileTypes can only be `true` in the types
16
+ files = await fsp.readdir(dir.toString(), { withFileTypes });
17
+ return files;
18
+ }
19
+ catch (err) {
20
+ error = new SpriteSourceError(`Failed to read directory ${dir}`, err);
21
+ retries++;
22
+ await new Promise((resolve) => setTimeout(resolve, FIO_RETRY_DELAY));
23
+ continue;
24
+ }
25
+ }
26
+ throw error;
27
+ }
28
+ export async function readdirSafe(dir) {
29
+ return await _readdirSafe(dir, false);
30
+ }
31
+ export async function readdirSafeWithFileTypes(dir) {
32
+ return await _readdirSafe(dir, true);
33
+ }
34
+ //# sourceMappingURL=safeFs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safeFs.js","sourceRoot":"","sources":["../src/safeFs.ts"],"names":[],"mappings":"AAEA,OAAO,GAAG,MAAM,kBAAkB,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD;;;GAGG;AACH,KAAK,UAAU,YAAY,CACzB,GAAmB,EACnB,aAAiB;IAEjB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,KAAK,GAAU,EAAE,CAAC;IACtB,IAAI,KAAK,GAA6B,IAAI,CAAC;IAC3C,OAAO,OAAO,GAAG,eAAe,EAAE,CAAC;QACjC,KAAK,GAAG,IAAI,CAAC;QACb,IAAI,CAAC;YACH,iEAAiE;YACjE,KAAK,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;YAC7D,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,GAAG,IAAI,iBAAiB,CAAC,4BAA4B,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;YACtE,OAAO,EAAE,CAAC;YACV,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;YACrE,SAAS;QACX,CAAC;IACH,CAAC;IACD,MAAM,KAAK,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAmB;IACnD,OAAO,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,GAAmB;IAEnB,OAAO,MAAM,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,25 @@
1
+ export interface Log {
2
+ action: 'deleted' | 'moved' | 'skipped-collaborator-owned';
3
+ path: string;
4
+ to?: string;
5
+ }
6
+ export interface BBox {
7
+ top: number;
8
+ bottom: number;
9
+ left: number;
10
+ right: number;
11
+ }
12
+ export interface Issue {
13
+ level: 'error' | 'warning';
14
+ message: string;
15
+ cause?: any;
16
+ }
17
+ export type AnyFunction<R> = (...args: any) => R extends Promise<infer U> ? Promise<U> : R;
18
+ export type Reporter = {
19
+ report(value: {
20
+ message?: string | undefined;
21
+ /** Percentage points to add to the completion metric */
22
+ increment?: number | undefined;
23
+ }): void;
24
+ };
25
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAAG;IAClB,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,4BAA4B,CAAC;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,IAAI;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAC3B,GAAG,IAAI,EAAE,GAAG,KACT,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAEjD,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,CAAC,KAAK,EAAE;QACZ,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC7B,wDAAwD;QACxD,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAChC,GAAG,IAAI,CAAC;CACV,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import { Pathy } from '@bscotch/pathy';
2
+ export type AnyFunc = (...args: any) => any;
3
+ export type Checked<T extends AnyFunc> = [error: Error, result: null] | [error: null, result: ReturnType<T>];
4
+ export type AsyncableChecked<T extends AnyFunc> = ReturnType<T> extends Promise<any> ? Promise<Checked<T>> : Checked<T>;
5
+ export declare function check<T extends AnyFunc>(func: T, message: string): AsyncableChecked<T>;
6
+ export declare class SpriteSourceError extends Error {
7
+ constructor(message: string, cause?: any, asserter?: Function);
8
+ }
9
+ export declare function assert(condition: any, message: string, cause?: any): asserts condition;
10
+ export declare function rethrow(cause: any, message: string): void;
11
+ export declare function getDirs(rootFolder: string, maxDepth?: number): Promise<Pathy[]>;
12
+ /**
13
+ * Delete the PNG images inside a folder. Returns the list of
14
+ * deleted images.
15
+ */
16
+ export declare function deletePngChildren(path: Pathy): Promise<Pathy<unknown>[]>;
17
+ /**
18
+ * Asynchronously get the size of a PNG image, given its path,
19
+ * with maximal speed.
20
+ */
21
+ export declare function getPngSize(path: Pathy): Promise<{
22
+ width: number;
23
+ height: number;
24
+ }>;
25
+ //# sourceMappingURL=utility.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utility.d.ts","sourceRoot":"","sources":["../src/utility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAiB,MAAM,gBAAgB,CAAC;AAKtD,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC;AAC5C,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,OAAO,IACjC,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,GAC5B,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzC,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,OAAO,IAC5C,UAAU,CAAC,CAAC,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAExE,wBAAgB,KAAK,CAAC,CAAC,SAAS,OAAO,EACrC,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,MAAM,GACd,gBAAgB,CAAC,CAAC,CAAC,CAmBrB;AAED,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,QAAQ;CAM9D;AAED,wBAAgB,MAAM,CACpB,SAAS,EAAE,GAAG,EACd,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,GAAG,GACV,OAAO,CAAC,SAAS,CAKnB;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,QAIlD;AAED,wBAAsB,OAAO,CAC3B,UAAU,EAAE,MAAM,EAClB,QAAQ,SAAW,GAClB,OAAO,CAAC,KAAK,EAAE,CAAC,CAoBlB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,KAAK,6BAgBlD;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,KAAK,GACV,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAc5C"}