@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.
- package/dist/_virtual/index4.js +2 -2
- package/dist/_virtual/index5.js +2 -3
- package/dist/_virtual/index5.js.map +1 -1
- package/dist/_virtual/index6.js +3 -2
- package/dist/_virtual/index6.js.map +1 -1
- package/dist/shop-minis-react/node_modules/.pnpm/@videojs_xhr@2.7.0/node_modules/@videojs/xhr/lib/index.js +1 -1
- package/dist/shop-minis-react/node_modules/.pnpm/mpd-parser@1.3.1/node_modules/mpd-parser/dist/mpd-parser.es.js +1 -1
- package/dist/shop-minis-react/node_modules/.pnpm/querystringify@2.2.0/node_modules/querystringify/index.js +1 -1
- package/eslint/config.cjs +5 -0
- package/eslint/index.cjs +4 -0
- package/eslint/rules/no-env-without-fallback.cjs +148 -0
- package/eslint/rules/no-secrets.cjs +27 -0
- package/package.json +6 -4
package/dist/_virtual/index4.js
CHANGED
package/dist/_virtual/index5.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index5.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index5.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
package/dist/_virtual/index6.js
CHANGED
|
@@ -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/
|
|
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/
|
|
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];
|
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
|
+
"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": "
|
|
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": "
|
|
60
|
-
"eslint-plugin-
|
|
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",
|