wesl-packager 0.7.19 → 0.7.21

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/main.mjs CHANGED
@@ -148,16 +148,16 @@ async function loadPackageFields(pkgJsonPath) {
148
148
  }
149
149
  /** setup biome to use as a formatter */
150
150
  async function setupBiome() {
151
- const biome$1 = await Biome.create({ distribution: Distribution.NODE });
152
- const { projectKey } = biome$1.openProject();
153
- biome$1.applyConfiguration(projectKey, { formatter: {
151
+ const biome = await Biome.create({ distribution: Distribution.NODE });
152
+ const { projectKey } = biome.openProject();
153
+ biome.applyConfiguration(projectKey, { formatter: {
154
154
  enabled: true,
155
155
  indentStyle: "space",
156
156
  lineEnding: "lf",
157
157
  expand: "auto"
158
158
  } });
159
159
  return {
160
- biome: biome$1,
160
+ biome,
161
161
  projectKey
162
162
  };
163
163
  }
@@ -165,8 +165,8 @@ async function setupBiome() {
165
165
  //#endregion
166
166
  //#region src/PackagerCli.ts
167
167
  let cliArgs;
168
- async function packagerCli(rawArgs$1) {
169
- cliArgs = await parseArgs(rawArgs$1);
168
+ async function packagerCli(rawArgs) {
169
+ cliArgs = await parseArgs(rawArgs);
170
170
  await packageWgsl(cliArgs);
171
171
  }
172
172
  async function parseArgs(args) {
package/dist/main.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.mjs","names":["biome","rawArgs"],"sources":["../src/PackageWesl.ts","../src/PackagerCli.ts","../src/main.ts"],"sourcesContent":["import fs, { mkdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Biome, Distribution } from \"@biomejs/js-api\";\nimport { noSuffix, sanitizePackageName, type WeslBundle } from \"wesl\";\nimport { weslBundleDeclUrl } from \"wesl/bundle-decl\";\nimport { loadModules, parseDependencies, zip } from \"wesl-tooling\";\nimport type { CliArgs } from \"./PackagerCli.ts\";\n\nconst weslBundleDecl = await readFile(new URL(weslBundleDeclUrl), \"utf8\");\n\nconst { biome, projectKey: biomeKey } = await setupBiome();\n\n/** write weslBundle .js and .d.ts files for this shader */\nexport async function packageWgsl(args: CliArgs): Promise<void> {\n const { projectDir, outDir, multiBundle, baseDir, src } = args;\n const modules = await loadModules(projectDir, baseDir, src);\n const pkgJsonPath = path.join(projectDir, \"package.json\");\n const { name } = await loadPackageFields(pkgJsonPath);\n const edition = \"unstable_2025_1\";\n\n if (args.multiBundle) {\n await writeMultiBundle(modules, name, edition, projectDir, outDir);\n } else {\n const allDeps = parseDependencies(modules, projectDir);\n const sanitized = sanitizePackageName(name);\n const deps = filterSelfDeps(allDeps, sanitized);\n const bundle: WeslBundle = { name: sanitized, edition, modules };\n await writeJsBundle(bundle, deps, outDir);\n }\n await writeTypeScriptDts(outDir);\n if (args.updatePackageJson) {\n await updatePackageJson(projectDir, outDir, multiBundle);\n }\n}\n\n/** add an 'exports' entry to package.json for the wesl bundles */\nasync function updatePackageJson(\n projectDir: string,\n outDir: string,\n multiBundle: boolean,\n): Promise<void> {\n const pkgJsonPath = path.join(projectDir, \"package.json\");\n const pkgJsonString = await fs.readFile(pkgJsonPath, { encoding: \"utf8\" });\n const pkgJson = JSON.parse(pkgJsonString);\n const exports: Record<string, any> = {};\n\n const distDir = path.relative(projectDir, outDir);\n if (multiBundle) {\n exports[\"./*\"] = {\n types: `./${distDir}/weslBundle.d.ts`,\n import: `./${distDir}/*/weslBundle.js`,\n };\n } else {\n exports[\".\"] = {\n types: `./${distDir}/weslBundle.d.ts`,\n import: `./${distDir}/weslBundle.js`,\n };\n }\n\n const newPkgJson = insertExports(pkgJson, exports);\n const jsonString = JSON.stringify(newPkgJson, null, 2).concat(\"\\n\");\n await fs.writeFile(pkgJsonPath, jsonString);\n}\n\n/** insert the exports field into the package.json */\nfunction insertExports(pkgJson: any, exports: Record<string, any>): any {\n // insert the export entries into the existing package.json, after these fields (for a clean format)\n const exportsAfter = [\n \"name\",\n \"description\",\n \"version\",\n \"private\",\n \"author\",\n \"type\",\n \"bin\",\n \"files\",\n \"repository\",\n \"homepage\",\n \"scripts\",\n ];\n const entries = Object.entries(pkgJson);\n const index = entries.findLastIndex(([key]) => exportsAfter.includes(key));\n\n entries.splice(index + 1, 0, [\"exports\", exports]);\n return Object.fromEntries(entries);\n}\n\n/** create one bundle per source module */\nasync function writeMultiBundle(\n modules: Record<string, string>,\n name: string,\n edition: string,\n projectDir: string,\n outDir: string,\n): Promise<void> {\n const sanitized = sanitizePackageName(name);\n for (const [moduleName, moduleSrc] of Object.entries(modules)) {\n const oneModule = { [moduleName]: moduleSrc };\n const moduleBundle: WeslBundle = {\n name: sanitized,\n edition,\n modules: oneModule,\n };\n const dependencies = parseDependencies(oneModule, projectDir);\n const bundleDirRelative = noSuffix(moduleName);\n const bundleDir = path.join(outDir, bundleDirRelative);\n await writeJsBundle(moduleBundle, dependencies, bundleDir);\n }\n}\n\n/** Write a weslBundle.js containing the bundled shader sources */\nasync function writeJsBundle(\n weslBundle: WeslBundle,\n dependencies: string[],\n outDir: string,\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n\n const depNames = dependencies.map(dep => dep.replaceAll(\"/\", \"_\"));\n const depsWithNames = zip(dependencies, depNames);\n\n const imports = depsWithNames\n .map(([dep, depName]) => {\n return `import ${depName} from \"${dep}\";`;\n })\n .join(\"\\n\");\n const importsStr = imports ? `${imports}\\n` : \"\";\n\n const bundleString = bundleToJsString(weslBundle, depNames);\n\n const outString = `\n ${importsStr}\n export const weslBundle = ${bundleString}\n\n export default weslBundle;\n `;\n\n const outPath = path.join(outDir, \"weslBundle.js\");\n const formatted = biome.formatContent(biomeKey, outString, {\n filePath: \"b.js\",\n });\n await fs.writeFile(outPath, formatted.content);\n}\n\n/** Write weslBundle.d.ts containing the type definitions for a WeslBundle */\nasync function writeTypeScriptDts(outDir: string): Promise<void> {\n // TODO could we use /// <reference types=\"wesl\"> to get the type of WeslBundle?\n const constDecl = `\n export declare const weslBundle: WeslBundle;\n export default weslBundle;\n `;\n const declText = weslBundleDecl + constDecl;\n const formatted = biome.formatContent(biomeKey, declText, {\n filePath: \"t.d.ts\",\n });\n\n const outPath = path.join(outDir, \"weslBundle.d.ts\");\n await fs.writeFile(outPath, formatted.content);\n}\n\n/** @return the bundle plus dependencies as a JavaScript string */\nfunction bundleToJsString(bundle: WeslBundle, dependencies: string[]): string {\n const { name, edition, modules } = bundle;\n const depsObj = dependencies.length ? { dependencies: 99 } : {};\n const obj = { name, edition, modules, ...depsObj };\n const jsonString = JSON.stringify(obj, null, 2);\n if (dependencies.length) {\n const dependenciesStr = `: [${dependencies.join(\", \")}]`;\n const result = jsonString.replace(\": 99\", dependenciesStr);\n return result;\n } else {\n return jsonString;\n }\n}\n\n/** Filter out self-dependencies from the dependency list */\nfunction filterSelfDeps(deps: string[], packageName: string): string[] {\n return deps.filter(\n dep => dep !== packageName && !dep.startsWith(`${packageName}/`),\n );\n}\n\ninterface PkgFields {\n name: string;\n}\n\n/** parse and extract fields from package.json that we care about\n * (the name of the package) */\nasync function loadPackageFields(pkgJsonPath: string): Promise<PkgFields> {\n const pkgJsonString = await fs.readFile(pkgJsonPath, { encoding: \"utf8\" });\n const pkgJson = JSON.parse(pkgJsonString);\n const { name } = pkgJson;\n verifyField(\"name\", name);\n\n function verifyField(field: string, value: any): void {\n if (value === undefined) {\n console.error(`no '${field}' field found in \"${pkgJsonPath}\"`);\n throw new Error(\"package.json incomplete\");\n }\n }\n return { name };\n}\n\n/** setup biome to use as a formatter */\nasync function setupBiome(): Promise<{ biome: Biome; projectKey: number }> {\n const biome = await Biome.create({\n distribution: Distribution.NODE,\n });\n const { projectKey } = biome.openProject();\n biome.applyConfiguration(projectKey, {\n formatter: {\n enabled: true,\n indentStyle: \"space\",\n lineEnding: \"lf\",\n expand: \"auto\",\n },\n });\n return { biome, projectKey };\n}\n","import { versionFromPackageJson } from \"wesl-tooling\";\nimport yargs from \"yargs\";\nimport { packageWgsl } from \"./PackageWesl.ts\";\n\nexport type CliArgs = Awaited<ReturnType<typeof parseArgs>>;\nlet cliArgs: CliArgs;\n\nexport async function packagerCli(rawArgs: string[]): Promise<void> {\n cliArgs = await parseArgs(rawArgs);\n await packageWgsl(cliArgs);\n}\n\nasync function parseArgs(args: string[]) {\n const projectDir = new URL(\"..\", import.meta.url).href;\n const appVersion = await versionFromPackageJson(projectDir);\n return yargs(args)\n .command(\"$0\", \"create an npm package from WGSL/WESL files\")\n .version(appVersion)\n .option(\"src\", {\n type: \"string\",\n describe:\n \"WGSL/WESL files to bundle in the package (glob syntax, defaults to wesl.toml or shaders/**/*.w[eg]sl)\",\n })\n .option(\"rootDir\", {\n deprecated: true,\n type: \"string\",\n describe: \"use --baseDir instead\",\n })\n .option(\"baseDir\", {\n deprecated: true,\n type: \"string\",\n describe: \"root directory for shaders (defaults to wesl.toml or shaders)\",\n })\n .option(\"projectDir\", {\n type: \"string\",\n default: \".\",\n describe: \"directory containing package.json and wesl.toml\",\n })\n .option(\"multiBundle\", {\n type: \"boolean\",\n default: false,\n describe: \"make a shader bundle for each source file\",\n })\n .option(\"exportName\", {\n type: \"string\",\n default: \".\",\n describe:\n \"package.json export name for consolidated bundle (ignored for multiBundle)\",\n })\n .option(\"updatePackageJson\", {\n type: \"boolean\",\n default: false,\n describe: \"add 'exports' entries into package.json\",\n })\n .option(\"outDir\", {\n type: \"string\",\n default: \"dist\",\n describe: \"where to put bundled output files (relative to projectDir)\",\n })\n .help()\n .parse();\n}\n","#!/usr/bin/env node\nimport { exit } from \"node:process\";\nimport { hideBin } from \"yargs/helpers\";\nimport { packagerCli } from \"./PackagerCli.ts\";\n\nconst rawArgs = hideBin(process.argv);\n\nconst [major] = process.versions.node.split(\".\").map(Number);\nif (major < 22) {\n console.error(\n `Please upgrade node to version 22 or higher. (The current node version is ${process.version})`,\n );\n exit(1);\n}\n\npackagerCli(rawArgs).catch(e => {\n console.error(e);\n exit(1);\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"main.mjs","names":[],"sources":["../src/PackageWesl.ts","../src/PackagerCli.ts","../src/main.ts"],"sourcesContent":["import fs, { mkdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Biome, Distribution } from \"@biomejs/js-api\";\nimport { noSuffix, sanitizePackageName, type WeslBundle } from \"wesl\";\nimport { weslBundleDeclUrl } from \"wesl/bundle-decl\";\nimport { loadModules, parseDependencies, zip } from \"wesl-tooling\";\nimport type { CliArgs } from \"./PackagerCli.ts\";\n\nconst weslBundleDecl = await readFile(new URL(weslBundleDeclUrl), \"utf8\");\n\nconst { biome, projectKey: biomeKey } = await setupBiome();\n\n/** write weslBundle .js and .d.ts files for this shader */\nexport async function packageWgsl(args: CliArgs): Promise<void> {\n const { projectDir, outDir, multiBundle, baseDir, src } = args;\n const modules = await loadModules(projectDir, baseDir, src);\n const pkgJsonPath = path.join(projectDir, \"package.json\");\n const { name } = await loadPackageFields(pkgJsonPath);\n const edition = \"unstable_2025_1\";\n\n if (args.multiBundle) {\n await writeMultiBundle(modules, name, edition, projectDir, outDir);\n } else {\n const allDeps = parseDependencies(modules, projectDir);\n const sanitized = sanitizePackageName(name);\n const deps = filterSelfDeps(allDeps, sanitized);\n const bundle: WeslBundle = { name: sanitized, edition, modules };\n await writeJsBundle(bundle, deps, outDir);\n }\n await writeTypeScriptDts(outDir);\n if (args.updatePackageJson) {\n await updatePackageJson(projectDir, outDir, multiBundle);\n }\n}\n\n/** add an 'exports' entry to package.json for the wesl bundles */\nasync function updatePackageJson(\n projectDir: string,\n outDir: string,\n multiBundle: boolean,\n): Promise<void> {\n const pkgJsonPath = path.join(projectDir, \"package.json\");\n const pkgJsonString = await fs.readFile(pkgJsonPath, { encoding: \"utf8\" });\n const pkgJson = JSON.parse(pkgJsonString);\n const exports: Record<string, any> = {};\n\n const distDir = path.relative(projectDir, outDir);\n if (multiBundle) {\n exports[\"./*\"] = {\n types: `./${distDir}/weslBundle.d.ts`,\n import: `./${distDir}/*/weslBundle.js`,\n };\n } else {\n exports[\".\"] = {\n types: `./${distDir}/weslBundle.d.ts`,\n import: `./${distDir}/weslBundle.js`,\n };\n }\n\n const newPkgJson = insertExports(pkgJson, exports);\n const jsonString = JSON.stringify(newPkgJson, null, 2).concat(\"\\n\");\n await fs.writeFile(pkgJsonPath, jsonString);\n}\n\n/** insert the exports field into the package.json */\nfunction insertExports(pkgJson: any, exports: Record<string, any>): any {\n // insert the export entries into the existing package.json, after these fields (for a clean format)\n const exportsAfter = [\n \"name\",\n \"description\",\n \"version\",\n \"private\",\n \"author\",\n \"type\",\n \"bin\",\n \"files\",\n \"repository\",\n \"homepage\",\n \"scripts\",\n ];\n const entries = Object.entries(pkgJson);\n const index = entries.findLastIndex(([key]) => exportsAfter.includes(key));\n\n entries.splice(index + 1, 0, [\"exports\", exports]);\n return Object.fromEntries(entries);\n}\n\n/** create one bundle per source module */\nasync function writeMultiBundle(\n modules: Record<string, string>,\n name: string,\n edition: string,\n projectDir: string,\n outDir: string,\n): Promise<void> {\n const sanitized = sanitizePackageName(name);\n for (const [moduleName, moduleSrc] of Object.entries(modules)) {\n const oneModule = { [moduleName]: moduleSrc };\n const moduleBundle: WeslBundle = {\n name: sanitized,\n edition,\n modules: oneModule,\n };\n const dependencies = parseDependencies(oneModule, projectDir);\n const bundleDirRelative = noSuffix(moduleName);\n const bundleDir = path.join(outDir, bundleDirRelative);\n await writeJsBundle(moduleBundle, dependencies, bundleDir);\n }\n}\n\n/** Write a weslBundle.js containing the bundled shader sources */\nasync function writeJsBundle(\n weslBundle: WeslBundle,\n dependencies: string[],\n outDir: string,\n): Promise<void> {\n await mkdir(outDir, { recursive: true });\n\n const depNames = dependencies.map(dep => dep.replaceAll(\"/\", \"_\"));\n const depsWithNames = zip(dependencies, depNames);\n\n const imports = depsWithNames\n .map(([dep, depName]) => {\n return `import ${depName} from \"${dep}\";`;\n })\n .join(\"\\n\");\n const importsStr = imports ? `${imports}\\n` : \"\";\n\n const bundleString = bundleToJsString(weslBundle, depNames);\n\n const outString = `\n ${importsStr}\n export const weslBundle = ${bundleString}\n\n export default weslBundle;\n `;\n\n const outPath = path.join(outDir, \"weslBundle.js\");\n const formatted = biome.formatContent(biomeKey, outString, {\n filePath: \"b.js\",\n });\n await fs.writeFile(outPath, formatted.content);\n}\n\n/** Write weslBundle.d.ts containing the type definitions for a WeslBundle */\nasync function writeTypeScriptDts(outDir: string): Promise<void> {\n // TODO could we use /// <reference types=\"wesl\"> to get the type of WeslBundle?\n const constDecl = `\n export declare const weslBundle: WeslBundle;\n export default weslBundle;\n `;\n const declText = weslBundleDecl + constDecl;\n const formatted = biome.formatContent(biomeKey, declText, {\n filePath: \"t.d.ts\",\n });\n\n const outPath = path.join(outDir, \"weslBundle.d.ts\");\n await fs.writeFile(outPath, formatted.content);\n}\n\n/** @return the bundle plus dependencies as a JavaScript string */\nfunction bundleToJsString(bundle: WeslBundle, dependencies: string[]): string {\n const { name, edition, modules } = bundle;\n const depsObj = dependencies.length ? { dependencies: 99 } : {};\n const obj = { name, edition, modules, ...depsObj };\n const jsonString = JSON.stringify(obj, null, 2);\n if (dependencies.length) {\n const dependenciesStr = `: [${dependencies.join(\", \")}]`;\n const result = jsonString.replace(\": 99\", dependenciesStr);\n return result;\n } else {\n return jsonString;\n }\n}\n\n/** Filter out self-dependencies from the dependency list */\nfunction filterSelfDeps(deps: string[], packageName: string): string[] {\n return deps.filter(\n dep => dep !== packageName && !dep.startsWith(`${packageName}/`),\n );\n}\n\ninterface PkgFields {\n name: string;\n}\n\n/** parse and extract fields from package.json that we care about\n * (the name of the package) */\nasync function loadPackageFields(pkgJsonPath: string): Promise<PkgFields> {\n const pkgJsonString = await fs.readFile(pkgJsonPath, { encoding: \"utf8\" });\n const pkgJson = JSON.parse(pkgJsonString);\n const { name } = pkgJson;\n verifyField(\"name\", name);\n\n function verifyField(field: string, value: any): void {\n if (value === undefined) {\n console.error(`no '${field}' field found in \"${pkgJsonPath}\"`);\n throw new Error(\"package.json incomplete\");\n }\n }\n return { name };\n}\n\n/** setup biome to use as a formatter */\nasync function setupBiome(): Promise<{ biome: Biome; projectKey: number }> {\n const biome = await Biome.create({\n distribution: Distribution.NODE,\n });\n const { projectKey } = biome.openProject();\n biome.applyConfiguration(projectKey, {\n formatter: {\n enabled: true,\n indentStyle: \"space\",\n lineEnding: \"lf\",\n expand: \"auto\",\n },\n });\n return { biome, projectKey };\n}\n","import { versionFromPackageJson } from \"wesl-tooling\";\nimport yargs from \"yargs\";\nimport { packageWgsl } from \"./PackageWesl.ts\";\n\nexport type CliArgs = Awaited<ReturnType<typeof parseArgs>>;\nlet cliArgs: CliArgs;\n\nexport async function packagerCli(rawArgs: string[]): Promise<void> {\n cliArgs = await parseArgs(rawArgs);\n await packageWgsl(cliArgs);\n}\n\nasync function parseArgs(args: string[]) {\n const projectDir = new URL(\"..\", import.meta.url).href;\n const appVersion = await versionFromPackageJson(projectDir);\n return yargs(args)\n .command(\"$0\", \"create an npm package from WGSL/WESL files\")\n .version(appVersion)\n .option(\"src\", {\n type: \"string\",\n describe:\n \"WGSL/WESL files to bundle in the package (glob syntax, defaults to wesl.toml or shaders/**/*.w[eg]sl)\",\n })\n .option(\"rootDir\", {\n deprecated: true,\n type: \"string\",\n describe: \"use --baseDir instead\",\n })\n .option(\"baseDir\", {\n deprecated: true,\n type: \"string\",\n describe: \"root directory for shaders (defaults to wesl.toml or shaders)\",\n })\n .option(\"projectDir\", {\n type: \"string\",\n default: \".\",\n describe: \"directory containing package.json and wesl.toml\",\n })\n .option(\"multiBundle\", {\n type: \"boolean\",\n default: false,\n describe: \"make a shader bundle for each source file\",\n })\n .option(\"exportName\", {\n type: \"string\",\n default: \".\",\n describe:\n \"package.json export name for consolidated bundle (ignored for multiBundle)\",\n })\n .option(\"updatePackageJson\", {\n type: \"boolean\",\n default: false,\n describe: \"add 'exports' entries into package.json\",\n })\n .option(\"outDir\", {\n type: \"string\",\n default: \"dist\",\n describe: \"where to put bundled output files (relative to projectDir)\",\n })\n .help()\n .parse();\n}\n","#!/usr/bin/env node\nimport { exit } from \"node:process\";\nimport { hideBin } from \"yargs/helpers\";\nimport { packagerCli } from \"./PackagerCli.ts\";\n\nconst rawArgs = hideBin(process.argv);\n\nconst [major] = process.versions.node.split(\".\").map(Number);\nif (major < 22) {\n console.error(\n `Please upgrade node to version 22 or higher. (The current node version is ${process.version})`,\n );\n exit(1);\n}\n\npackagerCli(rawArgs).catch(e => {\n console.error(e);\n exit(1);\n});\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wesl-packager",
3
- "version": "0.7.19",
3
+ "version": "0.7.21",
4
4
  "type": "module",
5
5
  "bin": "dist/main.mjs",
6
6
  "files": [
@@ -13,8 +13,8 @@
13
13
  "@biomejs/js-api": "^1.0.0",
14
14
  "@biomejs/wasm-nodejs": "^2.0.6",
15
15
  "yargs": "^18.0.0",
16
- "wesl": "0.7.21",
17
- "wesl-tooling": "0.6.33"
16
+ "wesl": "0.7.23",
17
+ "wesl-tooling": "0.6.35"
18
18
  },
19
19
  "devDependencies": {
20
20
  "dependent_package": "x",
@@ -0,0 +1,20 @@
1
+ export interface WeslBundle {
2
+ /** npm package name sanitized to be a valid WESL identifier
3
+ * (@ removed, / ==> __, - ==> _) */
4
+ name: string;
5
+
6
+ /** WESL edition of the code e.g. unstable_2025_1 */
7
+ edition: string;
8
+
9
+ /** map of WESL/WGSL modules:
10
+ * keys are file paths, relative to package root (e.g. "./lib.wgsl")
11
+ * values are WESL/WGSL code strings
12
+ */
13
+ modules: Record<string, string>;
14
+
15
+ /** packages referenced by this package */
16
+ dependencies?: WeslBundle[];
17
+ }
18
+
19
+ export declare const weslBundle: WeslBundle;
20
+ export default weslBundle;
@@ -0,0 +1,10 @@
1
+ export const weslBundle = {
2
+ name: "test_wesl_package",
3
+ edition: "unstable_2025_1",
4
+ modules: {
5
+ "util.wgsl": "fn foo() {}",
6
+ "lib.wesl": "import package::util;\n",
7
+ },
8
+ };
9
+
10
+ export default weslBundle;