@oazmi/superbuild 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/esm/_dnt.shims.d.ts +2 -0
  2. package/esm/_dnt.shims.d.ts.map +1 -0
  3. package/esm/_dnt.shims.js +57 -0
  4. package/esm/deps/jsr.io/@oazmi/esbuild-types/0.28.0/src/mod.d.ts +598 -0
  5. package/esm/deps/jsr.io/@oazmi/esbuild-types/0.28.0/src/mod.d.ts.map +1 -0
  6. package/esm/deps/jsr.io/@oazmi/esbuild-types/0.28.0/src/mod.js +1 -0
  7. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/alias.d.ts +617 -0
  8. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/alias.d.ts.map +1 -0
  9. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/alias.js +671 -0
  10. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array1d.d.ts +487 -0
  11. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array1d.d.ts.map +1 -0
  12. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array1d.js +536 -0
  13. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array2d.d.ts +266 -0
  14. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array2d.d.ts.map +1 -0
  15. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array2d.js +318 -0
  16. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/binder.d.ts +368 -0
  17. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/binder.d.ts.map +1 -0
  18. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/binder.js +380 -0
  19. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/crossenv.d.ts +711 -0
  20. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/crossenv.d.ts.map +1 -0
  21. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/crossenv.js +1173 -0
  22. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/cryptoman.d.ts +171 -0
  23. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/cryptoman.d.ts.map +1 -0
  24. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/cryptoman.js +308 -0
  25. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/deps.d.ts +10 -0
  26. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/deps.d.ts.map +1 -0
  27. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/deps.js +10 -0
  28. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack.d.ts +168 -0
  29. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack.d.ts.map +1 -0
  30. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack.js +236 -0
  31. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack_varint.d.ts +90 -0
  32. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack_varint.d.ts.map +1 -0
  33. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack_varint.js +237 -0
  34. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericarray.d.ts +213 -0
  35. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericarray.d.ts.map +1 -0
  36. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericarray.js +363 -0
  37. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericmethods.d.ts +233 -0
  38. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericmethods.d.ts.map +1 -0
  39. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericmethods.js +256 -0
  40. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/pathman.d.ts +1436 -0
  41. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/pathman.d.ts.map +1 -0
  42. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/pathman.js +1730 -0
  43. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/promiseman.d.ts +647 -0
  44. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/promiseman.d.ts.map +1 -0
  45. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/promiseman.js +762 -0
  46. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/stringman.d.ts +538 -0
  47. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/stringman.d.ts.map +1 -0
  48. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/stringman.js +626 -0
  49. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/struct.d.ts +734 -0
  50. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/struct.d.ts.map +1 -0
  51. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/struct.js +764 -0
  52. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedbuffer.d.ts +137 -0
  53. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedbuffer.d.ts.map +1 -0
  54. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedbuffer.js +234 -0
  55. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedefs.d.ts +391 -0
  56. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedefs.d.ts.map +1 -0
  57. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedefs.js +8 -0
  58. package/esm/deps.d.ts +56 -0
  59. package/esm/deps.d.ts.map +1 -0
  60. package/esm/deps.js +37 -0
  61. package/esm/esbuild/metafile.d.ts +90 -0
  62. package/esm/esbuild/metafile.d.ts.map +1 -0
  63. package/esm/esbuild/metafile.js +275 -0
  64. package/esm/esbuild/native.d.ts +95 -0
  65. package/esm/esbuild/native.d.ts.map +1 -0
  66. package/esm/esbuild/native.js +127 -0
  67. package/esm/esbuild/outputfile.d.ts +86 -0
  68. package/esm/esbuild/outputfile.d.ts.map +1 -0
  69. package/esm/esbuild/outputfile.js +221 -0
  70. package/esm/esbuild/strongtypes.d.ts +90 -0
  71. package/esm/esbuild/strongtypes.d.ts.map +1 -0
  72. package/esm/esbuild/strongtypes.js +8 -0
  73. package/esm/esbuild/typedefs.d.ts +121 -0
  74. package/esm/esbuild/typedefs.d.ts.map +1 -0
  75. package/esm/esbuild/typedefs.js +55 -0
  76. package/esm/esbuild/weaktypes.d.ts +46 -0
  77. package/esm/esbuild/weaktypes.d.ts.map +1 -0
  78. package/esm/esbuild/weaktypes.js +8 -0
  79. package/esm/funcdefs.d.ts +89 -0
  80. package/esm/funcdefs.d.ts.map +1 -0
  81. package/esm/funcdefs.js +145 -0
  82. package/esm/mod.d.ts +4 -0
  83. package/esm/mod.d.ts.map +1 -0
  84. package/esm/mod.js +2 -0
  85. package/esm/package.json +3 -0
  86. package/esm/plugins/emissions_driver.d.ts +33 -0
  87. package/esm/plugins/emissions_driver.d.ts.map +1 -0
  88. package/esm/plugins/emissions_driver.js +260 -0
  89. package/esm/plugins/long_build.d.ts +138 -0
  90. package/esm/plugins/long_build.d.ts.map +1 -0
  91. package/esm/plugins/long_build.js +288 -0
  92. package/esm/plugins/native_replica.d.ts +48 -0
  93. package/esm/plugins/native_replica.d.ts.map +1 -0
  94. package/esm/plugins/native_replica.js +122 -0
  95. package/esm/super/build.d.ts +53 -0
  96. package/esm/super/build.d.ts.map +1 -0
  97. package/esm/super/build.js +39 -0
  98. package/esm/super/build_context.d.ts +83 -0
  99. package/esm/super/build_context.d.ts.map +1 -0
  100. package/esm/super/build_context.js +124 -0
  101. package/esm/super/mod.d.ts +12 -0
  102. package/esm/super/mod.d.ts.map +1 -0
  103. package/esm/super/mod.js +9 -0
  104. package/esm/super/plugin.d.ts +23 -0
  105. package/esm/super/plugin.d.ts.map +1 -0
  106. package/esm/super/plugin.js +31 -0
  107. package/esm/super/plugin_build.d.ts +38 -0
  108. package/esm/super/plugin_build.d.ts.map +1 -0
  109. package/esm/super/plugin_build.js +198 -0
  110. package/esm/super/typedefs.d.ts +323 -0
  111. package/esm/super/typedefs.d.ts.map +1 -0
  112. package/esm/super/typedefs.js +10 -0
  113. package/esm/typedefs.d.ts +21 -0
  114. package/esm/typedefs.d.ts.map +1 -0
  115. package/esm/typedefs.js +5 -0
  116. package/license.md +37 -0
  117. package/package.json +88 -0
  118. package/readme.md +181 -0
