wesl-packager 0.6.33 → 0.6.43

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 (2) hide show
  1. package/bin/wesl-packager +132 -27
  2. package/package.json +2 -2
package/bin/wesl-packager CHANGED
@@ -9759,6 +9759,90 @@ function zip(as, bs) {
9759
9759
  return as.map((a, i) => [a, bs[i]]);
9760
9760
  }
9761
9761
 
9762
+ //#endregion
9763
+ //#region ../wesl-tooling/src/PackageNameUtils.ts
9764
+ /** Package name sanitization for WESL.
9765
+ *
9766
+ * Converts typical npm package names to WGSL-safe identifiers using double-underscore encoding.
9767
+ * NPM package names can contain `@`, `/`, and `-`, which are not allowed in WGSL identifiers.
9768
+ *
9769
+ * ## Encoding Scheme
9770
+ *
9771
+ * ```
9772
+ * @ ==> (remove)
9773
+ * / ==> __ (double underscore)
9774
+ * - ==> _ (single underscore)
9775
+ * ```
9776
+ *
9777
+ * ## Forward Mapping (npm ==> WGSL identifier)
9778
+ *
9779
+ * ```
9780
+ * my_package ==> my_package
9781
+ * random-wgsl ==> random_wgsl
9782
+ * @scope/my-pkg ==> scope__my_pkg
9783
+ * ```
9784
+ *
9785
+ * ## Reverse Mapping (WGSL identifier ==> npm package)
9786
+ *
9787
+ * ```
9788
+ * scope__my_pkg ==> try: @scope/my_pkg, @scope/my-pkg
9789
+ * random_wgsl ==> try: random_wgsl, random-wgsl
9790
+ * ```
9791
+ *
9792
+ * ## package.json Subpath Exports
9793
+ *
9794
+ * Subpaths don't create ambiguity because WeslBundle `name` field only contains package name:
9795
+ *
9796
+ * Scoped package:
9797
+ * ```
9798
+ * npm: @foo/shader-utils
9799
+ * weslBundle: { name: "foo__shader_utils", modules: {...} }
9800
+ * WESL: import foo__shader_utils::color::rgb2hsv
9801
+ * ```
9802
+ *
9803
+ * Unscoped package with subpath export:
9804
+ * ```
9805
+ * npm: "foo" (with exports: "./shader-utils": "./dist/...")
9806
+ * weslBundle: { name: "foo", modules: {...} } // NOT foo__shader_utils!
9807
+ * WESL: import foo::shader_utils::color::rgb2hsv // Different identifier!
9808
+ * ```
9809
+ *
9810
+ * The `__` only appears when the package name itself contains `/`, never for subpaths.
9811
+ */
9812
+ /** Convert npm package name to WGSL-safe identifier using double-underscore encoding. */
9813
+ function sanitizePackageName(npmName) {
9814
+ return npmName.replace(/^@/, "").replaceAll("/", "__").replaceAll("-", "_");
9815
+ }
9816
+ /** Generate npm package name variations from sanitized WESL identifier.
9817
+ *
9818
+ * Uses double-underscore encoding to distinguish scoped vs unscoped packages:
9819
+ * - Has __ → scoped package (try @scope/pkg variants)
9820
+ * - No __ → unscoped package (try pkg variants)
9821
+ *
9822
+ * Examples:
9823
+ * "lygia__shader_utils" → ["@lygia/shader_utils", "@lygia/shader-utils"]
9824
+ * "random_wgsl" → ["random_wgsl", "random-wgsl"]
9825
+ */
9826
+ function* npmNameVariations(sanitizedPath) {
9827
+ const [pkg, sub] = breakAt(sanitizedPath, "/");
9828
+ let pkgName = pkg;
9829
+ let scopePrefix = "";
9830
+ if (pkg.includes("__")) {
9831
+ const [scope, ...rest] = pkg.split("__");
9832
+ pkgName = rest.join("__");
9833
+ scopePrefix = `@${scope}/`;
9834
+ }
9835
+ yield `${scopePrefix}${pkgName}${sub}`;
9836
+ yield `${scopePrefix}${pkgName.replaceAll("_", "-")}${sub}`;
9837
+ }
9838
+ /** Break string at first occurrence of delimiter.
9839
+ * @returns [before, after] where after includes the delimiter */
9840
+ function breakAt(str, delimiter) {
9841
+ const index = str.indexOf(delimiter);
9842
+ if (index === -1) return [str, ""];
9843
+ return [str.slice(0, index), str.slice(index)];
9844
+ }
9845
+
9762
9846
  //#endregion
