@shopify/shop-minis-react 0.4.4 → 0.4.5

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.
@@ -1,5 +1,5 @@
1
- var e = { exports: {} };
1
+ var r = {};
2
2
  export {
3
- e as __module
3
+ r as __exports
4
4
  };
5
5
  //# sourceMappingURL=index4.js.map
@@ -1,6 +1,5 @@
1
- import { __require as r } from "../shop-minis-react/node_modules/.pnpm/@xmldom_xmldom@0.8.10/node_modules/@xmldom/xmldom/lib/index.js";
2
- var i = r();
1
+ var e = { exports: {} };
3
2
  export {
4
- i as l
3
+ e as __module
5
4
  };
6
5
  //# sourceMappingURL=index5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index5.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
1
+ {"version":3,"file":"index5.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -1,5 +1,6 @@
1
- var r = {};
1
+ import { __require as r } from "../shop-minis-react/node_modules/.pnpm/@xmldom_xmldom@0.8.10/node_modules/@xmldom/xmldom/lib/index.js";
2
+ var i = r();
2
3
  export {
3
- r as __exports
4
+ i as l
4
5
  };
5
6
  //# sourceMappingURL=index6.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index6.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"index6.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -1,4 +1,4 @@
1
- import { __module as q } from "../../../../../../../../_virtual/index4.js";
1
+ import { __module as q } from "../../../../../../../../_virtual/index5.js";
2
2
  import { __require as F } from "../../../../../global@4.4.0/node_modules/global/window.js";
3
3
  import { __require as N } from "../../../../../@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/extends.js";
4
4
  import { __require as J } from "../../../../../is-function@1.0.2/node_modules/is-function/index.js";
@@ -2,7 +2,7 @@ import L from "../../../../@videojs_vhs-utils@4.1.1/node_modules/@videojs/vhs-ut
2
2
  import T from "../../../../../../../_virtual/window.js";
3
3
  import { forEachMediaGroup as Z } from "../../../../@videojs_vhs-utils@4.1.1/node_modules/@videojs/vhs-utils/es/media-groups.js";
4
4
  import J from "../../../../@videojs_vhs-utils@4.1.1/node_modules/@videojs/vhs-utils/es/decode-b64-to-uint8-array.js";
5
- import { l as Q } from "../../../../../../../_virtual/index5.js";
5
+ import { l as Q } from "../../../../../../../_virtual/index6.js";
6
6
  /*! @name mpd-parser @version 1.3.1 @license Apache-2.0 */
7
7
  const w = (e) => !!e && typeof e == "object", E = (...e) => e.reduce((n, t) => (typeof t != "object" || Object.keys(t).forEach((r) => {
8
8
  Array.isArray(n[r]) && Array.isArray(t[r]) ? n[r] = n[r].concat(t[r]) : w(n[r]) && w(t[r]) ? n[r] = E(n[r], t[r]) : n[r] = t[r];
@@ -1,4 +1,4 @@
1
- import { __exports as i } from "../../../../../../_virtual/index6.js";
1
+ import { __exports as i } from "../../../../../../_virtual/index4.js";
2
2
  var c;
3
3
  function d() {
4
4
  if (c) return i;
package/eslint/config.cjs CHANGED
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  // Import the plugin directly so consumers don't need to install it separately
10
+ const compatPlugin = require('eslint-plugin-compat')
10
11
  const reactPlugin = require('eslint-plugin-react')
11
12
 
12
13
  const shopMinisPlugin = require('./index.cjs')
@@ -26,6 +27,7 @@ module.exports = {
26
27
  plugins: {
27
28
  'shop-minis': shopMinisPlugin,
28
29
  react: reactPlugin,
30
+ compat: compatPlugin,
29
31
  },
30
32
  rules: {
31
33
  // Console usage
@@ -35,7 +37,9 @@ module.exports = {
35
37
  'react/no-danger': 'error',
36
38
 
37
39
  // Shop Minis custom rules
40
+ 'shop-minis/no-env-without-fallback': 'error',
38
41
  'shop-minis/no-internal-imports': 'error',
42
+ 'shop-minis/no-secrets': 'error',
39
43
  'shop-minis/prefer-sdk-components': 'warn',
40
44
  'shop-minis/prefer-sdk-hooks': 'warn',
41
45
  'shop-minis/validate-manifest': 'error',
@@ -68,5 +72,6 @@ module.exports = {
68
72
  'WebAssembly is not supported in the Shop Minis environment. Consider using alternative JavaScript implementations.',
69
73
  },
70
74
  ],
75
+ 'compat/compat': 'error',
71
76
  },
72
77
  }
package/eslint/index.cjs CHANGED
@@ -4,14 +4,18 @@
4
4
  * @fileoverview Custom ESLint rules for Shop Minis React SDK
5
5
  */
6
6
 
7
+ const noEnvWithoutFallback = require('./rules/no-env-without-fallback.cjs')
7
8
  const noInternalImports = require('./rules/no-internal-imports.cjs')
9
+ const noSecrets = require('./rules/no-secrets.cjs')
8
10
  const preferSdkComponents = require('./rules/prefer-sdk-components.cjs')
9
11
  const preferSdkHooks = require('./rules/prefer-sdk-hooks.cjs')
10
12
  const validateManifest = require('./rules/validate-manifest.cjs')
11
13
 
12
14
  module.exports = {
13
15
  rules: {
16
+ 'no-env-without-fallback': noEnvWithoutFallback,
14
17
  'no-internal-imports': noInternalImports,
18
+ 'no-secrets': noSecrets,
15
19
  'prefer-sdk-components': preferSdkComponents,
16
20
  'prefer-sdk-hooks': preferSdkHooks,
17
21
  'validate-manifest': validateManifest,
@@ -0,0 +1,148 @@
1
+ /**
2
+ * ESLint rule to require fallbacks for environment variables
3
+ * @fileoverview Disallow using import.meta.env without a fallback value
4
+ *
5
+ * In Shop Minis, environment variables work in development but are not available
6
+ * in production. This rule ensures developers always provide fallback values.
7
+ */
8
+
9
+ module.exports = {
10
+ meta: {
11
+ type: 'problem',
12
+ docs: {
13
+ description:
14
+ 'Require fallback values when using import.meta.env variables',
15
+ category: 'Best Practices',
16
+ recommended: true,
17
+ },
18
+ messages: {
19
+ noFallback:
20
+ 'Environment variable "{{ name }}" must have a fallback value. Environment variables are only available in development. Use || or ?? to provide a production fallback.',
21
+ },
22
+ schema: [],
23
+ },
24
+
25
+ create(context) {
26
+ return {
27
+ MemberExpression(node) {
28
+ // Check if this is import.meta.env.SOMETHING
29
+ if (!isImportMetaEnv(node)) {
30
+ return
31
+ }
32
+
33
+ // Get the env variable name for the error message
34
+ const envName = node.property.name || node.property.value || 'unknown'
35
+
36
+ // Check if it has a fallback (|| or ??)
37
+ if (hasFallback(node)) {
38
+ return
39
+ }
40
+
41
+ context.report({
42
+ node,
43
+ messageId: 'noFallback',
44
+ data: {
45
+ name: `import.meta.env.${envName}`,
46
+ },
47
+ })
48
+ },
49
+ }
50
+ },
51
+ }
52
+
53
+ /**
54
+ * Check if node is import.meta.env.SOMETHING
55
+ */
56
+ function isImportMetaEnv(node) {
57
+ // Must be a member expression with a property
58
+ if (node.type !== 'MemberExpression' || !node.property) {
59
+ return false
60
+ }
61
+
62
+ // The object should be import.meta.env
63
+ const obj = node.object
64
+ if (
65
+ obj.type === 'MemberExpression' &&
66
+ obj.object.type === 'MetaProperty' &&
67
+ obj.object.meta.name === 'import' &&
68
+ obj.object.property.name === 'meta' &&
69
+ obj.property.name === 'env'
70
+ ) {
71
+ return true
72
+ }
73
+
74
+ return false
75
+ }
76
+
77
+ /**
78
+ * Check if the node has a fallback via || or ?? operator
79
+ */
80
+ function hasFallback(node) {
81
+ let current = node.parent
82
+
83
+ // Walk up the tree to find if we're in a logical expression with fallback
84
+ while (current) {
85
+ // Direct fallback: import.meta.env.FOO || 'default' or import.meta.env.FOO ?? 'default'
86
+ // Also handles chains: import.meta.env.A || import.meta.env.B || 'default'
87
+ if (
88
+ current.type === 'LogicalExpression' &&
89
+ (current.operator === '||' || current.operator === '??')
90
+ ) {
91
+ // Check if this logical expression chain eventually has a non-env fallback
92
+ if (logicalChainHasFallback(current)) {
93
+ return true
94
+ }
95
+ }
96
+
97
+ // Conditional expression: import.meta.env.FOO ? import.meta.env.FOO : 'default'
98
+ if (current.type === 'ConditionalExpression') {
99
+ // If used in the test part, it has a fallback (the alternate)
100
+ if (node === current.test) {
101
+ return true
102
+ }
103
+ // If used in the consequent and test is an env var check, it's valid
104
+ if (node === current.consequent && isImportMetaEnv(current.test)) {
105
+ return true
106
+ }
107
+ }
108
+
109
+ current = current.parent
110
+ }
111
+
112
+ return false
113
+ }
114
+
115
+ /**
116
+ * Check if a logical expression chain has a fallback at the end
117
+ * For: A || B || C, we walk up to find the topmost || or ?? and check its right side
118
+ */
119
+ function logicalChainHasFallback(node) {
120
+ // Walk up to the topmost logical expression in the chain
121
+ let topmost = node
122
+ while (
123
+ topmost.parent &&
124
+ topmost.parent.type === 'LogicalExpression' &&
125
+ (topmost.parent.operator === '||' || topmost.parent.operator === '??') &&
126
+ topmost.parent.left === topmost
127
+ ) {
128
+ topmost = topmost.parent
129
+ }
130
+
131
+ // The rightmost value in the chain is the fallback
132
+ // Check that it's not also an import.meta.env (that would mean no real fallback)
133
+ const rightmost = getRightmostValue(topmost)
134
+ return !isImportMetaEnv(rightmost)
135
+ }
136
+
137
+ /**
138
+ * Get the rightmost value in a logical expression chain
139
+ */
140
+ function getRightmostValue(node) {
141
+ if (
142
+ node.type === 'LogicalExpression' &&
143
+ (node.operator === '||' || node.operator === '??')
144
+ ) {
145
+ return getRightmostValue(node.right)
146
+ }
147
+ return node
148
+ }
@@ -0,0 +1,27 @@
1
+ /* eslint-disable import/extensions */
2
+ /**
3
+ * ESLint rule wrapper for eslint-plugin-no-secrets with custom messages
4
+ * @fileoverview Customized messages for detecting hardcoded secrets in Shop Minis
5
+ */
6
+
7
+ const noSecretsPlugin = require('eslint-plugin-no-secrets')
8
+
9
+ // Get the original rule
10
+ const originalRule = noSecretsPlugin.rules['no-secrets']
11
+
12
+ module.exports = {
13
+ meta: {
14
+ ...originalRule.meta,
15
+ messages: {
16
+ HIGH_ENTROPY:
17
+ 'This string may be a hardcoded credential, which should never be committed. Please check the Shop Minis documentation learn how to handle these cases. You can disable this rule if it is not a credential.',
18
+ PATTERN_MATCH:
19
+ 'Potential {{ name }} detected. Hardcoded credentials should never be committed. Please check the Shop Minis documentation learn how to handle these cases. You can disable this rule if it is not a credential.',
20
+ },
21
+ },
22
+ create(context) {
23
+ // Create the original rule's visitor
24
+ const originalVisitor = originalRule.create(context)
25
+ return originalVisitor
26
+ },
27
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shopify/shop-minis-react",
3
3
  "license": "SEE LICENSE IN LICENSE.txt",
4
- "version": "0.4.4",
4
+ "version": "0.4.5",
5
5
  "sideEffects": false,
6
6
  "type": "module",
7
7
  "engines": {
@@ -50,14 +50,16 @@
50
50
  "@types/lodash": "4.17.20",
51
51
  "@types/react-window": "1.8.8",
52
52
  "@types/url-parse": "1.4.9",
53
- "@typescript-eslint/parser": "^7.0.0",
53
+ "@typescript-eslint/parser": "7.0.0",
54
54
  "@vitejs/plugin-react": "4.5.1",
55
55
  "class-variance-authority": "0.7.1",
56
56
  "clsx": "2.1.1",
57
57
  "color": "4.2.3",
58
58
  "embla-carousel-react": "8.6.0",
59
- "eslint": "^8.57.0",
60
- "eslint-plugin-react": "^7.37.5",
59
+ "eslint": "8.57.0",
60
+ "eslint-plugin-compat": "6.0.2",
61
+ "eslint-plugin-no-secrets": "2.2.1",
62
+ "eslint-plugin-react": "7.37.5",
61
63
  "js-base64": "3.7.7",
62
64
  "lodash": "4.17.21",
63
65
  "lucide-react": "0.513.0",