@@ -0,0 +1,275 @@
1
+ /** utility submodule for converting esbuild's metafile and output file interfaces into more convenient and manageable format.
2
+ *
3
+ * @module
4
+ */
5
+ import { ensureFile, ensureRelativeDotSlash, identifyCurrentRuntime, isAbsolutePath, object_entries, object_fromEntries, object_keys, pathToPosixPath, statEntry, writeFile } from "../deps.js";
6
+ import { splitNamespacedPath } from "../funcdefs.js";
7
+ import { OutputFileEntity } from "./outputfile.js";
8
+ // regex for detecting if a path is an absolute windows path. copied from `@oazmi/kitchensink/pathman`.
9
+ const windows_absolute_path_regex = /^[a-z]\:[\/\\]/i;
10
+ /** normalize an esbuild resolved file path so that it:
11
+ * - uses posix `"/"` directory separators.
12
+ * - always has a leading `"./"` for relative paths.
13
+ * - is always in the `${namespace}:${path}` format, even when `namespace === "file".`
14
+ */
15
+ const normalize_esbuild_filepath = (path) => {
16
+ const is_local_path = !path.includes(":") || windows_absolute_path_regex.test(path);
17
+ return is_local_path
18
+ ? "file:" + normalize_local_filepath(path)
19
+ : path;
20
+ };
21
+ const normalize_local_filepath = (path) => {
22
+ const is_abs_path = isAbsolutePath(path);
23
+ return pathToPosixPath(is_abs_path ? path : ensureRelativeDotSlash(path));
24
+ };
25
+ const file_namespace = "file:", file_namespace_length = file_namespace.length;
26
+ const namespaced_path_to_abs_namespaced_path_factory = (resolve_path_fn) => {
27
+ return (namespaced_path) => {
28
+ if (!namespaced_path.startsWith(file_namespace)) {
29
+ return namespaced_path;
30
+ }
31
+ const abs_path = resolve_path_fn(namespaced_path.slice(file_namespace_length));
32
+ return file_namespace + abs_path;
33
+ };
34
+ };
35
+ export class Metafile {
36
+ value;
37
+ inputs;
38
+ outputs;
39
+ outputFileEntities = new Map();
40
+ /** a copy of the {@link SuperBuildContext.resolvedResourceRegistry}, where all keys use lower case characters.
41
+ * this is extremely important, as we've internally standardized to using only lower casing for namespaced resolved paths,
42
+ * in order to evade the filesystem case-insesnsitivity problem when matching strings.
43
+ */
44
+ resolvedResourceRegistry;
45
+ /** a function that resolves the given path segment to an absolute path, with respect to `cwd` or `absWorkingDir`. */
46
+ resolvePath;
47
+ /** holds all warnings that have occurred during method calls. */
48
+ warnings = [];
49
+ constructor(esbuild_metafile, config) {
50
+ const { resolvedResourceRegistry, resolvePath } = config;
51
+ esbuild_metafile = Metafile.asNormalized(esbuild_metafile);
52
+ esbuild_metafile = Metafile.asAbsolute(esbuild_metafile, { resolvePath: resolvePath });
53
+ esbuild_metafile = Metafile.asLowercased(esbuild_metafile, {
54
+ namespacedPaths: true,
55
+ outputPaths: true,
56
+ externalPaths: false,
57
+ });
58
+ const { result: registry_lowercase, warnings } = format_resolved_resource_registry(resolvedResourceRegistry);
59
+ this.value = esbuild_metafile;
60
+ this.resolvedResourceRegistry = registry_lowercase;
61
+ this.resolvePath = resolvePath;
62
+ this.inputs = new Map(object_entries(this.value.inputs));
63
+ this.outputs = new Map(object_entries(this.value.outputs).map(([output_path_lowercase, props]) => {
64
+ return [output_path_lowercase, {
65
+ entryPoint: props.entryPoint,
66
+ inputs: object_keys(props.inputs),
67
+ imports: props.imports.map(({ path, kind, external = false }) => ({ path, kind, external })),
68
+ }];
69
+ }));
70
+ this.warnings.push(...warnings);
71
+ }
72
+ addFile(esbuild_file) {
73
+ const file_entity = new OutputFileEntity(this, esbuild_file), output_path_lowercase = (file_entity.initialPath ?? file_entity.outputPath).toLowerCase();
74
+ this.outputFileEntities.set(output_path_lowercase, file_entity);
75
+ return file_entity;
76
+ }
77
+ /** this function is intended to run _after_ you have added **all** of your {@link EsbuildOutputFile | esbuild output files} via {@link addFile}.
78
+ * what it does is that it simply calls the {@link OutputFileEntity.scanEsbuildImports} method of each {@link outputFileEntities | registered file},
79
+ * so that they can discover the file entity associated which each of their esbuild-based imports.
80
+ */
81
+ scanEsbuildImports() {
82
+ this.outputFileEntities.forEach((file_entity) => {
83
+ file_entity.scanEsbuildImports();
84
+ });
85
+ }
86
+ /** find the file entity corresponding to the given absolute output path. you won't receive entities associated with external paths/references. */
87
+ getFile(output_path_key) {
88
+ output_path_key = output_path_key.toLowerCase();
89
+ const file_entity = this.outputFileEntities.get(output_path_key);
90
+ if (file_entity) {
91
+ return file_entity;
92
+ }
93
+ this.warnings.push({ text: `[Metafile.getFile]: no file entity with the following path key was ever added: "${output_path_key}".` });
94
+ }
95
+ /** find all file entities that incorporate (i.e. originate from) certain namespaced source files/resources into their bundled form. */
96
+ findFileFromSources(predicate_fn) {
97
+ const file_entity_matches = [];
98
+ this.outputFileEntities.forEach((file_entity) => {
99
+ const file_sources = file_entity.inputs.map(({ namespace, path }) => ({ namespace, path }));
100
+ if (predicate_fn(file_sources)) {
101
+ file_entity_matches.push(file_entity);
102
+ }
103
+ });
104
+ return file_entity_matches;
105
+ }
106
+ /** prepares a dependency graph from the current list of {@link outputFileEntities}. */
107
+ createFileDependencyGraph() {
108
+ const graph = new Map();
109
+ for (const [output_path_key, entity] of this.outputFileEntities) {
110
+ const dependencies = entity.imports
111
+ // external resources do not contribute to dependency graph, as they themselves (the external resources) do not get emitted, nor do they go through the emission stage.
112
+ .filter((dep_node) => { return !("externalPath" in dep_node.entity); })
113
+ .map((dep_node) => { return dep_node.entity; });
114
+ graph.set(entity, new Set(dependencies));
115
+ }
116
+ return graph;
117
+ }
118
+ /** write all output file entities (those with `entity.write !== false`) to the filesystem. */
119
+ async writeFiles(allow_overwrite = false) {
120
+ const current_runtime = identifyCurrentRuntime(), write_file_fn = async (file_path, data) => {
121
+ // if overwriting is not permitted and an entry already exists at the given `file_path`, then skip writing.
122
+ if (!allow_overwrite && await statEntry(current_runtime, file_path)) {
123
+ return;
124
+ }
125
+ await ensureFile(current_runtime, file_path);
126
+ await writeFile(current_runtime, file_path, data);
127
+ };
128
+ const promises = [...this.outputFileEntities].map(async ([output_path_key, entity]) => {
129
+ const is_external_entity = "externalPath" in entity;
130
+ if (is_external_entity) {
131
+ return;
132
+ }
133
+ return entity.writeFile(write_file_fn);
134
+ });
135
+ await Promise.all(promises);
136
+ }
137
+ /** normalizes an esbuild metafile to use namespaced paths (`${namespace}:${resolved_path}`) for resolved paths,
138
+ * and absolute paths for output file paths.
139
+ *
140
+ * this function mutates the original metafile object passed to it.
141
+ */
142
+ static asNormalized(esbuild_metafile) {
143
+ const { inputs, outputs } = esbuild_metafile;
144
+ esbuild_metafile.inputs = object_fromEntries(object_entries(inputs).map(([resolved_path, props]) => {
145
+ // resolved path name of this input file.
146
+ resolved_path = normalize_esbuild_filepath(resolved_path);
147
+ // direct dependencies of this input file as resolved paths.
148
+ props.imports = props.imports.map((props) => {
149
+ props.path = normalize_esbuild_filepath(props.path);
150
+ return props;
151
+ });
152
+ return [resolved_path, props];
153
+ }));
154
+ esbuild_metafile.outputs = object_fromEntries(object_entries(outputs).map(([output_path, props]) => {
155
+ // path name of the output file (including the path to the `outdir` relative to the `cwd` or `absWorkingDir`).
156
+ output_path = normalize_local_filepath(output_path);
157
+ // list of linked output files that are referenced by this resource (but not bundled into it).
158
+ // even though the import paths are relative, they are relative to the `cwd` or `absWorkingDir`,
159
+ // and not relative to the `pathname`.
160
+ props.imports = props.imports.map((props) => {
161
+ props.path = normalize_local_filepath(props.path);
162
+ return props;
163
+ });
164
+ // list of files (as resolved paths) that were bundled into this resource.
165
+ props.inputs = object_fromEntries(object_entries(props.inputs).map(([resolved_path, props]) => {
166
+ return [normalize_esbuild_filepath(resolved_path), props];
167
+ }));
168
+ // entrypoint's resolved path corresponding to this output resource.
169
+ if (props.entryPoint) {
170
+ props.entryPoint = normalize_esbuild_filepath(props.entryPoint);
171
+ }
172
+ return [output_path, props];
173
+ }));
174
+ return esbuild_metafile;
175
+ }
176
+ /** lower the casing of an esbuild metafile's namespaced resolved paths,
177
+ * output file paths, and external paths, based on your `config` configuration.
178
+ *
179
+ * lower casing helps in ensuring that there won't be any casing conflicts when searching for a particular resource.
180
+ *
181
+ * this function mutates the original metafile object passed to it.
182
+ */
183
+ static asLowercased(esbuild_metafile, config) {
184
+ const { namespacedPaths, outputPaths, externalPaths } = config, { inputs, outputs } = esbuild_metafile;
185
+ esbuild_metafile.inputs = object_fromEntries(object_entries(inputs).map(([resolved_path, props]) => {
186
+ if (namespacedPaths) {
187
+ resolved_path = resolved_path.toLowerCase();
188
+ props.imports = props.imports.map((props) => {
189
+ props.path = props.path.toLowerCase();
190
+ return props;
191
+ });
192
+ }
193
+ return [resolved_path, props];
194
+ }));
195
+ esbuild_metafile.outputs = object_fromEntries(object_entries(outputs).map(([output_path, props]) => {
196
+ if (namespacedPaths) {
197
+ props.inputs = object_fromEntries(object_entries(props.inputs).map(([resolved_path, props]) => {
198
+ return [resolved_path.toLowerCase(), props];
199
+ }));
200
+ if (props.entryPoint) {
201
+ props.entryPoint = props.entryPoint.toLowerCase();
202
+ }
203
+ }
204
+ if (outputPaths) {
205
+ output_path = output_path.toLowerCase();
206
+ props.imports = props.imports.map((props) => {
207
+ // only lower the casing of non-external paths if `externalPaths` is disabled.
208
+ if (externalPaths || !(props.external ?? false)) {
209
+ props.path = props.path.toLowerCase();
210
+ }
211
+ return props;
212
+ });
213
+ }
214
+ return [output_path, props];
215
+ }));
216
+ return esbuild_metafile;
217
+ }
218
+ /** resolve all relative file paths in a {@link asNormalized | **normalized**} esbuild metafile to absolute file paths.
219
+ *
220
+ * this function mutates the original metafile object passed to it.
221
+ */
222
+ static asAbsolute(esbuild_metafile, config) {
223
+ const { resolvePath } = config, namespaced_path_to_abs_namespaced_path = namespaced_path_to_abs_namespaced_path_factory(resolvePath), output_entries = object_entries(esbuild_metafile.outputs);
224
+ esbuild_metafile.outputs = object_fromEntries(output_entries.map(([output_path, props]) => {
225
+ output_path = resolvePath(output_path);
226
+ props.entryPoint = props.entryPoint ? namespaced_path_to_abs_namespaced_path(props.entryPoint) : undefined;
227
+ props.inputs = object_fromEntries(object_entries(props.inputs).map(([input_path, props]) => {
228
+ input_path = namespaced_path_to_abs_namespaced_path(input_path);
229
+ return [input_path, props];
230
+ }));
231
+ props.imports = props.imports.map((props) => {
232
+ // only non-external paths must be resolved to an absolute output local file path.
233
+ props.path = props.external
234
+ ? props.path
235
+ : resolvePath(props.path);
236
+ return props;
237
+ });
238
+ return [output_path, props];
239
+ }));
240
+ return esbuild_metafile;
241
+ }
242
+ }
243
+ /** turns all keys of {@link SuperBuildContext.resolvedResourceRegistry} to lower case, while documenting any key conflicts that occur as a result. */
244
+ const format_resolved_resource_registry = (registry) => {
245
+ const warnings = [], registry_lowercase = new Map([...registry].map(([resolved_path, props]) => {
246
+ return [resolved_path.toLowerCase(), props];
247
+ }));
248
+ if (registry_lowercase.size < registry.size) {
249
+ const size_difference = registry.size - registry_lowercase.size, conflicting_keys = new Set(), encountered_lowercase_keys = new Map([...registry].map(([key, props]) => {
250
+ const key_lowercase = key.toLowerCase();
251
+ return [key_lowercase, key];
252
+ }));
253
+ for (const [key, props] of registry) {
254
+ const key_lowercase = key.toLowerCase(), key_original = encountered_lowercase_keys.get(key_lowercase);
255
+ if (key_original !== key) {
256
+ conflicting_keys.add(key);
257
+ conflicting_keys.add(key_original);
258
+ }
259
+ }
260
+ warnings.push({
261
+ text: `[format_resolved_resource_registry]: ${size_difference} resolved resources use the same name, but only differ in letter casing. `
262
+ + `right now, super-build is not able to distinguish between the two (in order to achieve path name casing insensitivity), `
263
+ + `so this problem will likely mess up your build. `
264
+ + `if it's possible, you should change the name of the duplicate resources. see the notes for the conflicting resource names:`,
265
+ notes: [...conflicting_keys].map((resolved_path) => {
266
+ const { path, namespace } = splitNamespacedPath(resolved_path);
267
+ return {
268
+ text: `conflicting key: "${resolved_path.toLowerCase()}"`,
269
+ location: { file: path, namespace: namespace },
270
+ };
271
+ }),
272
+ });
273
+ }
274
+ return { result: registry_lowercase, warnings };
275
+ };
@@ -0,0 +1,95 @@
1
+ /** a submodule to mimic some of esbuild's native behavior.
2
+ *
3
+ * TODO: in the future, make this _version_ dependent, using your `semver` submodule from kitchensink to match the version to a behavior.
4
+ * also, use a factory function that takes in concrete semver version of esbuild, and then returns a function that matches the desired behavior.
5
+ *
6
+ * @module
7
+ */
8
+ import type { EsbuildLoaderTypeOrEmpty, OnLoadArgs } from "./strongtypes.js";
9
+ /** this function guesses which esbuild loader to use, based on the files extension of the file.
10
+ *
11
+ * the way it works is by finding the longest matching suffix defined in the list of user-defined file-extensions,
12
+ * and the predefined list of known file-extensions ({@link defaultExtensionToLoaderMap}),
13
+ * while also taking into account any `with` attribute arguments that may be present when the import was being performed.
14
+ *
15
+ * this function is roughly based on the following esbuild function:
16
+ * [`"/internal/config/config.go":LoaderFromFileExtension`](https://github.com/evanw/esbuild/blob/6ff1d8b0d8c134e867a397eef39702a223ebef9e/internal/config/config.go#L259)
17
+ *
18
+ * > [!important]
19
+ * > while esbuild generally gives priority to any import-attributes (`with_attr`) that may be present, over file-extension based loader guessing,
20
+ * > it makes an exception with regards to any file-extensions that uses the `"copy"` loader, giving it the highest priority.
21
+ * > you can see this behavior detailed in the following line of esbuild:
22
+ * > [`"/internal/bundler/bundler.go":parseFile`](https://github.com/evanw/esbuild/blob/6ff1d8b0d8c134e867a397eef39702a223ebef9e/internal/bundler/bundler.go#L201)
23
+ *
24
+ * > [!note]
25
+ * > the only behavioral difference in this function and esbuild's own function is that the default loader
26
+ * > (for unidentified file-extensions, or those with none) resolves to `undefined` rather than `"js"`.
27
+ * >
28
+ * > the reason for this is because this information can be useful to the person using this function,
29
+ * > in addition to not causing any harm if this info is not utilized,
30
+ * > as passing an `undefined` loader to esbuild will cause it to use the `"js"` loader anyway.
31
+ *
32
+ * @param ext_to_loader_map a map tying file-extensions with loaders.
33
+ * @param with_attr_type_map a mapping between `with.type` attributes and their respective loaders.
34
+ * @param file_path the file path or url to guess the loader type from.
35
+ * @param with_attr specify an optional `with` attribute dictionary that might be present.
36
+ * @returns the appropriate esbuild loader type for the given file path.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { assertEquals, assertThrows } from "jsr:@std/assert"
41
+ * import { EsbuildLoaderTypeOrEmpty } from "./strongtypes.ts"
42
+ *
43
+ * const my_loader_map: Record<string, EsbuildLoaderTypeOrEmpty> = {
44
+ * "": undefined,
45
+ * ".js": "js",
46
+ * ".jsx": "jsx",
47
+ * ".ts": "ts",
48
+ * ".css": "css",
49
+ * ".module.css": "local-css",
50
+ * ".json": "json",
51
+ * ".txt.json": "text",
52
+ * ".txt.json.png": "copy",
53
+ * ".png": "file",
54
+ * }
55
+ *
56
+ * const my_with_type_map: Record<string, EsbuildLoaderTypeOrEmpty> = {
57
+ * "json": "json",
58
+ * "bytes": "binary",
59
+ * "image": "binary",
60
+ * "empty": undefined,
61
+ * }
62
+ *
63
+ * // aliasing our function for brevity
64
+ * const fn = (path: string, with_attr?: Record<string, string>) => {
65
+ * return loaderFromFileExtension(my_loader_map, my_with_type_map, path, with_attr)
66
+ * }
67
+ *
68
+ * // non-with import attribute tests:
69
+ * assertEquals(fn("./hello/.world/.vscode/settings.json"), "json")
70
+ * assertEquals(fn("./settings.json"), "json")
71
+ * assertEquals(fn("./.settings.txt.json"), "text")
72
+ * assertEquals(fn("~/home/hello/meow.module.css"), "local-css")
73
+ * assertEquals(fn("/some/dir/"), undefined)
74
+ * assertEquals(fn("/some/dir/file.js"), "js")
75
+ * assertEquals(fn("/some/dir/file.js.ts"), "ts")
76
+ *
77
+ * // with import attribute tests:
78
+ * assertEquals(fn("./settings.txt.json", { type: "empty" }), undefined)
79
+ * assertEquals(fn("./settings.txt.json", { type: "image" }), "binary")
80
+ * // below, notice that the "copy" loader gets a higher precedence than any import attribute.
81
+ * assertEquals(fn("./settings.txt.json.png", { type: "image" }), "copy")
82
+ * ```
83
+ */
84
+ export declare const loaderFromFileExtension: (ext_to_loader_map: Record<string, EsbuildLoaderTypeOrEmpty>, with_attr_type_map: Record<string, EsbuildLoaderTypeOrEmpty>, file_path: string | URL, with_attr?: OnLoadArgs["with"]) => EsbuildLoaderTypeOrEmpty;
85
+ /** the return type of {@link guessExtensionLoader_Factory},
86
+ * which guesses a file's loader based on its file-path and the import's `with` attributes,
87
+ * behaving similar to how esbuild behaves natively.
88
+ */
89
+ export type GuessExtensionLoader = (file_path: string | URL, with_attr?: OnLoadArgs["with"]) => EsbuildLoaderTypeOrEmpty;
90
+ /** returns a function that guesses the loader that esbuild would natively suggest for a given input file path.
91
+ *
92
+ * this factory function expects to be provided with the user's {@link EsbuildPluginBuild["initialOptions"]["loader"]} map.
93
+ */
94
+ export declare const guessExtensionLoader_Factory: (user_ext_to_loader_map: Record<string, EsbuildLoaderTypeOrEmpty>) => GuessExtensionLoader;
95
+ //# sourceMappingURL=native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../src/esbuild/native.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAGF,OAAO,KAAK,EAAE,wBAAwB,EAAsB,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAIhG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0EE;AACF,eAAO,MAAM,uBAAuB,sBAChB,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,sBACvC,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,aACjD,MAAM,GAAG,GAAG,cACX,UAAU,CAAC,MAAM,CAAC,KAC5B,wBAwBF,CAAA;AAED;;;EAGE;AACF,MAAM,MAAM,oBAAoB,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,EAAE,SAAS,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,KAAK,wBAAwB,CAAA;AAExH;;;EAGE;AACF,eAAO,MAAM,4BAA4B,2BAA4B,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,KAAG,oBAW/G,CAAA"}
@@ -0,0 +1,127 @@
1
+ /** a submodule to mimic some of esbuild's native behavior.
2
+ *
3
+ * TODO: in the future, make this _version_ dependent, using your `semver` submodule from kitchensink to match the version to a behavior.
4
+ * also, use a factory function that takes in concrete semver version of esbuild, and then returns a function that matches the desired behavior.
5
+ *
6
+ * @module
7
+ */
8
+ import { DEBUG, isString, parseFilepathInfo, urlToString } from "../deps.js";
9
+ import { defaultExtensionToLoaderMap } from "./typedefs.js";
10
+ /** this function guesses which esbuild loader to use, based on the files extension of the file.
11
+ *
12
+ * the way it works is by finding the longest matching suffix defined in the list of user-defined file-extensions,
13
+ * and the predefined list of known file-extensions ({@link defaultExtensionToLoaderMap}),
14
+ * while also taking into account any `with` attribute arguments that may be present when the import was being performed.
15
+ *
16
+ * this function is roughly based on the following esbuild function:
17
+ * [`"/internal/config/config.go":LoaderFromFileExtension`](https://github.com/evanw/esbuild/blob/6ff1d8b0d8c134e867a397eef39702a223ebef9e/internal/config/config.go#L259)
18
+ *
19
+ * > [!important]
20
+ * > while esbuild generally gives priority to any import-attributes (`with_attr`) that may be present, over file-extension based loader guessing,
21
+ * > it makes an exception with regards to any file-extensions that uses the `"copy"` loader, giving it the highest priority.
22
+ * > you can see this behavior detailed in the following line of esbuild:
23
+ * > [`"/internal/bundler/bundler.go":parseFile`](https://github.com/evanw/esbuild/blob/6ff1d8b0d8c134e867a397eef39702a223ebef9e/internal/bundler/bundler.go#L201)
24
+ *
25
+ * > [!note]
26
+ * > the only behavioral difference in this function and esbuild's own function is that the default loader
27
+ * > (for unidentified file-extensions, or those with none) resolves to `undefined` rather than `"js"`.
28
+ * >
29
+ * > the reason for this is because this information can be useful to the person using this function,
30
+ * > in addition to not causing any harm if this info is not utilized,
31
+ * > as passing an `undefined` loader to esbuild will cause it to use the `"js"` loader anyway.
32
+ *
33
+ * @param ext_to_loader_map a map tying file-extensions with loaders.
34
+ * @param with_attr_type_map a mapping between `with.type` attributes and their respective loaders.
35
+ * @param file_path the file path or url to guess the loader type from.
36
+ * @param with_attr specify an optional `with` attribute dictionary that might be present.
37
+ * @returns the appropriate esbuild loader type for the given file path.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * import { assertEquals, assertThrows } from "jsr:@std/assert"
42
+ * import { EsbuildLoaderTypeOrEmpty } from "./strongtypes.ts"
43
+ *
44
+ * const my_loader_map: Record<string, EsbuildLoaderTypeOrEmpty> = {
45
+ * "": undefined,
46
+ * ".js": "js",
47
+ * ".jsx": "jsx",
48
+ * ".ts": "ts",
49
+ * ".css": "css",
50
+ * ".module.css": "local-css",
51
+ * ".json": "json",
52
+ * ".txt.json": "text",
53
+ * ".txt.json.png": "copy",
54
+ * ".png": "file",
55
+ * }
56
+ *
57
+ * const my_with_type_map: Record<string, EsbuildLoaderTypeOrEmpty> = {
58
+ * "json": "json",
59
+ * "bytes": "binary",
60
+ * "image": "binary",
61
+ * "empty": undefined,
62
+ * }
63
+ *
64
+ * // aliasing our function for brevity
65
+ * const fn = (path: string, with_attr?: Record<string, string>) => {
66
+ * return loaderFromFileExtension(my_loader_map, my_with_type_map, path, with_attr)
67
+ * }
68
+ *
69
+ * // non-with import attribute tests:
70
+ * assertEquals(fn("./hello/.world/.vscode/settings.json"), "json")
71
+ * assertEquals(fn("./settings.json"), "json")
72
+ * assertEquals(fn("./.settings.txt.json"), "text")
73
+ * assertEquals(fn("~/home/hello/meow.module.css"), "local-css")
74
+ * assertEquals(fn("/some/dir/"), undefined)
75
+ * assertEquals(fn("/some/dir/file.js"), "js")
76
+ * assertEquals(fn("/some/dir/file.js.ts"), "ts")
77
+ *
78
+ * // with import attribute tests:
79
+ * assertEquals(fn("./settings.txt.json", { type: "empty" }), undefined)
80
+ * assertEquals(fn("./settings.txt.json", { type: "image" }), "binary")
81
+ * // below, notice that the "copy" loader gets a higher precedence than any import attribute.
82
+ * assertEquals(fn("./settings.txt.json.png", { type: "image" }), "copy")
83
+ * ```
84
+ */
85
+ export const loaderFromFileExtension = (ext_to_loader_map, with_attr_type_map, file_path, with_attr) => {
86
+ // first, we check if any `withAttr.type` exists that matches with the provided `withAttr mapping`.
87
+ const with_attr_type = with_attr?.type;
88
+ if (isString(with_attr_type) && (with_attr_type in with_attr_type_map)) {
89
+ // we don't return immediately because esbuild makes an exception for the "copy" loader,
90
+ // giving it a higher precedence over any with-import attribute.
91
+ const suggested_loader_without_with_attr = loaderFromFileExtension(ext_to_loader_map, with_attr_type_map, file_path);
92
+ return suggested_loader_without_with_attr === "copy"
93
+ ? suggested_loader_without_with_attr
94
+ : with_attr_type_map[with_attr_type];
95
+ }
96
+ // next, we pick the longest matching extension by recursively trimming down the `".${remaining_ext}"` until a match is found.
97
+ const filename = parseFilepathInfo(urlToString(file_path)).filename;
98
+ let slice_idx = 0;
99
+ while (true) {
100
+ slice_idx = filename.indexOf(".", slice_idx);
101
+ const remaining_ext = (slice_idx >= 0) ? filename.slice(slice_idx) : "";
102
+ if (remaining_ext in ext_to_loader_map) {
103
+ return ext_to_loader_map[remaining_ext];
104
+ }
105
+ if (slice_idx < 0) {
106
+ break;
107
+ }
108
+ slice_idx++; // we must move the cursor forward by one, so that the starting `"."` is ignored.
109
+ }
110
+ // the above should eventually match all possible file-extensions if the `""` extension is also present there (which it is, in esbuild's default config).
111
+ // however, if for some reason we end up at this point, then we'll throw an error.
112
+ throw new Error(DEBUG.ERROR ? `[loaderFromFileExtension]: expected at least one file-extension to match with the path: "${file_path}".` : "");
113
+ };
114
+ /** returns a function that guesses the loader that esbuild would natively suggest for a given input file path.
115
+ *
116
+ * this factory function expects to be provided with the user's {@link EsbuildPluginBuild["initialOptions"]["loader"]} map.
117
+ */
118
+ export const guessExtensionLoader_Factory = (user_ext_to_loader_map) => {
119
+ const ext_to_loader_map = { ...defaultExtensionToLoaderMap, ...user_ext_to_loader_map }, with_attr_type_map = {
120
+ "json": "json",
121
+ "bytes": "binary",
122
+ "text": "text",
123
+ };
124
+ return (file_path, with_attr) => {
125
+ return loaderFromFileExtension(ext_to_loader_map, with_attr_type_map, file_path, with_attr);
126
+ };
127
+ };
@@ -0,0 +1,86 @@
1
+ /** a utility submodule that works alongside {@link Metafile} to aid in holding onto a given file's contents, path, inputs, and imports,
2
+ * in addition to providing useful file-related methods, such as {@link OnEmitOptions} filter matching, and etc...
3
+ *
4
+ * @module
5
+ */
6
+ import { type Require } from "../deps.js";
7
+ import type { OnEmitHandler } from "../super/build_context.js";
8
+ import type { BundledInputFile, ImportedEntity, OnEmitOptions, OnEmitResult } from "../super/typedefs.js";
9
+ import type { AbsolutePath, Path } from "../typedefs.js";
10
+ import type { Metafile } from "./metafile.js";
11
+ import type { EsbuildOutputFile } from "./typedefs.js";
12
+ /** an imported entity node, similar to {@link ImportedEntity}, but with a shared {@link entity} object field. */
13
+ export interface ImportedEntityNode<K = any> extends Pick<ImportedEntity<K>, "key" | "with" | "kind" | "external"> {
14
+ /** the output file entity being referenced by this import.
15
+ * this is present even when resource being referenced is an external resource.
16
+ */
17
+ entity: OutputFileEntity | ExternalFileEntity;
18
+ }
19
+ export interface ExternalFileEntity {
20
+ /** the **absolute** external path of this external resource entity. */
21
+ externalPath: AbsolutePath;
22
+ }
23
+ /** this dictionary maps an output file's **original** absolute output path to its {@link OutputFileEntity} object.
24
+ *
25
+ * the keys of this map are always in **lower casing**, and never change, even after an output file has been renamed via {@link OnEmitResult.path}.
26
+ * the way to acquire a given {@link OutputFileEntity}'s original output path key is by simply performing:
27
+ * `original_path_key = (file_entity.initialPath ?? file_entity.outputPath).toLowerCase()`.
28
+ */
29
+ export type OutputFileEntityMap = Map<string, OutputFileEntity>;
30
+ export type WriteFileFn = (file_path: string | URL, data: ArrayBufferView) => Promise<void>;
31
+ export declare class OutputFileEntity implements Require<Pick<EsbuildOutputFile, "contents" | "hash">, "contents"> {
32
+ /** the **absolute** output path of this resource entity. */
33
+ outputPath: AbsolutePath;
34
+ /** if this resource entity was renamed during the {@link SuperPluginBuild.onEmit, emission stage},
35
+ * then its original (absolute) {@link outputPath} will get saved here.
36
+ */
37
+ initialPath?: AbsolutePath;
38
+ hash?: string;
39
+ contents: Uint8Array<ArrayBuffer>;
40
+ /** specify if this file entry should be written.
41
+ *
42
+ * @defaultValue `true` (i.e. it'll be written if `EsbuildBuildOption.write` is enabled, otherwise it won't be.)
43
+ */
44
+ write: boolean;
45
+ /** an array of metadata on the loaded input files that were bundled into _this_ physical output file entity. */
46
+ inputs: Readonly<BundledInputFile>[];
47
+ /** an array of metadata on the output files that are imported by _this_ file entity during runtime.
48
+ *
49
+ * each of these is basically associated with a js (`import { x, y, z } from "abc"`), css (`@import url("./blahblah.css")`),
50
+ * or user-import (i.e. {@link OnTransformResult.imports}) statement.
51
+ */
52
+ imports: Readonly<ImportedEntityNode<any>>[];
53
+ protected metafile: Metafile;
54
+ constructor(metafile: Metafile, esbuild_file: EsbuildOutputFile);
55
+ /** scans esbuild's metafile outputs to find the input sources bundled into this output file.
56
+ * the input sources are presented with resolved path information, namespace, `onEmit` information,
57
+ * and other additional information acquired from the resource's resolver, loader, and transformer results.
58
+ * (the collection of this information is stored in {@link metafile.resolvedResourceRegistry},
59
+ * which is inherited from the {@link SuperBuildContext}.)
60
+ */
61
+ scanEsbuildInputs(): typeof this.inputs;
62
+ /** scans esbuild's metafile outputs to find all file imports performed by this output file.
63
+ * these only include entity imports found by esbuild natively (js imports, css imports, etc...), and not long-build plugin based imports.
64
+ *
65
+ * > [!important]
66
+ * > this function should be run _after_ all files have been added to your {@link metafile} via {@link metafile.addFile},
67
+ * > because the imports need to reference the {@link OutputFileEntity} associated with the imported file.
68
+ */
69
+ scanEsbuildImports(): typeof this.imports;
70
+ /** test if an `onEmit` handler's filters apply to _this_ output file entity. */
71
+ protected matchOnEmitFilter(options: OnEmitOptions): boolean;
72
+ /** perform `onEmit` action on _this_ output file entity, based on the provided `onEmit` handlers. */
73
+ performOnEmit(on_emit_handlers: Array<OnEmitHandler>): Promise<OnEmitResult | undefined>;
74
+ /** rename this file. you can either provide an absolute path, or a relative path.
75
+ * relative paths will be resolved with respect to the `cwd` or esbuild's `absWorkingDir`.
76
+ */
77
+ rename(new_output_path: Path): void;
78
+ /** convert an output file entity to an esbuild-compatible {@link EsbuildOutputFile | output file description}.
79
+ *
80
+ * (honestly, I don't see myself using it, and if we're overloading esbuild anyway, why don't we overload the `OutputFile`
81
+ * interface to include new fields, such as `write` and `external`, etc...?)
82
+ */
83
+ toEsbuildOutputFile(outdir?: Path): Require<EsbuildOutputFile, "path" | "contents"> | undefined;
84
+ writeFile(write_file_fn: WriteFileFn): Promise<void>;
85
+ }
86
+ //# sourceMappingURL=outputfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outputfile.d.ts","sourceRoot":"","sources":["../../src/esbuild/outputfile.ts"],"names":[],"mappings":"AAAA;;;;EAIE;AAEF,OAAO,EAA8D,KAAK,OAAO,EAAE,MAAM,YAAY,CAAA;AACrG,OAAO,KAAK,EAAE,aAAa,EAAqB,MAAM,2BAA2B,CAAA;AAEjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAqB,MAAM,sBAAsB,CAAA;AAC5H,OAAO,KAAK,EAAE,YAAY,EAAkB,IAAI,EAAE,MAAM,gBAAgB,CAAA;AACxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAGtD,iHAAiH;AACjH,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,GAAG,CAAE,SAAQ,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;IACjH;;MAEE;IACF,MAAM,EAAE,gBAAgB,GAAG,kBAAkB,CAAA;CAC7C;AAED,MAAM,WAAW,kBAAkB;IAClC,uEAAuE;IACvE,YAAY,EAAE,YAAY,CAAA;CAC1B;AAED;;;;;EAKE;AACF,MAAM,MAAM,mBAAmB,GAAG,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;AAE/D,MAAM,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAE3F,qBAAa,gBAAiB,YAAW,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,UAAU,GAAG,MAAM,CAAC,EAAE,UAAU,CAAC;IACzG,4DAA4D;IACrD,UAAU,EAAE,YAAY,CAAA;IAE/B;;MAEE;IACK,WAAW,CAAC,EAAE,YAAY,CAAA;IAE1B,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb,QAAQ,EAAE,UAAU,CAAC,WAAW,CAAC,CAAA;IAExC;;;MAGE;IACK,KAAK,EAAE,OAAO,CAAO;IAE5B,gHAAgH;IACzG,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAK;IAEhD;;;;MAIE;IACK,OAAO,EAAE,QAAQ,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,EAAE,CAAK;IAExD,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAA;gBAEhB,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,iBAAiB;IAc/D;;;;;MAKE;IACK,iBAAiB,IAAI,OAAO,IAAI,CAAC,MAAM;IAmB9C;;;;;;MAME;IACK,kBAAkB,IAAI,OAAO,IAAI,CAAC,OAAO;IA6ChD,gFAAgF;IAChF,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO;IA2B5D,qGAAqG;IACxF,aAAa,CAAC,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;IA0CrG;;MAEE;IACK,MAAM,CAAC,eAAe,EAAE,IAAI;IAMnC;;;;MAIE;IACK,mBAAmB,CAAC,MAAM,GAAE,IAAW,GAAG,OAAO,CAAC,iBAAiB,EAAE,MAAM,GAAG,UAAU,CAAC,GAAG,SAAS;IAY/F,SAAS,CAAC,aAAa,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAIjE"}