9763
9847
  //#region ../../node_modules/.pnpm/import-meta-resolve@4.1.0/node_modules/import-meta-resolve/lib/errors.js
9764
9848
  const own$1 = {}.hasOwnProperty;
@@ -10981,6 +11065,49 @@ function resolve(specifier, parent) {
10981
11065
  }
10982
11066
  }
10983
11067
 
11068
+ //#endregion
11069
+ //#region ../wesl-tooling/src/NpmResolver.ts
11070
+ /** Find longest resolvable npm subpath from WESL module path segments.
11071
+ *
11072
+ * A WESL statement containing a WESL module path like 'import foo__bar::baz::elem;' references
11073
+ * an npm package, an export within that package, a module within the WeslBundle,
11074
+ * and an element within the WESL module.
11075
+ * This function returns the npm package and export portion from the module path.
11076
+ * The return value is usable to dynamically import the corresponding weslBundle.js file.
11077
+ *
11078
+ * Translation from a WESL module path to an npm package path involves:
11079
+ * - Mapping WESL package names to their npm counterparts (e.g., 'foo__bar' -> '@foo/bar')
11080
+ * - Probing to find the longest valid export subpath within the package
11081
+ * - package.json allows export subpaths, so 'mypkg::gpu' could be 'mypkg/gpu' or just 'mypkg' in npm
11082
+ * - Probing to handle variations in package naming
11083
+ * - foo_bar could be foo-bar in npm
11084
+ *
11085
+ * Note that the resolution is based on package.json.
11086
+ * The resolved file itself may not exist yet. (e.g. dist/weslBundle.js may not have been built yet)
11087
+ *
11088
+ * @param mPath - Module path segments
11089
+ * @param importerURL - Base URL for resolution (e.g., 'file:///path/to/project/')
11090
+ * @returns Longest resolvable subpath (e.g., 'foo/bar/baz' or 'foo')
11091
+ */
11092
+ function npmResolveWESL(mPath, importerURL) {
11093
+ for (const subPath of exportSubpaths(mPath)) for (const npmPath of npmNameVariations(subPath)) if (tryResolve(npmPath, importerURL)) return npmPath;
11094
+ }
11095
+ /** Try Node.js module resolution.
11096
+ * @return undefined if unresolvable. */
11097
+ function tryResolve(path$2, importerURL) {
11098
+ try {
11099
+ return resolve(path$2, importerURL);
11100
+ } catch {
11101
+ return;
11102
+ }
11103
+ }
11104
+ /** Yield possible export subpaths from module path, longest first.
11105
+ * Drops the last segment (element name) and iterates down. */
11106
+ function* exportSubpaths(mPath) {
11107
+ const longest = mPath.length - 1;
11108
+ for (let i = longest; i >= 0; i--) yield mPath.slice(0, i).join("/");
11109
+ }
11110
+
10984
11111
  //#endregion
10985
11112
  //#region ../wesl-tooling/src/ParseDependencies.ts
