@wix/origami-site 0.1.32 → 0.1.33

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/origami-site",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "description": "Runs an exported Wix origami site: file-based routing, Wix dynamic pages, popups and build checks. Use with @wix/origami-site-astro or @wix/origami-site-express.",
5
5
  "type": "module",
6
6
  "files": [
@@ -93,5 +93,5 @@
93
93
  "optional": true
94
94
  }
95
95
  },
96
- "falconPackageHash": "521196d96b89520b98a02f6d8f882dd74e393b1728ef2943a0dc2e7a"
96
+ "falconPackageHash": "f699993cd6dc0b08545a5b50b04d801776a7b77e10c81bd7ac6cd6e7"
97
97
  }
@@ -2,6 +2,7 @@ import { transforms } from './transforms.js'
2
2
  import { globalImports } from './globalImports.js'
3
3
  import { pageList } from './pageList.js'
4
4
  import { sharedPackages } from './sharedPackages.js'
5
+ import { wrapperAliases } from './wrapperAliases.js'
5
6
 
6
7
  /** @param {import('./index.js').OrigamiVitePluginsOptions} options
7
8
  * @returns {import('vite').Plugin[]} */
@@ -11,5 +12,6 @@ export function origamiVitePlugins({ root, siteTree }) {
11
12
  pageList(siteTree),
12
13
  ...transforms({ root }),
13
14
  sharedPackages(),
15
+ wrapperAliases(root),
14
16
  ]
15
17
  }
@@ -0,0 +1,79 @@
1
+ // Raw components import each other by module specifier, such as a store component importing its hook from
2
+ // `@wix/stores/product-list-context-provider`. The Wix viewer resolves these with an import map. Here each wrapper
3
+ // package (`@origami-wrappers/*`) lists them under `origami.aliases`, and they become `resolve.alias` entries, which
4
+ // Vite also applies while pre-bundling dependencies, where these imports sit.
5
+
6
+ import { existsSync, readFileSync } from 'node:fs'
7
+ import { createRequire } from 'node:module'
8
+ import { resolve } from 'node:path'
9
+
10
+ const WRAPPERS_SCOPE = '@origami-wrappers/'
11
+
12
+ /** @param {string} text */
13
+ const escapeRegExp = text => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
14
+
15
+ /** @param {string} path */
16
+ const readJson = path => JSON.parse(readFileSync(path, 'utf8'))
17
+
18
+ /**
19
+ * A wrapper package's `package.json`, or undefined for one that has nothing to read: one from before the aliases
20
+ * does not export its `package.json`, and one not installed yet has none.
21
+ *
22
+ * @param {NodeJS.Require} require
23
+ * @param {string} name
24
+ */
25
+ const readWrapperPackageJson = (require, name) => {
26
+ try {
27
+ return readJson(require.resolve(`${name}/package.json`))
28
+ } catch (error) {
29
+ const { code } = /** @type {NodeJS.ErrnoException} */ (error)
30
+ if (code === 'ERR_PACKAGE_PATH_NOT_EXPORTED' || code === 'MODULE_NOT_FOUND') return undefined
31
+ throw error
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Every alias the site's wrapper packages declare. A `./` target is in the package itself, which the site installs
37
+ * under a name of its own, so the name goes in front; any other target is an npm import, kept as is. Each alias
38
+ * matches the whole import, not longer paths that start with it. Two packages pointing one specifier at different
39
+ * modules fail, rather than leave it to the order of the dependencies.
40
+ *
41
+ * @param {string} root the site app folder, whose `package.json` lists the wrapper packages
42
+ * @returns {{ find: RegExp, replacement: string }[]}
43
+ */
44
+ export const collectWrapperAliases = root => {
45
+ const packageJsonPath = resolve(root, 'package.json')
46
+ if (!existsSync(packageJsonPath)) return []
47
+ const require = createRequire(packageJsonPath)
48
+ const wrapperNames = Object.keys(readJson(packageJsonPath).dependencies ?? {}).filter(name =>
49
+ name.startsWith(WRAPPERS_SCOPE)
50
+ )
51
+
52
+ /** @type {Map<string, { name: string, replacement: string }>} */
53
+ const claims = new Map()
54
+ for (const name of wrapperNames) {
55
+ /** @type {Record<string, string>} */
56
+ const aliases = readWrapperPackageJson(require, name)?.origami?.aliases ?? {}
57
+ for (const [specifier, target] of Object.entries(aliases)) {
58
+ const replacement = target.startsWith('./') ? `${name}/${target.slice(2)}` : target
59
+ const claim = claims.get(specifier)
60
+ if (claim && claim.replacement !== replacement)
61
+ throw new Error(
62
+ `${claim.name} and ${name} both alias ${specifier}, to ${claim.replacement} and ${replacement}`
63
+ )
64
+ claims.set(specifier, { name, replacement })
65
+ }
66
+ }
67
+
68
+ return [...claims].map(([specifier, { replacement }]) => ({
69
+ find: new RegExp(`^${escapeRegExp(specifier)}$`),
70
+ replacement,
71
+ }))
72
+ }
73
+
74
+ /** @param {string} root
75
+ * @returns {import('vite').Plugin} */
76
+ export const wrapperAliases = root => ({
77
+ name: 'origami:wrapper-aliases',
78
+ config: () => ({ resolve: { alias: collectWrapperAliases(root) } }),
79
+ })