10986
11113
  /**
@@ -11013,32 +11140,9 @@ function parseDependencies(weslSrc, projectDir) {
11013
11140
  const pkgRefs = unbound.filter((modulePath) => modulePath.length > 1 && modulePath[0] !== "constants");
11014
11141
  if (pkgRefs.length === 0) return [];
11015
11142
  const projectURL = projectDirURL(projectDir);
11016
- const deps = filterMap(pkgRefs, (mPath) => unboundToDependency(mPath, projectURL));
11143
+ const deps = filterMap(pkgRefs, (mPath) => npmResolveWESL(mPath, projectURL));
11017
11144
  return [...new Set(deps)];
11018
11145
  }
11019
- /** Find longest resolvable npm subpath from module path segments.
11020
- *
11021
- * @param mPath - Module path segments (e.g., ['foo', 'bar', 'baz', 'elem'])
11022
- * @param importerURL - Base URL for resolution (e.g., 'file:///path/to/project/')
11023
- * @returns Longest resolvable subpath (e.g., 'foo/bar/baz' or 'foo')
11024
- */
11025
- function unboundToDependency(mPath, importerURL) {
11026
- return [...exportSubpaths(mPath)].find((subPath) => tryResolve(subPath, importerURL));
11027
- }
11028
- /** Try Node.js module resolution; returns undefined if unresolvable. */
11029
- function tryResolve(path$2, importerURL) {
11030
- try {
11031
- return resolve(path$2, importerURL);
11032
- } catch {
11033
- return;
11034
- }
11035
- }
11036
- /** Yield possible export subpaths from module path, longest first.
11037
- * Drops the last segment (element name) and iterates down. */
11038
- function* exportSubpaths(mPath) {
11039
- const longest = mPath.length - 1;
11040
- for (let i = longest; i >= 0; i--) yield mPath.slice(0, i).join("/");
11041
- }
11042
11146
  /** Normalize project directory to file:// URL with trailing slash. */
11043
11147
  function projectDirURL(projectDir) {
11044
11148
  if (projectDir.startsWith("file://")) return projectDir.endsWith("/") ? projectDir : `${projectDir}/`;
@@ -11065,7 +11169,7 @@ async function versionFromPackageJson(projectDir) {
11065
11169
 
11066
11170
  //#endregion
11067
11171
  //#region \0raw:../wesl/src/WeslBundle.ts
11068
- var WeslBundle_default = "export interface WeslBundle {\n /** name of the package, e.g. random_wgsl */\n name: string;\n\n /** wesl edition of the code e.g. unstable_2025_1 */\n edition: string;\n\n /** map of wesl/wgsl modules:\n * keys are file paths, relative to package root (e.g. \"./lib.wgsl\")\n * values are wgsl/wesl code strings\n */\n modules: Record<string, string>;\n\n /** packages referenced by this package */\n dependencies?: WeslBundle[];\n}\n";
11172
+ var WeslBundle_default = "export interface WeslBundle {\n /** npm package name sanitized to be a valid WESL identifier\n * (@ removed, / ==> __, - ==> _) */\n name: string;\n\n /** WESL edition of the code e.g. unstable_2025_1 */\n edition: string;\n\n /** map of WESL/WGSL modules:\n * keys are file paths, relative to package root (e.g. \"./lib.wgsl\")\n * values are WESL/WGSL code strings\n */\n modules: Record<string, string>;\n\n /** packages referenced by this package */\n dependencies?: WeslBundle[];\n}\n";
11069
11173
 
11070
11174
  //#endregion
11071
11175
  //#region src/PackageWesl.ts
@@ -11080,7 +11184,7 @@ async function packageWgsl(args) {
11080
11184
  else {
11081
11185
  const deps = parseDependencies(modules, projectDir);
11082
11186
  await writeJsBundle({
11083
- name,
11187
+ name: sanitizePackageName(name),
11084
11188
  edition,
11085
11189
  modules
11086
11190
  }, deps, outDir);
@@ -11129,10 +11233,11 @@ function insertExports(pkgJson, exports) {
11129
11233
  }
11130
11234
  /** create one bundle per source module */
11131
11235
  async function writeMultiBundle(modules, name, edition, projectDir, outDir) {
11236
+ const sanitized = sanitizePackageName(name);
11132
11237
  for (const [moduleName, moduleSrc] of Object.entries(modules)) {
11133
11238
  const oneModule = { [moduleName]: moduleSrc };
11134
11239
  const moduleBundle = {
11135
- name,
11240
+ name: sanitized,
11136
11241
  edition,
11137
11242
  modules: oneModule
11138
11243
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wesl-packager",
3
- "version": "0.6.33",
3
+ "version": "0.6.43",
4
4
  "type": "module",
5
5
  "bin": "bin/wesl-packager",
6
6
  "files": [
@@ -11,7 +11,7 @@
11
11
  "@biomejs/js-api": "^1.0.0",
12
12
  "@biomejs/wasm-nodejs": "^2.0.6",
13
13
  "yargs": "^18.0.0",
14
- "wesl": "0.6.33"
14
+ "wesl": "0.6.43"
15
15
  },
16
16
  "devDependencies": {
17
17
  "dependent_package": "x",