@shopify/create-app 4.9.2 → 4.9.4
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/{analytics-TUZG7DA4.js → analytics-7RLRFLCQ.js} +17 -17
- package/dist/{analytics-6EJD33WP.js → analytics-WZ4U5RJZ.js} +17 -17
- package/dist/{chunk-BJRUKXTH.js → chunk-52LPDF46.js} +5 -5
- package/dist/{chunk-IY53IJS3.js → chunk-53A2QBFH.js} +16 -16
- package/dist/{chunk-VDUAROBQ.js → chunk-57VCTLOQ.js} +3 -3
- package/dist/{chunk-KCVRVXZY.js → chunk-6BEAY6DV.js} +6 -6
- package/dist/{chunk-U5KA5YG3.js → chunk-75IKCZVA.js} +7 -7
- package/dist/{chunk-GR2RHEDU.js → chunk-7EY7VZVX.js} +2 -2
- package/dist/{chunk-4L6UUTTJ.js → chunk-ATS65VTD.js} +3 -3
- package/dist/{chunk-CK3T27VW.js → chunk-C3P3BBJI.js} +2 -2
- package/dist/{chunk-SHCNJ47P.js → chunk-DXHBESFY.js} +3 -3
- package/dist/{chunk-TCPQPFTE.js → chunk-IG7O7GU7.js} +3 -3
- package/dist/{chunk-MB6QQB5L.js → chunk-IIDLK3B2.js} +2 -2
- package/dist/{chunk-CVBQ5S5E.js → chunk-IYZRNCTE.js} +10 -10
- package/dist/{chunk-AKE2R5YA.js → chunk-L6MEGCFP.js} +2 -2
- package/dist/{chunk-PYUSHB4W.js → chunk-MNUDC2IF.js} +2 -2
- package/dist/{chunk-PI6OTTFS.js → chunk-NN45GPHA.js} +4 -4
- package/dist/{chunk-DBII5OBE.js → chunk-PUN2NAT5.js} +16 -21
- package/dist/{chunk-JLQYDEOX.js → chunk-QLLL4VIM.js} +7 -7
- package/dist/{chunk-YMDHYX2O.js → chunk-RRQPXOTA.js} +2 -2
- package/dist/{chunk-UHTO6LKY.js → chunk-TJDRI2KO.js} +6 -6
- package/dist/{chunk-R2AIQR2X.js → chunk-TLGD6UXP.js} +19 -19
- package/dist/{chunk-UU2BFFYI.js → chunk-VDSENONW.js} +7 -7
- package/dist/{command-json-schema-JURPJVZ3.js → command-json-schema-LA7ZVL4O.js} +10 -10
- package/dist/{conf-store-WTXS6AY6.js → conf-store-NRFTTQPX.js} +7 -7
- package/dist/{custom-oclif-loader-M5AZS4TE.js → custom-oclif-loader-WGQ253VO.js} +8 -8
- package/dist/{deprecations-HATTH3TU.js → deprecations-WHQU454D.js} +13 -13
- package/dist/{environment-OJNKZ7ML.js → environment-5XBFWY2A.js} +4 -4
- package/dist/environments-II3QYMU3.js +32 -0
- package/dist/{error-handler-T5DK23DW.js → error-handler-MENPWWOI.js} +17 -17
- package/dist/{fs-YBH7ZBPM.js → fs-SDWO6JOY.js} +5 -5
- package/dist/hooks/postrun.js +6 -6
- package/dist/hooks/prerun.js +6 -6
- package/dist/index.js +256 -139
- package/dist/{is-global-RSJKDZBD.js → is-global-JQIYTGBN.js} +5 -5
- package/dist/{json-error-EHXN4G6A.js → json-error-XFVCG7UX.js} +8 -8
- package/dist/{local-XHZE5NPW.js → local-G2BSQFFH.js} +4 -4
- package/dist/{metadata-3AKOV7W4.js → metadata-XWHS3SDJ.js} +5 -5
- package/dist/{node-package-manager-IRHXUBQ2.js → node-package-manager-QET5FYFY.js} +15 -15
- package/dist/{notifications-system-LJSYFBE6.js → notifications-system-TAHUXXGQ.js} +18 -18
- package/dist/{os-TMXMOEZT.js → os-JHHBXO2N.js} +6 -6
- package/dist/{output-62KIUOOP.js → output-2B3LJAUM.js} +5 -5
- package/dist/{path-2KZ7FSGN.js → path-RDYZ7Q5T.js} +2 -2
- package/dist/{system-JRCUPDF5.js → system-EHWOZQCE.js} +13 -13
- package/dist/{ui-XXDBKKJS.js → ui-ZXHKYLCS.js} +13 -13
- package/dist/{upgrade-J6F3T32S.js → upgrade-H2IEKPCC.js} +19 -19
- package/dist/{version-NC64OPAP.js → version-IJ2X574N.js} +2 -2
- package/dist/{version-VZYNTIET.js → version-QY5L7H5O.js} +14 -14
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
- package/dist/environments-P6W4YQBT.js +0 -32
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
decodeToml,
|
|
5
5
|
loadEnvironment,
|
|
6
6
|
require_toml_patch
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VDSENONW.js";
|
|
8
8
|
import {
|
|
9
9
|
require_normalize_path
|
|
10
10
|
} from "./chunk-RIQNGBMO.js";
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import {
|
|
16
16
|
setCurrentCommandId,
|
|
17
17
|
showNotificationsIfNeeded
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-IYZRNCTE.js";
|
|
19
19
|
import {
|
|
20
20
|
ClientError,
|
|
21
21
|
DevServerCore,
|
|
@@ -81,7 +81,7 @@ import {
|
|
|
81
81
|
setPathValue,
|
|
82
82
|
shopifyFetch,
|
|
83
83
|
storeAdminUrl
|
|
84
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-TLGD6UXP.js";
|
|
85
85
|
import {
|
|
86
86
|
setNextDeprecationDate
|
|
87
87
|
} from "./chunk-MSED5ZFM.js";
|
|
@@ -103,26 +103,26 @@ import {
|
|
|
103
103
|
usesWorkspaces,
|
|
104
104
|
versionSatisfies,
|
|
105
105
|
writePackageJSON
|
|
106
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-75IKCZVA.js";
|
|
107
107
|
import {
|
|
108
108
|
import_websocket_server
|
|
109
109
|
} from "./chunk-LDYT4FTV.js";
|
|
110
110
|
import "./chunk-FKZ3NFHZ.js";
|
|
111
111
|
import {
|
|
112
112
|
CLI_KIT_VERSION
|
|
113
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-MNUDC2IF.js";
|
|
114
114
|
import "./chunk-G53O4PDO.js";
|
|
115
115
|
import {
|
|
116
116
|
LocalStorage,
|
|
117
117
|
require_ajv,
|
|
118
118
|
runAtMinimumInterval,
|
|
119
119
|
serviceEnvironment
|
|
120
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-TJDRI2KO.js";
|
|
121
121
|
import {
|
|
122
122
|
globalCLIVersion,
|
|
123
123
|
isPreReleaseVersion,
|
|
124
124
|
localCLIVersion
|
|
125
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-IIDLK3B2.js";
|
|
126
126
|
import {
|
|
127
127
|
AbortController as AbortController2,
|
|
128
128
|
Alert,
|
|
@@ -170,10 +170,10 @@ import {
|
|
|
170
170
|
use_input_default,
|
|
171
171
|
use_stdin_default,
|
|
172
172
|
use_stdout_default
|
|
173
|
-
} from "./chunk-
|
|
173
|
+
} from "./chunk-PUN2NAT5.js";
|
|
174
174
|
import {
|
|
175
175
|
runWithCommandEventsForCommand
|
|
176
|
-
} from "./chunk-
|
|
176
|
+
} from "./chunk-52LPDF46.js";
|
|
177
177
|
import {
|
|
178
178
|
execa,
|
|
179
179
|
isStream,
|
|
@@ -186,14 +186,14 @@ import {
|
|
|
186
186
|
require_signal_exit,
|
|
187
187
|
stripFinalNewline,
|
|
188
188
|
username
|
|
189
|
-
} from "./chunk-
|
|
189
|
+
} from "./chunk-RRQPXOTA.js";
|
|
190
190
|
import "./chunk-JGGOQOPO.js";
|
|
191
191
|
import {
|
|
192
192
|
addPublicMetadata,
|
|
193
193
|
addSensitiveMetadata,
|
|
194
194
|
createRuntimeMetadataContainer,
|
|
195
195
|
runWithTimer
|
|
196
|
-
} from "./chunk-
|
|
196
|
+
} from "./chunk-ATS65VTD.js";
|
|
197
197
|
import {
|
|
198
198
|
fileHash,
|
|
199
199
|
getAppAutomationToken,
|
|
@@ -203,23 +203,23 @@ import {
|
|
|
203
203
|
nonRandomUUID,
|
|
204
204
|
randomUUID,
|
|
205
205
|
sha256
|
|
206
|
-
} from "./chunk-
|
|
206
|
+
} from "./chunk-DXHBESFY.js";
|
|
207
207
|
import {
|
|
208
208
|
defineJsonOutputSchema
|
|
209
|
-
} from "./chunk-
|
|
209
|
+
} from "./chunk-L6MEGCFP.js";
|
|
210
210
|
import "./chunk-CM6ALOD7.js";
|
|
211
211
|
import {
|
|
212
212
|
AbortError,
|
|
213
213
|
AbortSilentError,
|
|
214
214
|
BugError,
|
|
215
215
|
CancelExecution
|
|
216
|
-
} from "./chunk-
|
|
216
|
+
} from "./chunk-6BEAY6DV.js";
|
|
217
217
|
import {
|
|
218
218
|
waitForPostRunHookAndExit
|
|
219
|
-
} from "./chunk-
|
|
219
|
+
} from "./chunk-53A2QBFH.js";
|
|
220
220
|
import {
|
|
221
221
|
treeKill
|
|
222
|
-
} from "./chunk-
|
|
222
|
+
} from "./chunk-7EY7VZVX.js";
|
|
223
223
|
import {
|
|
224
224
|
appendFile,
|
|
225
225
|
asHumanFriendlyArray,
|
|
@@ -316,7 +316,7 @@ import {
|
|
|
316
316
|
unstyled,
|
|
317
317
|
writeFile,
|
|
318
318
|
writeFileSync
|
|
319
|
-
} from "./chunk-
|
|
319
|
+
} from "./chunk-QLLL4VIM.js";
|
|
320
320
|
import {
|
|
321
321
|
codespacePortForwardingDomain,
|
|
322
322
|
codespaceURL,
|
|
@@ -330,11 +330,11 @@ import {
|
|
|
330
330
|
isUnitTest,
|
|
331
331
|
isVerbose,
|
|
332
332
|
noInputFlag
|
|
333
|
-
} from "./chunk-
|
|
333
|
+
} from "./chunk-NN45GPHA.js";
|
|
334
334
|
import {
|
|
335
335
|
environmentVariables,
|
|
336
336
|
themeKitAccessDomain
|
|
337
|
-
} from "./chunk-
|
|
337
|
+
} from "./chunk-C3P3BBJI.js";
|
|
338
338
|
import {
|
|
339
339
|
isTruthy
|
|
340
340
|
} from "./chunk-HNIAZN6U.js";
|
|
@@ -344,7 +344,9 @@ import {
|
|
|
344
344
|
} from "./chunk-EJEHENXO.js";
|
|
345
345
|
import "./chunk-23UTCSPZ.js";
|
|
346
346
|
import "./chunk-LBXDGVFS.js";
|
|
347
|
-
import
|
|
347
|
+
import {
|
|
348
|
+
require_semver
|
|
349
|
+
} from "./chunk-OQ3KXXGH.js";
|
|
348
350
|
import "./chunk-D6NYWNY2.js";
|
|
349
351
|
import {
|
|
350
352
|
basename,
|
|
@@ -362,7 +364,7 @@ import {
|
|
|
362
364
|
resolvePath,
|
|
363
365
|
sanitizeRelativePath,
|
|
364
366
|
sniffForJson
|
|
365
|
-
} from "./chunk-
|
|
367
|
+
} from "./chunk-57VCTLOQ.js";
|
|
366
368
|
import "./chunk-UFLX7QDP.js";
|
|
367
369
|
import "./chunk-SI4LHZYW.js";
|
|
368
370
|
import {
|
|
@@ -30653,7 +30655,7 @@ var require_lodash = __commonJS({
|
|
|
30653
30655
|
function isWeakSet(value) {
|
|
30654
30656
|
return isObjectLike(value) && baseGetTag(value) == weakSetTag;
|
|
30655
30657
|
}
|
|
30656
|
-
var
|
|
30658
|
+
var lt2 = createRelationalOperation(baseLt), lte = createRelationalOperation(function(value, other) {
|
|
30657
30659
|
return value <= other;
|
|
30658
30660
|
});
|
|
30659
30661
|
function toArray(value) {
|
|
@@ -31226,7 +31228,7 @@ function print() { __p += __j.call(arguments, '') }
|
|
|
31226
31228
|
function sumBy(array, iteratee2) {
|
|
31227
31229
|
return array && array.length ? baseSum(array, getIteratee(iteratee2, 2)) : 0;
|
|
31228
31230
|
}
|
|
31229
|
-
return lodash.after = after, lodash.ary = ary, lodash.assign = assign, lodash.assignIn = assignIn, lodash.assignInWith = assignInWith, lodash.assignWith = assignWith, lodash.at = at, lodash.before = before, lodash.bind = bind, lodash.bindAll = bindAll, lodash.bindKey = bindKey, lodash.castArray = castArray, lodash.chain = chain, lodash.chunk = chunk, lodash.compact = compact2, lodash.concat = concat, lodash.cond = cond, lodash.conforms = conforms, lodash.constant = constant, lodash.countBy = countBy, lodash.create = create, lodash.curry = curry, lodash.curryRight = curryRight, lodash.debounce = debounce2, lodash.defaults = defaults, lodash.defaultsDeep = defaultsDeep, lodash.defer = defer2, lodash.delay = delay2, lodash.difference = difference2, lodash.differenceBy = differenceBy, lodash.differenceWith = differenceWith, lodash.drop = drop, lodash.dropRight = dropRight, lodash.dropRightWhile = dropRightWhile, lodash.dropWhile = dropWhile, lodash.fill = fill, lodash.filter = filter, lodash.flatMap = flatMap, lodash.flatMapDeep = flatMapDeep, lodash.flatMapDepth = flatMapDepth, lodash.flatten = flatten, lodash.flattenDeep = flattenDeep, lodash.flattenDepth = flattenDepth, lodash.flip = flip, lodash.flow = flow, lodash.flowRight = flowRight, lodash.fromPairs = fromPairs, lodash.functions = functions, lodash.functionsIn = functionsIn, lodash.groupBy = groupBy2, lodash.initial = initial, lodash.intersection = intersection, lodash.intersectionBy = intersectionBy, lodash.intersectionWith = intersectionWith, lodash.invert = invert, lodash.invertBy = invertBy, lodash.invokeMap = invokeMap, lodash.iteratee = iteratee, lodash.keyBy = keyBy, lodash.keys = keys, lodash.keysIn = keysIn, lodash.map = map, lodash.mapKeys = mapKeys, lodash.mapValues = mapValues, lodash.matches = matches2, lodash.matchesProperty = matchesProperty, lodash.memoize = memoize, lodash.merge = merge, lodash.mergeWith = mergeWith, lodash.method = method, lodash.methodOf = methodOf, lodash.mixin = mixin, lodash.negate = negate, lodash.nthArg = nthArg, lodash.omit = omit, lodash.omitBy = omitBy, lodash.once = once, lodash.orderBy = orderBy, lodash.over = over, lodash.overArgs = overArgs, lodash.overEvery = overEvery, lodash.overSome = overSome, lodash.partial = partial, lodash.partialRight = partialRight, lodash.partition = partition2, lodash.pick = pick, lodash.pickBy = pickBy2, lodash.property = property, lodash.propertyOf = propertyOf, lodash.pull = pull3, lodash.pullAll = pullAll, lodash.pullAllBy = pullAllBy, lodash.pullAllWith = pullAllWith, lodash.pullAt = pullAt, lodash.range = range, lodash.rangeRight = rangeRight, lodash.rearg = rearg, lodash.reject = reject, lodash.remove = remove2, lodash.rest = rest, lodash.reverse = reverse, lodash.sampleSize = sampleSize, lodash.set = set, lodash.setWith = setWith, lodash.shuffle = shuffle, lodash.slice = slice, lodash.sortBy = sortBy, lodash.sortedUniq = sortedUniq, lodash.sortedUniqBy = sortedUniqBy, lodash.split = split, lodash.spread = spread, lodash.tail = tail, lodash.take = take, lodash.takeRight = takeRight, lodash.takeRightWhile = takeRightWhile, lodash.takeWhile = takeWhile, lodash.tap = tap, lodash.throttle = throttle, lodash.thru = thru, lodash.toArray = toArray, lodash.toPairs = toPairs, lodash.toPairsIn = toPairsIn, lodash.toPath = toPath, lodash.toPlainObject = toPlainObject, lodash.transform = transform2, lodash.unary = unary, lodash.union = union2, lodash.unionBy = unionBy, lodash.unionWith = unionWith, lodash.uniq = uniq2, lodash.uniqBy = uniqBy2, lodash.uniqWith = uniqWith, lodash.unset = unset, lodash.unzip = unzip, lodash.unzipWith = unzipWith, lodash.update = update, lodash.updateWith = updateWith, lodash.values = values2, lodash.valuesIn = valuesIn, lodash.without = without, lodash.words = words, lodash.wrap = wrap, lodash.xor = xor, lodash.xorBy = xorBy, lodash.xorWith = xorWith, lodash.zip = zip2, lodash.zipObject = zipObject, lodash.zipObjectDeep = zipObjectDeep, lodash.zipWith = zipWith, lodash.entries = toPairs, lodash.entriesIn = toPairsIn, lodash.extend = assignIn, lodash.extendWith = assignInWith, mixin(lodash, lodash), lodash.add = add, lodash.attempt = attempt, lodash.camelCase = camelCase, lodash.capitalize = capitalize2, lodash.ceil = ceil, lodash.clamp = clamp, lodash.clone = clone, lodash.cloneDeep = cloneDeep2, lodash.cloneDeepWith = cloneDeepWith, lodash.cloneWith = cloneWith, lodash.conformsTo = conformsTo, lodash.deburr = deburr, lodash.defaultTo = defaultTo, lodash.divide = divide, lodash.endsWith = endsWith3, lodash.eq = eq, lodash.escape = escape, lodash.escapeRegExp = escapeRegExp4, lodash.every = every, lodash.find = find, lodash.findIndex = findIndex, lodash.findKey = findKey, lodash.findLast = findLast, lodash.findLastIndex = findLastIndex, lodash.findLastKey = findLastKey, lodash.floor = floor, lodash.forEach = forEach, lodash.forEachRight = forEachRight, lodash.forIn = forIn, lodash.forInRight = forInRight, lodash.forOwn = forOwn, lodash.forOwnRight = forOwnRight, lodash.get = get, lodash.gt = gt, lodash.gte = gte, lodash.has = has, lodash.hasIn = hasIn, lodash.head = head, lodash.identity = identity2, lodash.includes = includes2, lodash.indexOf = indexOf, lodash.inRange = inRange, lodash.invoke = invoke, lodash.isArguments = isArguments, lodash.isArray = isArray, lodash.isArrayBuffer = isArrayBuffer, lodash.isArrayLike = isArrayLike, lodash.isArrayLikeObject = isArrayLikeObject, lodash.isBoolean = isBoolean2, lodash.isBuffer = isBuffer, lodash.isDate = isDate, lodash.isElement = isElement, lodash.isEmpty = isEmpty2, lodash.isEqual = isEqual, lodash.isEqualWith = isEqualWith, lodash.isError = isError2, lodash.isFinite = isFinite2, lodash.isFunction = isFunction, lodash.isInteger = isInteger, lodash.isLength = isLength, lodash.isMap = isMap, lodash.isMatch = isMatch, lodash.isMatchWith = isMatchWith, lodash.isNaN = isNaN2, lodash.isNative = isNative, lodash.isNil = isNil, lodash.isNull = isNull, lodash.isNumber = isNumber2, lodash.isObject = isObject2, lodash.isObjectLike = isObjectLike, lodash.isPlainObject = isPlainObject3, lodash.isRegExp = isRegExp, lodash.isSafeInteger = isSafeInteger, lodash.isSet = isSet, lodash.isString = isString3, lodash.isSymbol = isSymbol, lodash.isTypedArray = isTypedArray, lodash.isUndefined = isUndefined, lodash.isWeakMap = isWeakMap, lodash.isWeakSet = isWeakSet, lodash.join = join2, lodash.kebabCase = kebabCase, lodash.last = last, lodash.lastIndexOf = lastIndexOf, lodash.lowerCase = lowerCase, lodash.lowerFirst = lowerFirst, lodash.lt =
|
|
31231
|
+
return lodash.after = after, lodash.ary = ary, lodash.assign = assign, lodash.assignIn = assignIn, lodash.assignInWith = assignInWith, lodash.assignWith = assignWith, lodash.at = at, lodash.before = before, lodash.bind = bind, lodash.bindAll = bindAll, lodash.bindKey = bindKey, lodash.castArray = castArray, lodash.chain = chain, lodash.chunk = chunk, lodash.compact = compact2, lodash.concat = concat, lodash.cond = cond, lodash.conforms = conforms, lodash.constant = constant, lodash.countBy = countBy, lodash.create = create, lodash.curry = curry, lodash.curryRight = curryRight, lodash.debounce = debounce2, lodash.defaults = defaults, lodash.defaultsDeep = defaultsDeep, lodash.defer = defer2, lodash.delay = delay2, lodash.difference = difference2, lodash.differenceBy = differenceBy, lodash.differenceWith = differenceWith, lodash.drop = drop, lodash.dropRight = dropRight, lodash.dropRightWhile = dropRightWhile, lodash.dropWhile = dropWhile, lodash.fill = fill, lodash.filter = filter, lodash.flatMap = flatMap, lodash.flatMapDeep = flatMapDeep, lodash.flatMapDepth = flatMapDepth, lodash.flatten = flatten, lodash.flattenDeep = flattenDeep, lodash.flattenDepth = flattenDepth, lodash.flip = flip, lodash.flow = flow, lodash.flowRight = flowRight, lodash.fromPairs = fromPairs, lodash.functions = functions, lodash.functionsIn = functionsIn, lodash.groupBy = groupBy2, lodash.initial = initial, lodash.intersection = intersection, lodash.intersectionBy = intersectionBy, lodash.intersectionWith = intersectionWith, lodash.invert = invert, lodash.invertBy = invertBy, lodash.invokeMap = invokeMap, lodash.iteratee = iteratee, lodash.keyBy = keyBy, lodash.keys = keys, lodash.keysIn = keysIn, lodash.map = map, lodash.mapKeys = mapKeys, lodash.mapValues = mapValues, lodash.matches = matches2, lodash.matchesProperty = matchesProperty, lodash.memoize = memoize, lodash.merge = merge, lodash.mergeWith = mergeWith, lodash.method = method, lodash.methodOf = methodOf, lodash.mixin = mixin, lodash.negate = negate, lodash.nthArg = nthArg, lodash.omit = omit, lodash.omitBy = omitBy, lodash.once = once, lodash.orderBy = orderBy, lodash.over = over, lodash.overArgs = overArgs, lodash.overEvery = overEvery, lodash.overSome = overSome, lodash.partial = partial, lodash.partialRight = partialRight, lodash.partition = partition2, lodash.pick = pick, lodash.pickBy = pickBy2, lodash.property = property, lodash.propertyOf = propertyOf, lodash.pull = pull3, lodash.pullAll = pullAll, lodash.pullAllBy = pullAllBy, lodash.pullAllWith = pullAllWith, lodash.pullAt = pullAt, lodash.range = range, lodash.rangeRight = rangeRight, lodash.rearg = rearg, lodash.reject = reject, lodash.remove = remove2, lodash.rest = rest, lodash.reverse = reverse, lodash.sampleSize = sampleSize, lodash.set = set, lodash.setWith = setWith, lodash.shuffle = shuffle, lodash.slice = slice, lodash.sortBy = sortBy, lodash.sortedUniq = sortedUniq, lodash.sortedUniqBy = sortedUniqBy, lodash.split = split, lodash.spread = spread, lodash.tail = tail, lodash.take = take, lodash.takeRight = takeRight, lodash.takeRightWhile = takeRightWhile, lodash.takeWhile = takeWhile, lodash.tap = tap, lodash.throttle = throttle, lodash.thru = thru, lodash.toArray = toArray, lodash.toPairs = toPairs, lodash.toPairsIn = toPairsIn, lodash.toPath = toPath, lodash.toPlainObject = toPlainObject, lodash.transform = transform2, lodash.unary = unary, lodash.union = union2, lodash.unionBy = unionBy, lodash.unionWith = unionWith, lodash.uniq = uniq2, lodash.uniqBy = uniqBy2, lodash.uniqWith = uniqWith, lodash.unset = unset, lodash.unzip = unzip, lodash.unzipWith = unzipWith, lodash.update = update, lodash.updateWith = updateWith, lodash.values = values2, lodash.valuesIn = valuesIn, lodash.without = without, lodash.words = words, lodash.wrap = wrap, lodash.xor = xor, lodash.xorBy = xorBy, lodash.xorWith = xorWith, lodash.zip = zip2, lodash.zipObject = zipObject, lodash.zipObjectDeep = zipObjectDeep, lodash.zipWith = zipWith, lodash.entries = toPairs, lodash.entriesIn = toPairsIn, lodash.extend = assignIn, lodash.extendWith = assignInWith, mixin(lodash, lodash), lodash.add = add, lodash.attempt = attempt, lodash.camelCase = camelCase, lodash.capitalize = capitalize2, lodash.ceil = ceil, lodash.clamp = clamp, lodash.clone = clone, lodash.cloneDeep = cloneDeep2, lodash.cloneDeepWith = cloneDeepWith, lodash.cloneWith = cloneWith, lodash.conformsTo = conformsTo, lodash.deburr = deburr, lodash.defaultTo = defaultTo, lodash.divide = divide, lodash.endsWith = endsWith3, lodash.eq = eq, lodash.escape = escape, lodash.escapeRegExp = escapeRegExp4, lodash.every = every, lodash.find = find, lodash.findIndex = findIndex, lodash.findKey = findKey, lodash.findLast = findLast, lodash.findLastIndex = findLastIndex, lodash.findLastKey = findLastKey, lodash.floor = floor, lodash.forEach = forEach, lodash.forEachRight = forEachRight, lodash.forIn = forIn, lodash.forInRight = forInRight, lodash.forOwn = forOwn, lodash.forOwnRight = forOwnRight, lodash.get = get, lodash.gt = gt, lodash.gte = gte, lodash.has = has, lodash.hasIn = hasIn, lodash.head = head, lodash.identity = identity2, lodash.includes = includes2, lodash.indexOf = indexOf, lodash.inRange = inRange, lodash.invoke = invoke, lodash.isArguments = isArguments, lodash.isArray = isArray, lodash.isArrayBuffer = isArrayBuffer, lodash.isArrayLike = isArrayLike, lodash.isArrayLikeObject = isArrayLikeObject, lodash.isBoolean = isBoolean2, lodash.isBuffer = isBuffer, lodash.isDate = isDate, lodash.isElement = isElement, lodash.isEmpty = isEmpty2, lodash.isEqual = isEqual, lodash.isEqualWith = isEqualWith, lodash.isError = isError2, lodash.isFinite = isFinite2, lodash.isFunction = isFunction, lodash.isInteger = isInteger, lodash.isLength = isLength, lodash.isMap = isMap, lodash.isMatch = isMatch, lodash.isMatchWith = isMatchWith, lodash.isNaN = isNaN2, lodash.isNative = isNative, lodash.isNil = isNil, lodash.isNull = isNull, lodash.isNumber = isNumber2, lodash.isObject = isObject2, lodash.isObjectLike = isObjectLike, lodash.isPlainObject = isPlainObject3, lodash.isRegExp = isRegExp, lodash.isSafeInteger = isSafeInteger, lodash.isSet = isSet, lodash.isString = isString3, lodash.isSymbol = isSymbol, lodash.isTypedArray = isTypedArray, lodash.isUndefined = isUndefined, lodash.isWeakMap = isWeakMap, lodash.isWeakSet = isWeakSet, lodash.join = join2, lodash.kebabCase = kebabCase, lodash.last = last, lodash.lastIndexOf = lastIndexOf, lodash.lowerCase = lowerCase, lodash.lowerFirst = lowerFirst, lodash.lt = lt2, lodash.lte = lte, lodash.max = max, lodash.maxBy = maxBy, lodash.mean = mean, lodash.meanBy = meanBy, lodash.min = min, lodash.minBy = minBy, lodash.stubArray = stubArray, lodash.stubFalse = stubFalse, lodash.stubObject = stubObject, lodash.stubString = stubString, lodash.stubTrue = stubTrue, lodash.multiply = multiply, lodash.nth = nth, lodash.noConflict = noConflict, lodash.noop = noop2, lodash.now = now, lodash.pad = pad, lodash.padEnd = padEnd, lodash.padStart = padStart, lodash.parseInt = parseInt2, lodash.random = random, lodash.reduce = reduce, lodash.reduceRight = reduceRight, lodash.repeat = repeat3, lodash.replace = replace, lodash.result = result, lodash.round = round, lodash.runInContext = runInContext2, lodash.sample = sample, lodash.size = size, lodash.snakeCase = snakeCase, lodash.some = some, lodash.sortedIndex = sortedIndex, lodash.sortedIndexBy = sortedIndexBy, lodash.sortedIndexOf = sortedIndexOf, lodash.sortedLastIndex = sortedLastIndex, lodash.sortedLastIndexBy = sortedLastIndexBy, lodash.sortedLastIndexOf = sortedLastIndexOf, lodash.startCase = startCase, lodash.startsWith = startsWith3, lodash.subtract = subtract, lodash.sum = sum, lodash.sumBy = sumBy, lodash.template = template, lodash.times = times, lodash.toFinite = toFinite, lodash.toInteger = toInteger, lodash.toLength = toLength, lodash.toLower = toLower, lodash.toNumber = toNumber, lodash.toSafeInteger = toSafeInteger, lodash.toString = toString2, lodash.toUpper = toUpper, lodash.trim = trim2, lodash.trimEnd = trimEnd, lodash.trimStart = trimStart, lodash.truncate = truncate, lodash.unescape = unescape4, lodash.uniqueId = uniqueId, lodash.upperCase = upperCase, lodash.upperFirst = upperFirst, lodash.each = forEach, lodash.eachRight = forEachRight, lodash.first = head, mixin(lodash, (function() {
|
|
31230
31232
|
var source = {};
|
|
31231
31233
|
return baseForOwn(lodash, function(func, methodName) {
|
|
31232
31234
|
hasOwnProperty.call(lodash.prototype, methodName) || (source[methodName] = func);
|
|
@@ -51028,7 +51030,7 @@ var require_lodash2 = __commonJS({
|
|
|
51028
51030
|
function isWeakSet(value) {
|
|
51029
51031
|
return isObjectLike(value) && baseGetTag(value) == weakSetTag;
|
|
51030
51032
|
}
|
|
51031
|
-
var
|
|
51033
|
+
var lt2 = createRelationalOperation(baseLt), lte = createRelationalOperation(function(value, other) {
|
|
51032
51034
|
return value <= other;
|
|
51033
51035
|
});
|
|
51034
51036
|
function toArray(value) {
|
|
@@ -51596,7 +51598,7 @@ function print() { __p += __j.call(arguments, '') }
|
|
|
51596
51598
|
function sumBy(array, iteratee2) {
|
|
51597
51599
|
return array && array.length ? baseSum(array, getIteratee(iteratee2, 2)) : 0;
|
|
51598
51600
|
}
|
|
51599
|
-
return lodash.after = after, lodash.ary = ary, lodash.assign = assign, lodash.assignIn = assignIn, lodash.assignInWith = assignInWith, lodash.assignWith = assignWith, lodash.at = at, lodash.before = before, lodash.bind = bind, lodash.bindAll = bindAll, lodash.bindKey = bindKey, lodash.castArray = castArray, lodash.chain = chain, lodash.chunk = chunk, lodash.compact = compact2, lodash.concat = concat, lodash.cond = cond, lodash.conforms = conforms, lodash.constant = constant, lodash.countBy = countBy, lodash.create = create, lodash.curry = curry, lodash.curryRight = curryRight, lodash.debounce = debounce2, lodash.defaults = defaults, lodash.defaultsDeep = defaultsDeep, lodash.defer = defer2, lodash.delay = delay2, lodash.difference = difference2, lodash.differenceBy = differenceBy, lodash.differenceWith = differenceWith, lodash.drop = drop, lodash.dropRight = dropRight, lodash.dropRightWhile = dropRightWhile, lodash.dropWhile = dropWhile, lodash.fill = fill, lodash.filter = filter, lodash.flatMap = flatMap, lodash.flatMapDeep = flatMapDeep, lodash.flatMapDepth = flatMapDepth, lodash.flatten = flatten, lodash.flattenDeep = flattenDeep, lodash.flattenDepth = flattenDepth, lodash.flip = flip, lodash.flow = flow, lodash.flowRight = flowRight, lodash.fromPairs = fromPairs, lodash.functions = functions, lodash.functionsIn = functionsIn, lodash.groupBy = groupBy2, lodash.initial = initial, lodash.intersection = intersection, lodash.intersectionBy = intersectionBy, lodash.intersectionWith = intersectionWith, lodash.invert = invert, lodash.invertBy = invertBy, lodash.invokeMap = invokeMap, lodash.iteratee = iteratee, lodash.keyBy = keyBy, lodash.keys = keys, lodash.keysIn = keysIn, lodash.map = map, lodash.mapKeys = mapKeys, lodash.mapValues = mapValues, lodash.matches = matches2, lodash.matchesProperty = matchesProperty, lodash.memoize = memoize, lodash.merge = merge, lodash.mergeWith = mergeWith, lodash.method = method, lodash.methodOf = methodOf, lodash.mixin = mixin, lodash.negate = negate, lodash.nthArg = nthArg, lodash.omit = omit, lodash.omitBy = omitBy, lodash.once = once, lodash.orderBy = orderBy, lodash.over = over, lodash.overArgs = overArgs, lodash.overEvery = overEvery, lodash.overSome = overSome, lodash.partial = partial, lodash.partialRight = partialRight, lodash.partition = partition2, lodash.pick = pick, lodash.pickBy = pickBy2, lodash.property = property, lodash.propertyOf = propertyOf, lodash.pull = pull3, lodash.pullAll = pullAll, lodash.pullAllBy = pullAllBy, lodash.pullAllWith = pullAllWith, lodash.pullAt = pullAt, lodash.range = range, lodash.rangeRight = rangeRight, lodash.rearg = rearg, lodash.reject = reject, lodash.remove = remove2, lodash.rest = rest, lodash.reverse = reverse, lodash.sampleSize = sampleSize, lodash.set = set, lodash.setWith = setWith, lodash.shuffle = shuffle, lodash.slice = slice, lodash.sortBy = sortBy, lodash.sortedUniq = sortedUniq, lodash.sortedUniqBy = sortedUniqBy, lodash.split = split, lodash.spread = spread, lodash.tail = tail, lodash.take = take, lodash.takeRight = takeRight, lodash.takeRightWhile = takeRightWhile, lodash.takeWhile = takeWhile, lodash.tap = tap, lodash.throttle = throttle, lodash.thru = thru, lodash.toArray = toArray, lodash.toPairs = toPairs, lodash.toPairsIn = toPairsIn, lodash.toPath = toPath, lodash.toPlainObject = toPlainObject, lodash.transform = transform2, lodash.unary = unary, lodash.union = union2, lodash.unionBy = unionBy, lodash.unionWith = unionWith, lodash.uniq = uniq2, lodash.uniqBy = uniqBy2, lodash.uniqWith = uniqWith, lodash.unset = unset, lodash.unzip = unzip, lodash.unzipWith = unzipWith, lodash.update = update, lodash.updateWith = updateWith, lodash.values = values2, lodash.valuesIn = valuesIn, lodash.without = without, lodash.words = words, lodash.wrap = wrap, lodash.xor = xor, lodash.xorBy = xorBy, lodash.xorWith = xorWith, lodash.zip = zip2, lodash.zipObject = zipObject, lodash.zipObjectDeep = zipObjectDeep, lodash.zipWith = zipWith, lodash.entries = toPairs, lodash.entriesIn = toPairsIn, lodash.extend = assignIn, lodash.extendWith = assignInWith, mixin(lodash, lodash), lodash.add = add, lodash.attempt = attempt, lodash.camelCase = camelCase, lodash.capitalize = capitalize2, lodash.ceil = ceil, lodash.clamp = clamp, lodash.clone = clone, lodash.cloneDeep = cloneDeep2, lodash.cloneDeepWith = cloneDeepWith, lodash.cloneWith = cloneWith, lodash.conformsTo = conformsTo, lodash.deburr = deburr, lodash.defaultTo = defaultTo, lodash.divide = divide, lodash.endsWith = endsWith3, lodash.eq = eq, lodash.escape = escape, lodash.escapeRegExp = escapeRegExp4, lodash.every = every, lodash.find = find, lodash.findIndex = findIndex, lodash.findKey = findKey, lodash.findLast = findLast, lodash.findLastIndex = findLastIndex, lodash.findLastKey = findLastKey, lodash.floor = floor, lodash.forEach = forEach, lodash.forEachRight = forEachRight, lodash.forIn = forIn, lodash.forInRight = forInRight, lodash.forOwn = forOwn, lodash.forOwnRight = forOwnRight, lodash.get = get, lodash.gt = gt, lodash.gte = gte, lodash.has = has, lodash.hasIn = hasIn, lodash.head = head, lodash.identity = identity2, lodash.includes = includes2, lodash.indexOf = indexOf, lodash.inRange = inRange, lodash.invoke = invoke, lodash.isArguments = isArguments, lodash.isArray = isArray, lodash.isArrayBuffer = isArrayBuffer, lodash.isArrayLike = isArrayLike, lodash.isArrayLikeObject = isArrayLikeObject, lodash.isBoolean = isBoolean2, lodash.isBuffer = isBuffer, lodash.isDate = isDate, lodash.isElement = isElement, lodash.isEmpty = isEmpty2, lodash.isEqual = isEqual, lodash.isEqualWith = isEqualWith, lodash.isError = isError2, lodash.isFinite = isFinite2, lodash.isFunction = isFunction, lodash.isInteger = isInteger, lodash.isLength = isLength, lodash.isMap = isMap, lodash.isMatch = isMatch, lodash.isMatchWith = isMatchWith, lodash.isNaN = isNaN2, lodash.isNative = isNative, lodash.isNil = isNil, lodash.isNull = isNull, lodash.isNumber = isNumber2, lodash.isObject = isObject2, lodash.isObjectLike = isObjectLike, lodash.isPlainObject = isPlainObject3, lodash.isRegExp = isRegExp, lodash.isSafeInteger = isSafeInteger, lodash.isSet = isSet, lodash.isString = isString3, lodash.isSymbol = isSymbol, lodash.isTypedArray = isTypedArray, lodash.isUndefined = isUndefined, lodash.isWeakMap = isWeakMap, lodash.isWeakSet = isWeakSet, lodash.join = join2, lodash.kebabCase = kebabCase, lodash.last = last, lodash.lastIndexOf = lastIndexOf, lodash.lowerCase = lowerCase, lodash.lowerFirst = lowerFirst, lodash.lt =
|
|
51601
|
+
return lodash.after = after, lodash.ary = ary, lodash.assign = assign, lodash.assignIn = assignIn, lodash.assignInWith = assignInWith, lodash.assignWith = assignWith, lodash.at = at, lodash.before = before, lodash.bind = bind, lodash.bindAll = bindAll, lodash.bindKey = bindKey, lodash.castArray = castArray, lodash.chain = chain, lodash.chunk = chunk, lodash.compact = compact2, lodash.concat = concat, lodash.cond = cond, lodash.conforms = conforms, lodash.constant = constant, lodash.countBy = countBy, lodash.create = create, lodash.curry = curry, lodash.curryRight = curryRight, lodash.debounce = debounce2, lodash.defaults = defaults, lodash.defaultsDeep = defaultsDeep, lodash.defer = defer2, lodash.delay = delay2, lodash.difference = difference2, lodash.differenceBy = differenceBy, lodash.differenceWith = differenceWith, lodash.drop = drop, lodash.dropRight = dropRight, lodash.dropRightWhile = dropRightWhile, lodash.dropWhile = dropWhile, lodash.fill = fill, lodash.filter = filter, lodash.flatMap = flatMap, lodash.flatMapDeep = flatMapDeep, lodash.flatMapDepth = flatMapDepth, lodash.flatten = flatten, lodash.flattenDeep = flattenDeep, lodash.flattenDepth = flattenDepth, lodash.flip = flip, lodash.flow = flow, lodash.flowRight = flowRight, lodash.fromPairs = fromPairs, lodash.functions = functions, lodash.functionsIn = functionsIn, lodash.groupBy = groupBy2, lodash.initial = initial, lodash.intersection = intersection, lodash.intersectionBy = intersectionBy, lodash.intersectionWith = intersectionWith, lodash.invert = invert, lodash.invertBy = invertBy, lodash.invokeMap = invokeMap, lodash.iteratee = iteratee, lodash.keyBy = keyBy, lodash.keys = keys, lodash.keysIn = keysIn, lodash.map = map, lodash.mapKeys = mapKeys, lodash.mapValues = mapValues, lodash.matches = matches2, lodash.matchesProperty = matchesProperty, lodash.memoize = memoize, lodash.merge = merge, lodash.mergeWith = mergeWith, lodash.method = method, lodash.methodOf = methodOf, lodash.mixin = mixin, lodash.negate = negate, lodash.nthArg = nthArg, lodash.omit = omit, lodash.omitBy = omitBy, lodash.once = once, lodash.orderBy = orderBy, lodash.over = over, lodash.overArgs = overArgs, lodash.overEvery = overEvery, lodash.overSome = overSome, lodash.partial = partial, lodash.partialRight = partialRight, lodash.partition = partition2, lodash.pick = pick, lodash.pickBy = pickBy2, lodash.property = property, lodash.propertyOf = propertyOf, lodash.pull = pull3, lodash.pullAll = pullAll, lodash.pullAllBy = pullAllBy, lodash.pullAllWith = pullAllWith, lodash.pullAt = pullAt, lodash.range = range, lodash.rangeRight = rangeRight, lodash.rearg = rearg, lodash.reject = reject, lodash.remove = remove2, lodash.rest = rest, lodash.reverse = reverse, lodash.sampleSize = sampleSize, lodash.set = set, lodash.setWith = setWith, lodash.shuffle = shuffle, lodash.slice = slice, lodash.sortBy = sortBy, lodash.sortedUniq = sortedUniq, lodash.sortedUniqBy = sortedUniqBy, lodash.split = split, lodash.spread = spread, lodash.tail = tail, lodash.take = take, lodash.takeRight = takeRight, lodash.takeRightWhile = takeRightWhile, lodash.takeWhile = takeWhile, lodash.tap = tap, lodash.throttle = throttle, lodash.thru = thru, lodash.toArray = toArray, lodash.toPairs = toPairs, lodash.toPairsIn = toPairsIn, lodash.toPath = toPath, lodash.toPlainObject = toPlainObject, lodash.transform = transform2, lodash.unary = unary, lodash.union = union2, lodash.unionBy = unionBy, lodash.unionWith = unionWith, lodash.uniq = uniq2, lodash.uniqBy = uniqBy2, lodash.uniqWith = uniqWith, lodash.unset = unset, lodash.unzip = unzip, lodash.unzipWith = unzipWith, lodash.update = update, lodash.updateWith = updateWith, lodash.values = values2, lodash.valuesIn = valuesIn, lodash.without = without, lodash.words = words, lodash.wrap = wrap, lodash.xor = xor, lodash.xorBy = xorBy, lodash.xorWith = xorWith, lodash.zip = zip2, lodash.zipObject = zipObject, lodash.zipObjectDeep = zipObjectDeep, lodash.zipWith = zipWith, lodash.entries = toPairs, lodash.entriesIn = toPairsIn, lodash.extend = assignIn, lodash.extendWith = assignInWith, mixin(lodash, lodash), lodash.add = add, lodash.attempt = attempt, lodash.camelCase = camelCase, lodash.capitalize = capitalize2, lodash.ceil = ceil, lodash.clamp = clamp, lodash.clone = clone, lodash.cloneDeep = cloneDeep2, lodash.cloneDeepWith = cloneDeepWith, lodash.cloneWith = cloneWith, lodash.conformsTo = conformsTo, lodash.deburr = deburr, lodash.defaultTo = defaultTo, lodash.divide = divide, lodash.endsWith = endsWith3, lodash.eq = eq, lodash.escape = escape, lodash.escapeRegExp = escapeRegExp4, lodash.every = every, lodash.find = find, lodash.findIndex = findIndex, lodash.findKey = findKey, lodash.findLast = findLast, lodash.findLastIndex = findLastIndex, lodash.findLastKey = findLastKey, lodash.floor = floor, lodash.forEach = forEach, lodash.forEachRight = forEachRight, lodash.forIn = forIn, lodash.forInRight = forInRight, lodash.forOwn = forOwn, lodash.forOwnRight = forOwnRight, lodash.get = get, lodash.gt = gt, lodash.gte = gte, lodash.has = has, lodash.hasIn = hasIn, lodash.head = head, lodash.identity = identity2, lodash.includes = includes2, lodash.indexOf = indexOf, lodash.inRange = inRange, lodash.invoke = invoke, lodash.isArguments = isArguments, lodash.isArray = isArray, lodash.isArrayBuffer = isArrayBuffer, lodash.isArrayLike = isArrayLike, lodash.isArrayLikeObject = isArrayLikeObject, lodash.isBoolean = isBoolean2, lodash.isBuffer = isBuffer, lodash.isDate = isDate, lodash.isElement = isElement, lodash.isEmpty = isEmpty2, lodash.isEqual = isEqual, lodash.isEqualWith = isEqualWith, lodash.isError = isError2, lodash.isFinite = isFinite2, lodash.isFunction = isFunction, lodash.isInteger = isInteger, lodash.isLength = isLength, lodash.isMap = isMap, lodash.isMatch = isMatch, lodash.isMatchWith = isMatchWith, lodash.isNaN = isNaN2, lodash.isNative = isNative, lodash.isNil = isNil, lodash.isNull = isNull, lodash.isNumber = isNumber2, lodash.isObject = isObject2, lodash.isObjectLike = isObjectLike, lodash.isPlainObject = isPlainObject3, lodash.isRegExp = isRegExp, lodash.isSafeInteger = isSafeInteger, lodash.isSet = isSet, lodash.isString = isString3, lodash.isSymbol = isSymbol, lodash.isTypedArray = isTypedArray, lodash.isUndefined = isUndefined, lodash.isWeakMap = isWeakMap, lodash.isWeakSet = isWeakSet, lodash.join = join2, lodash.kebabCase = kebabCase, lodash.last = last, lodash.lastIndexOf = lastIndexOf, lodash.lowerCase = lowerCase, lodash.lowerFirst = lowerFirst, lodash.lt = lt2, lodash.lte = lte, lodash.max = max, lodash.maxBy = maxBy, lodash.mean = mean, lodash.meanBy = meanBy, lodash.min = min, lodash.minBy = minBy, lodash.stubArray = stubArray, lodash.stubFalse = stubFalse, lodash.stubObject = stubObject, lodash.stubString = stubString, lodash.stubTrue = stubTrue, lodash.multiply = multiply, lodash.nth = nth, lodash.noConflict = noConflict, lodash.noop = noop2, lodash.now = now, lodash.pad = pad, lodash.padEnd = padEnd, lodash.padStart = padStart, lodash.parseInt = parseInt2, lodash.random = random, lodash.reduce = reduce, lodash.reduceRight = reduceRight, lodash.repeat = repeat3, lodash.replace = replace, lodash.result = result, lodash.round = round, lodash.runInContext = runInContext2, lodash.sample = sample, lodash.size = size, lodash.snakeCase = snakeCase, lodash.some = some, lodash.sortedIndex = sortedIndex, lodash.sortedIndexBy = sortedIndexBy, lodash.sortedIndexOf = sortedIndexOf, lodash.sortedLastIndex = sortedLastIndex, lodash.sortedLastIndexBy = sortedLastIndexBy, lodash.sortedLastIndexOf = sortedLastIndexOf, lodash.startCase = startCase, lodash.startsWith = startsWith3, lodash.subtract = subtract, lodash.sum = sum, lodash.sumBy = sumBy, lodash.template = template, lodash.times = times, lodash.toFinite = toFinite, lodash.toInteger = toInteger, lodash.toLength = toLength, lodash.toLower = toLower, lodash.toNumber = toNumber, lodash.toSafeInteger = toSafeInteger, lodash.toString = toString2, lodash.toUpper = toUpper, lodash.trim = trim2, lodash.trimEnd = trimEnd, lodash.trimStart = trimStart, lodash.truncate = truncate, lodash.unescape = unescape4, lodash.uniqueId = uniqueId, lodash.upperCase = upperCase, lodash.upperFirst = upperFirst, lodash.each = forEach, lodash.eachRight = forEachRight, lodash.first = head, mixin(lodash, (function() {
|
|
51600
51602
|
var source = {};
|
|
51601
51603
|
return baseForOwn(lodash, function(func, methodName) {
|
|
51602
51604
|
hasOwnProperty.call(lodash.prototype, methodName) || (source[methodName] = func);
|
|
@@ -126903,22 +126905,22 @@ From ` + this.originalError.stack);
|
|
|
126903
126905
|
this.context.memoryLimit.use(str.length);
|
|
126904
126906
|
let blocks2 = /* @__PURE__ */ new Map([["<script", "</script>"], ["<style", "</style>"], ["<!--", "-->"], ["<", ">"]]), out = "", i = 0;
|
|
126905
126907
|
for (; i < str.length; ) {
|
|
126906
|
-
let
|
|
126907
|
-
if (
|
|
126908
|
+
let lt2 = str.indexOf("<", i);
|
|
126909
|
+
if (lt2 < 0)
|
|
126908
126910
|
return out + str.slice(i);
|
|
126909
|
-
out += str.slice(i,
|
|
126911
|
+
out += str.slice(i, lt2);
|
|
126910
126912
|
for (let [opener, closer] of blocks2) {
|
|
126911
|
-
if (!str.startsWith(opener,
|
|
126913
|
+
if (!str.startsWith(opener, lt2))
|
|
126912
126914
|
continue;
|
|
126913
|
-
let e = str.indexOf(closer,
|
|
126915
|
+
let e = str.indexOf(closer, lt2 + opener.length);
|
|
126914
126916
|
if (e >= 0) {
|
|
126915
126917
|
i = e + closer.length;
|
|
126916
126918
|
break;
|
|
126917
126919
|
}
|
|
126918
126920
|
blocks2.delete(opener);
|
|
126919
126921
|
}
|
|
126920
|
-
if (i ===
|
|
126921
|
-
return out + str.slice(
|
|
126922
|
+
if (i === lt2)
|
|
126923
|
+
return out + str.slice(lt2);
|
|
126922
126924
|
}
|
|
126923
126925
|
return out;
|
|
126924
126926
|
}
|
|
@@ -203943,7 +203945,7 @@ var import_core2 = __toESM(require_lib()), BaseCommand = class extends import_co
|
|
|
203943
203945
|
}
|
|
203944
203946
|
async catch(error) {
|
|
203945
203947
|
error.skipOclifErrorHandling = !0;
|
|
203946
|
-
let { errorHandler } = await import("./error-handler-
|
|
203948
|
+
let { errorHandler } = await import("./error-handler-MENPWWOI.js");
|
|
203947
203949
|
return await errorHandler(error, this.config), import_core2.Errors.handle(error);
|
|
203948
203950
|
}
|
|
203949
203951
|
async _run() {
|
|
@@ -203951,11 +203953,11 @@ var import_core2 = __toESM(require_lib()), BaseCommand = class extends import_co
|
|
|
203951
203953
|
}
|
|
203952
203954
|
async init() {
|
|
203953
203955
|
if (this.exitWithTimestampWhenEnvVariablePresent(), setCurrentCommandId(this.id ?? ""), !isDevelopment()) {
|
|
203954
|
-
let { registerCleanBugsnagErrorsFromWithinPlugins } = await import("./error-handler-
|
|
203956
|
+
let { registerCleanBugsnagErrorsFromWithinPlugins } = await import("./error-handler-MENPWWOI.js");
|
|
203955
203957
|
await registerCleanBugsnagErrorsFromWithinPlugins(this.config);
|
|
203956
203958
|
}
|
|
203957
203959
|
await removeDuplicatedPlugins(this.config), this.showNpmFlagWarning();
|
|
203958
|
-
let { showNotificationsIfNeeded: showNotificationsIfNeeded2 } = await import("./notifications-system-
|
|
203960
|
+
let { showNotificationsIfNeeded: showNotificationsIfNeeded2 } = await import("./notifications-system-TAHUXXGQ.js");
|
|
203959
203961
|
return await showNotificationsIfNeeded2(), super.init();
|
|
203960
203962
|
}
|
|
203961
203963
|
// NPM creates an environment variable for every flag passed to a script.
|
|
@@ -203963,7 +203965,7 @@ var import_core2 = __toESM(require_lib()), BaseCommand = class extends import_co
|
|
|
203963
203965
|
// and warns the user to use the `--` separator.
|
|
203964
203966
|
showNpmFlagWarning() {
|
|
203965
203967
|
let commandVariables = this.constructor;
|
|
203966
|
-
Object.keys(commandVariables.flags || {}).map((key) => `npm_config_${underscore(key).replace(/^no_/, "")}`).some((flag) => process.env[flag] !== void 0) && import("./ui-
|
|
203968
|
+
Object.keys(commandVariables.flags || {}).map((key) => `npm_config_${underscore(key).replace(/^no_/, "")}`).some((flag) => process.env[flag] !== void 0) && import("./ui-ZXHKYLCS.js").then(({ renderWarning: renderWarning2 }) => {
|
|
203967
203969
|
renderWarning2({
|
|
203968
203970
|
body: [
|
|
203969
203971
|
"NPM scripts require an extra",
|
|
@@ -204012,7 +204014,7 @@ ${explanation} in non-interactive terminal environments, such as a CI environmen
|
|
|
204012
204014
|
let flags = originalResult.flags, environmentsFileName = this.environmentsFilename();
|
|
204013
204015
|
if (!environmentsFileName)
|
|
204014
204016
|
return originalResult;
|
|
204015
|
-
let { environmentFilePath } = await import("./environments-
|
|
204017
|
+
let { environmentFilePath } = await import("./environments-II3QYMU3.js"), environmentFileExists = await environmentFilePath(environmentsFileName, { from: flags.path }), environments = [];
|
|
204016
204018
|
flags.environment && (environments = Array.isArray(flags.environment) ? flags.environment : [flags.environment]);
|
|
204017
204019
|
let environmentSpecified = environments.length > 0;
|
|
204018
204020
|
if (!environmentFileExists && !environmentSpecified || environmentSpecified && environments.length > 1)
|
|
@@ -204033,7 +204035,7 @@ ${explanation} in non-interactive terminal environments, such as a CI environmen
|
|
|
204033
204035
|
* is specified it will try to load a default environment.
|
|
204034
204036
|
*/
|
|
204035
204037
|
async loadEnvironmentForCommand(path4, environmentsFileName, specifiedEnvironment) {
|
|
204036
|
-
let { loadEnvironment: loadEnvironment2 } = await import("./environments-
|
|
204038
|
+
let { loadEnvironment: loadEnvironment2 } = await import("./environments-II3QYMU3.js");
|
|
204037
204039
|
return specifiedEnvironment ? { environment: await loadEnvironment2(specifiedEnvironment, environmentsFileName, { from: path4 }), isDefaultEnvironment: !1 } : { environment: await loadEnvironment2("default", environmentsFileName, { from: path4, silent: !0 }), isDefaultEnvironment: !0 };
|
|
204038
204040
|
}
|
|
204039
204041
|
};
|
|
@@ -204056,7 +204058,7 @@ function reportEnvironmentApplication(noDefaultsFlags, flagsWithEnvironments, en
|
|
|
204056
204058
|
if (Object.keys(changes).length === 0)
|
|
204057
204059
|
return;
|
|
204058
204060
|
let items = Object.entries(changes).map(([name, value]) => `${name}: ${value}`);
|
|
204059
|
-
import("./ui-
|
|
204061
|
+
import("./ui-ZXHKYLCS.js").then(({ renderInfo: renderInfo2 }) => {
|
|
204060
204062
|
renderInfo2({
|
|
204061
204063
|
headline: ["Using applicable flags from", { userInput: environmentName }, "environment:"],
|
|
204062
204064
|
body: [{ list: { items } }]
|
|
@@ -204107,7 +204109,7 @@ async function removeDuplicatedPlugins(config2) {
|
|
|
204107
204109
|
let plugins = Array.from(config2.plugins.values()), bundlePlugins = ["@shopify/app", "@shopify/plugin-cloudflare"], pluginsToRemove = plugins.filter((plugin) => bundlePlugins.includes(plugin.name));
|
|
204108
204110
|
if (pluginsToRemove.length > 0) {
|
|
204109
204111
|
let commandsToRun = pluginsToRemove.map((plugin) => ` - shopify plugins remove ${plugin.name}`).join(`
|
|
204110
|
-
`), { renderWarning: renderWarning2 } = await import("./ui-
|
|
204112
|
+
`), { renderWarning: renderWarning2 } = await import("./ui-ZXHKYLCS.js");
|
|
204111
204113
|
renderWarning2({
|
|
204112
204114
|
headline: `Unsupported plugins detected: ${pluginsToRemove.map((plugin) => plugin.name).join(", ")}`,
|
|
204113
204115
|
body: [
|
|
@@ -204129,20 +204131,20 @@ init_cjs_shims();
|
|
|
204129
204131
|
init_cjs_shims();
|
|
204130
204132
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
204131
204133
|
async function launchCLI(options) {
|
|
204132
|
-
let { isDevelopment: isDevelopment2 } = await import("./local-
|
|
204134
|
+
let { isDevelopment: isDevelopment2 } = await import("./local-G2BSQFFH.js"), { ShopifyConfig } = await import("./custom-oclif-loader-WGQ253VO.js"), oclifModule = await import("./lib-NYDMHWZM.js"), { run, flush, Errors: Errors2, settings } = oclifModule.default ?? oclifModule;
|
|
204133
204135
|
isDevelopment2() && (settings.debug = !0);
|
|
204134
204136
|
try {
|
|
204135
204137
|
let config2 = new ShopifyConfig({ root: fileURLToPath2(options.moduleURL) });
|
|
204136
204138
|
await config2.load(), options.lazyCommandLoader && config2.setLazyCommandLoader(options.lazyCommandLoader);
|
|
204137
204139
|
let argv = options.argv ?? process.argv.slice(2), passthroughIndex = argv.indexOf("--");
|
|
204138
204140
|
if ((passthroughIndex === -1 ? argv : argv.slice(0, passthroughIndex)).includes("--json-schema") || isTruthy(process.env.SHOPIFY_FLAG_JSON_SCHEMA)) {
|
|
204139
|
-
let { printCommandJsonSchema } = await import("./command-json-schema-
|
|
204141
|
+
let { printCommandJsonSchema } = await import("./command-json-schema-LA7ZVL4O.js");
|
|
204140
204142
|
await printCommandJsonSchema(config2, argv, options.lazyCommandLoader);
|
|
204141
204143
|
return;
|
|
204142
204144
|
}
|
|
204143
204145
|
await run(argv, config2), await flush();
|
|
204144
204146
|
} catch (error) {
|
|
204145
|
-
let { errorHandler } = await import("./error-handler-
|
|
204147
|
+
let { errorHandler } = await import("./error-handler-MENPWWOI.js");
|
|
204146
204148
|
await errorHandler(error);
|
|
204147
204149
|
let handledError = error;
|
|
204148
204150
|
return Errors2.handle({
|
|
@@ -204160,7 +204162,7 @@ var import_core3 = __toESM(require_lib());
|
|
|
204160
204162
|
async function exitIfOldNodeVersion(versions2 = process.versions) {
|
|
204161
204163
|
let nodeVersion = versions2.node, nodeMajorVersion = Number(nodeVersion.split(".")[0]);
|
|
204162
204164
|
if (nodeMajorVersion < 22) {
|
|
204163
|
-
let { renderError: renderError2 } = await import("./ui-
|
|
204165
|
+
let { renderError: renderError2 } = await import("./ui-ZXHKYLCS.js");
|
|
204164
204166
|
renderError2({
|
|
204165
204167
|
headline: "Upgrade to a supported Node version now.",
|
|
204166
204168
|
body: [
|
|
@@ -204187,7 +204189,7 @@ async function runCLI(options, launchCLI2 = launchCLI, argv = process.argv, env2
|
|
|
204187
204189
|
return setupEnvironmentVariables(options, argv, env2), options.runInCreateMode && await addInitToArgvWhenRunningCreateCLI(options, argv), forceNoColor(argv, env2), await exitIfOldNodeVersion(versions2), launchCLI2({ moduleURL: options.moduleURL, lazyCommandLoader: options.lazyCommandLoader });
|
|
204188
204190
|
}
|
|
204189
204191
|
async function addInitToArgvWhenRunningCreateCLI(options, argv = process.argv) {
|
|
204190
|
-
let { findUpAndReadPackageJson: findUpAndReadPackageJson2 } = await import("./node-package-manager-
|
|
204192
|
+
let { findUpAndReadPackageJson: findUpAndReadPackageJson2 } = await import("./node-package-manager-QET5FYFY.js"), { moduleDirectory: moduleDirectory2 } = await import("./path-RDYZ7Q5T.js"), name = (await findUpAndReadPackageJson2(moduleDirectory2(options.moduleURL))).content.name.replace("@shopify/create-", "");
|
|
204191
204193
|
if (argv.findIndex((arg) => arg.includes("init")) === -1) {
|
|
204192
204194
|
let initIndex2 = argv.findIndex((arg) => arg.match(new RegExp(`bin(\\/|\\\\)+(create-${name}|dev|run)`))) + 1;
|
|
204193
204195
|
argv.splice(initIndex2, 0, "init");
|
|
@@ -215322,7 +215324,7 @@ init_cjs_shims();
|
|
|
215322
215324
|
|
|
215323
215325
|
// ../cli-kit/dist/public/node/git.js
|
|
215324
215326
|
init_cjs_shims();
|
|
215325
|
-
var import_ignore3 = __toESM(require_ignore2());
|
|
215327
|
+
var import_semver = __toESM(require_semver()), import_ignore3 = __toESM(require_ignore2());
|
|
215326
215328
|
async function gitCommand(args, directory) {
|
|
215327
215329
|
try {
|
|
215328
215330
|
return (await execa("git", args, { cwd: directory })).stdout;
|
|
@@ -215385,6 +215387,35 @@ async function ensureGitIsPresentOrAbort() {
|
|
|
215385
215387
|
if (!await hasGit())
|
|
215386
215388
|
throw new AbortError("Git is necessary in the environment to continue", outputContent`Install ${outputToken.link("git", "https://git-scm.com/book/en/v2/Getting-Started-Installing-Git")}`);
|
|
215387
215389
|
}
|
|
215390
|
+
function parseGitVersion(versionOutput) {
|
|
215391
|
+
let match2 = /^git version (?<version>\d+\.\d+\.\d+)(?<suffix>[.\s-].*)?$/.exec(versionOutput.trim()), version = match2?.groups?.version;
|
|
215392
|
+
if (!version)
|
|
215393
|
+
return;
|
|
215394
|
+
let releaseCandidateNumber = /^(?:\.rc|-rc\.?)(?<number>\d+)(?:[.\s-].*)?$/.exec(match2.groups?.suffix ?? "")?.groups?.number;
|
|
215395
|
+
return releaseCandidateNumber ? `${version}-rc.${releaseCandidateNumber}` : version;
|
|
215396
|
+
}
|
|
215397
|
+
async function ensureGitVersionIsAtLeast(minimumVersion, options = {}) {
|
|
215398
|
+
let versionOutput = await inTemporaryDirectory((emptyGitDirectory) => captureGitVersionOutput(minimumVersion, { cwd: options.cwd, env: { GIT_DIR: emptyGitDirectory } })), installedVersion = parseGitVersion(versionOutput);
|
|
215399
|
+
if (!installedVersion)
|
|
215400
|
+
throw outputDebug(outputContent`Unrecognized git --version output: ${outputToken.raw(JSON.stringify(versionOutput.slice(0, 200)))}`), new AbortError("Couldn't determine the installed Git version.", `Install Git ${minimumVersion} or later, then try again.`);
|
|
215401
|
+
if ((0, import_semver.lt)(installedVersion, minimumVersion))
|
|
215402
|
+
throw new AbortError(`Git ${minimumVersion} or later is required, but version ${installedVersion} is installed.`, `Upgrade Git to version ${minimumVersion} or later, then try again.`);
|
|
215403
|
+
}
|
|
215404
|
+
async function captureGitVersionOutput(minimumVersion, execOptions) {
|
|
215405
|
+
let { captureOutput } = await import("./system-EHWOZQCE.js");
|
|
215406
|
+
try {
|
|
215407
|
+
return await captureOutput("git", ["--version"], execOptions);
|
|
215408
|
+
} catch (error) {
|
|
215409
|
+
if (error instanceof AbortError)
|
|
215410
|
+
throw error;
|
|
215411
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
215412
|
+
throw new AbortError(`Git ${minimumVersion} or later is required, but Git isn't installed.`, `Install Git ${minimumVersion} or later, then try again.`);
|
|
215413
|
+
let reason = error instanceof Error ? error.message : String(error);
|
|
215414
|
+
outputDebug(outputContent`Couldn't run git --version: ${outputToken.raw(reason)}`);
|
|
215415
|
+
let gitError = error instanceof Error && "stderr" in error && typeof error.stderr == "string" ? error.stderr.trim() : "";
|
|
215416
|
+
throw new AbortError(gitError ? `Couldn't run Git to check its version: ${gitError}` : "Couldn't run Git to check its version.", `Check that Git ${minimumVersion} or later is installed and can run, then try again.`);
|
|
215417
|
+
}
|
|
215418
|
+
}
|
|
215388
215419
|
async function insideGitDirectory(directory) {
|
|
215389
215420
|
return await hasGit() ? checkIfInsideGitDirectory(directory) : !1;
|
|
215390
215421
|
}
|
|
@@ -217373,7 +217404,7 @@ init_cjs_shims();
|
|
|
217373
217404
|
|
|
217374
217405
|
// ../cli-kit/dist/public/node/liquid.js
|
|
217375
217406
|
init_cjs_shims();
|
|
217376
|
-
var import_liquidjs = __toESM(require_liquid_node()
|
|
217407
|
+
var import_liquidjs = __toESM(require_liquid_node());
|
|
217377
217408
|
function renderLiquidTemplate(templateContent, data) {
|
|
217378
217409
|
let engine = new import_liquidjs.Liquid();
|
|
217379
217410
|
return engine.render(engine.parse(templateContent), data);
|
|
@@ -220472,7 +220503,7 @@ init_cjs_shims();
|
|
|
220472
220503
|
init_cjs_shims();
|
|
220473
220504
|
var import_core29 = __toESM(require_lib(), 1), blockingLevels = ["high", "medium", "low", "none"], appSecurityBlockingFlag = {
|
|
220474
220505
|
blocking: import_core29.Flags.custom({
|
|
220475
|
-
description: "The minimum finding severity that causes a non-zero exit code.",
|
|
220506
|
+
description: "The minimum finding severity that causes a non-zero exit code: high, medium, or low. Defaults to none, which never fails on findings.",
|
|
220476
220507
|
options: blockingLevels,
|
|
220477
220508
|
default: "none",
|
|
220478
220509
|
env: "SHOPIFY_FLAG_APP_SECURITY_BLOCKING"
|
|
@@ -220595,7 +220626,7 @@ Do not report:
|
|
|
220595
220626
|
`,
|
|
220596
220627
|
`---
|
|
220597
220628
|
id: APP_PROXY_LIQUID_INJECTION
|
|
220598
|
-
version:
|
|
220629
|
+
version: 3
|
|
220599
220630
|
severity: high
|
|
220600
220631
|
precedence: prefer-agent
|
|
220601
220632
|
---
|
|
@@ -220700,10 +220731,10 @@ Do not report:
|
|
|
220700
220731
|
- Protocol-only canonicalization concerns with no demonstrated app-local exploit path
|
|
220701
220732
|
- Test handlers
|
|
220702
220733
|
`,
|
|
220703
|
-
"---\nid: COMMITTED_SECRET\nversion:
|
|
220734
|
+
"---\nid: COMMITTED_SECRET\nversion: 4\nseverity: high\nprecedence: union\n---\n\n# Committed Secret\n\nInspect files skipped by deterministic secret scanning for committed credentials. Never quote or reproduce a secret; cite only the file and redacted credential kind, and recommend rotation.\n\nDo not report placeholders, public client identifiers (`SHOPIFY_API_KEY`, Stripe `pk_`), or files git confirms are untracked and ignored. Template env files (`.env.example`, `.sample`, `.template`, `.dist`) are findings only when they contain a known credential format.\n",
|
|
220704
220735
|
`---
|
|
220705
220736
|
id: CREDENTIAL_BROWSER_LEAKAGE
|
|
220706
|
-
version:
|
|
220737
|
+
version: 2
|
|
220707
220738
|
severity: high
|
|
220708
220739
|
precedence: prefer-agent
|
|
220709
220740
|
---
|
|
@@ -220714,7 +220745,7 @@ Trace credentials, access tokens, session tokens, and client secrets into loader
|
|
|
220714
220745
|
`,
|
|
220715
220746
|
`---
|
|
220716
220747
|
id: CREDENTIAL_LOG_LEAKAGE
|
|
220717
|
-
version:
|
|
220748
|
+
version: 2
|
|
220718
220749
|
severity: high
|
|
220719
220750
|
precedence: prefer-agent
|
|
220720
220751
|
---
|
|
@@ -221025,7 +221056,7 @@ Do not report:
|
|
|
221025
221056
|
`,
|
|
221026
221057
|
`---
|
|
221027
221058
|
id: DEPRECATED_SCRIPT_TAG_SCOPE
|
|
221028
|
-
version:
|
|
221059
|
+
version: 2
|
|
221029
221060
|
severity: medium
|
|
221030
221061
|
precedence: prefer-agent
|
|
221031
221062
|
---
|
|
@@ -221036,7 +221067,7 @@ Inspect parsed app scopes and JavaScript/TypeScript Admin API operations for dep
|
|
|
221036
221067
|
`,
|
|
221037
221068
|
`---
|
|
221038
221069
|
id: EOL_API_VERSION
|
|
221039
|
-
version:
|
|
221070
|
+
version: 2
|
|
221040
221071
|
severity: low
|
|
221041
221072
|
precedence: prefer-agent
|
|
221042
221073
|
---
|
|
@@ -221045,7 +221076,7 @@ precedence: prefer-agent
|
|
|
221045
221076
|
|
|
221046
221077
|
Inspect the selected \`shopify.app*.toml\` plus React Router \`app/shopify.server.*\` declarations. Shopify publishes quarterly versions in January, April, July, and October and supports each stable version for 12 months; the app security check allows a documented 30-day extension grace period before reporting it as end-of-life. Cite the exact declaration. For malformed config, computed \`ApiVersion\` values, or a Shopify-announced exceptional extension, inspect the source and current lifecycle policy rather than inferring from unrelated constants.
|
|
221047
221078
|
`,
|
|
221048
|
-
"---\nid: EXPIRING_OFFLINE_TOKEN\nversion:
|
|
221079
|
+
"---\nid: EXPIRING_OFFLINE_TOKEN\nversion: 2\nseverity: medium\nprecedence: prefer-agent\n---\n\n# Expiring Offline Token\n\nFor supported React Router apps, verify `expiringOfflineAccessTokens` is enabled and the selected session storage persists `expires`, `refreshToken`, and `refreshTokenExpires` metadata needed for refresh and rotation. `isOnline: false` selects an offline session; it does not disable token expiry and is not a finding. Report an explicit `expiringOfflineAccessTokens: false`. Treat absent or computed flags, custom storage, and ambiguous Prisma schemas as unresolved investigation: inspect storage adapters, migrations, and serialization before returning a clean result. Config-only and unsupported frameworks are handled by the runtime applicability boundary.\n",
|
|
221049
221080
|
`---
|
|
221050
221081
|
id: INSECURE_WEBHOOK_URL
|
|
221051
221082
|
version: 2
|
|
@@ -221060,17 +221091,24 @@ Inspect webhook destinations and OAuth redirect URLs in the selected Shopify app
|
|
|
221060
221091
|
"---\nid: LIQUID_UNSAFE_RENDER\nversion: 1\nseverity: medium\nprecedence: union\n---\n\n# Liquid Unsafe Render\n\nInspect only theme-extension Liquid/HTML files the parser could not analyze. Liquid output is not automatically HTML-escaped. Check the destination: use `escape`/`escape_once` for HTML text and ordinary attributes, `json` when embedding a value as JavaScript data, and `metafield_tag` only for supported rich metafield rendering in HTML content. HTML escaping is not sufficient for event handlers, `srcdoc`, or a `<script src>` URL; avoid merchant-controlled output there and validate any dynamic URL. An ordinary non-script `src` attribute is not itself an executable sink. `{% raw %}` suppresses Liquid parsing, so apparent output inside it is literal text. Follow rendered snippets and inspect ambiguous filters or parser failures before reporting.\n",
|
|
221061
221092
|
`---
|
|
221062
221093
|
id: METAFIELD_OFFLINE_TOKEN
|
|
221063
|
-
version:
|
|
221094
|
+
version: 2
|
|
221064
221095
|
severity: high
|
|
221065
221096
|
---
|
|
221066
221097
|
|
|
221067
221098
|
# Metafield Offline Token
|
|
221068
221099
|
|
|
221069
|
-
Trace metafield writes and determine
|
|
221100
|
+
Trace metafield and metaobject writes and determine their token provenance. Report a write that runs in an offline Admin API context that no verified request for the same shop authorizes: for example \`unauthenticated.admin(shop)\` or a stored offline session reached from an unauthenticated route, an unverified webhook or app proxy request, or a job whose shop or values come from request-controlled input.
|
|
221101
|
+
|
|
221102
|
+
An offline session returned by \`authenticate.admin(request)\` (the React Router SDK default when \`useOnlineTokens\` isn't set) is a verified, shop-bound context: Shopify verified the session token and the staff member's access to the app. Don't report a write only because its token is offline or because an online token would add user attribution or expiry. Report it when:
|
|
221103
|
+
|
|
221104
|
+
- the app defines its own per-user permission, for example an app-level role or allowlist check, and this write bypasses it. Name that permission.
|
|
221105
|
+
- request-controlled values reach an app-reserved (\`$app\`) metafield or metaobject that the app treats as trusted state and merchants can't edit themselves, for example a definition with \`access.admin = "merchant_read"\` or no merchant access, or billing, entitlement or feature-flag data. Writing to the \`$app\` namespace isn't safe by itself.
|
|
221106
|
+
|
|
221107
|
+
Confirm token provenance and compensating authorization before reporting.
|
|
221070
221108
|
`,
|
|
221071
221109
|
`---
|
|
221072
221110
|
id: MISSING_AUTHORIZATION_CHECK
|
|
221073
|
-
version:
|
|
221111
|
+
version: 3
|
|
221074
221112
|
severity: high
|
|
221075
221113
|
---
|
|
221076
221114
|
|
|
@@ -221127,6 +221165,16 @@ actions.
|
|
|
221127
221165
|
changes, direct URLs that survive permission downgrades, and backend actions
|
|
221128
221166
|
that remain callable after a feature is hidden or disabled in the UI.
|
|
221129
221167
|
|
|
221168
|
+
## Shopify embedded apps (React Router)
|
|
221169
|
+
|
|
221170
|
+
\`authenticate.admin(request)\` verifies the Shopify session token, so the caller is a staff member of that shop whom Shopify has granted access to this app. With offline tokens (the SDK default), Admin API calls use the app's granted scopes rather than the staff member's own permissions. That is Shopify's standard embedded app model, not a finding by itself. Report a handler only when it skips a concrete authorization boundary inside the app:
|
|
221171
|
+
|
|
221172
|
+
- The app defines its own roles, owners, or allowlists (for example a check on \`sessionToken.sub\`, \`onlineAccessInfo.associated_user\`, \`account_owner\`, or an app database role), and a handler that performs the same or a more privileged operation doesn't apply it. Compare each route's loader and action, and sibling routes.
|
|
221173
|
+
- A request-supplied identifier selects an app-owned record that belongs to another user of the app.
|
|
221174
|
+
- The app uses online tokens to respect staff permissions on some paths, but a privileged path falls back to an offline session.
|
|
221175
|
+
|
|
221176
|
+
If none of these applies, record the check as executed with no finding.
|
|
221177
|
+
|
|
221130
221178
|
## What to report
|
|
221131
221179
|
|
|
221132
221180
|
For each action that exposes a concrete unauthorized operation beyond authentication:
|
|
@@ -221530,7 +221578,7 @@ Do not report:
|
|
|
221530
221578
|
`,
|
|
221531
221579
|
`---
|
|
221532
221580
|
id: REQUEST_CONTROLLED_ADMIN_CONTEXT
|
|
221533
|
-
version:
|
|
221581
|
+
version: 4
|
|
221534
221582
|
severity: high
|
|
221535
221583
|
precedence: prefer-agent
|
|
221536
221584
|
---
|
|
@@ -222129,17 +222177,7 @@ Do not report:
|
|
|
222129
222177
|
- \`exec()\` with literal strings (no user input)
|
|
222130
222178
|
- Shell calls with properly escaped arguments
|
|
222131
222179
|
`,
|
|
222132
|
-
|
|
222133
|
-
id: STATIC_FRAME_ANCESTORS
|
|
222134
|
-
version: 1
|
|
222135
|
-
severity: high
|
|
222136
|
-
precedence: prefer-agent
|
|
222137
|
-
---
|
|
222138
|
-
|
|
222139
|
-
# Static Frame Ancestors
|
|
222140
|
-
|
|
222141
|
-
Inspect embedded-app Content-Security-Policy construction. Report wildcard or static cross-shop frame-ancestors policies; accept a policy derived safely for the authenticated shop plus Shopify Admin.
|
|
222142
|
-
`,
|
|
222180
|
+
"---\nid: STATIC_FRAME_ANCESTORS\nversion: 2\nseverity: high\nprecedence: prefer-agent\n---\n\n# Static Frame Ancestors\n\nInspect embedded-app Content-Security-Policy construction, including headers that app code sets after or instead of the SDK's. Report wildcard or static cross-shop frame-ancestors policies, such as `*`, `https:`, `*.myshopify.com`, or a fixed list of shop domains, whether the value is written literally or built from variables. Accept a policy derived safely for the shop plus Shopify Admin.\n\nThe React Router SDK's `addDocumentResponseHeaders` (from `shopifyApp()`, usually called in `entry.server`) is the accepted pattern: it sets `frame-ancestors` to the sanitized request shop plus Shopify Admin origins, including Shopify-operated development admin origins. Don't report it unless app code overrides or extends its header.\n",
|
|
222143
222181
|
`---
|
|
222144
222182
|
id: TEXT_SETTING_HTML_SMUGGLING
|
|
222145
222183
|
version: 2
|
|
@@ -222334,7 +222372,7 @@ Do not report:
|
|
|
222334
222372
|
`,
|
|
222335
222373
|
`---
|
|
222336
222374
|
id: UNAUTHENTICATED_ENDPOINT
|
|
222337
|
-
version:
|
|
222375
|
+
version: 3
|
|
222338
222376
|
severity: high
|
|
222339
222377
|
precedence: union
|
|
222340
222378
|
---
|
|
@@ -222471,7 +222509,7 @@ pack instructions.
|
|
|
222471
222509
|
`,
|
|
222472
222510
|
`---
|
|
222473
222511
|
id: UNSAFE_INNERHTML
|
|
222474
|
-
version:
|
|
222512
|
+
version: 3
|
|
222475
222513
|
severity: high
|
|
222476
222514
|
precedence: union
|
|
222477
222515
|
---
|
|
@@ -222745,7 +222783,10 @@ For each check:
|
|
|
222745
222783
|
5. Keep the check \`id\` and \`version\` exactly as they appear in {{AGENT_CHECKS_PATH}}.
|
|
222746
222784
|
6. Include concise evidence citations. Never include a detected secret value or unnecessary personal data.
|
|
222747
222785
|
|
|
222748
|
-
A check with no verified issue must not produce a fabricated finding.
|
|
222786
|
+
A check with no verified issue must not produce a fabricated finding. Choose the status from what you were able to investigate, not from whether you can prove a negative:
|
|
222787
|
+
|
|
222788
|
+
- \`executed\`: you traced the paths the check directs you to and found no concrete issue. This includes code that follows the safe pattern the check or its \`docs_url\` describes. A candidate is ruled out when the code establishes the boundary the check asks about, even if you can't rule out hypothetical policies or requirements that the repository doesn't define.
|
|
222789
|
+
- \`unresolved\`: you couldn't complete the investigation, for example because required code was unreadable, out of scope, or outside the repository and you couldn't inspect it, or you found a specific candidate whose boundary you could neither establish nor show to be missing. Name the candidate's file and line, or the missing input, in the reason.
|
|
222749
222790
|
|
|
222750
222791
|
### 4. Write one findings document
|
|
222751
222792
|
|
|
@@ -222789,7 +222830,7 @@ Write a single JSON document that covers every check you ran:
|
|
|
222789
222830
|
- \`status\` is one of:
|
|
222790
222831
|
- \`executed\`: you investigated the check, whether or not it produced findings.
|
|
222791
222832
|
- \`not_applicable\`: the capability the check covers is absent. It can't have findings.
|
|
222792
|
-
- \`unresolved\`: you couldn't
|
|
222833
|
+
- \`unresolved\`: you couldn't complete the investigation, or you named a specific candidate whose boundary is still unclear. An unresolved check didn't pass; never describe it as passing.
|
|
222793
222834
|
- \`not_applicable\` and \`unresolved\` require a \`reason\` with a short \`code\` and a \`message\`.
|
|
222794
222835
|
- Each finding needs \`file\`, \`line\` (1 or greater), \`message\`, and at least one \`evidence\` item with \`file\`, \`line\`, and \`quote\`.
|
|
222795
222836
|
- Optional finding fields: \`snippet\`, \`confidence\` (\`high\`, \`medium\`, or \`low\`), \`reasoning\`, and \`suppression\` (\`{"justification": "..."}\`).
|
|
@@ -222871,13 +222912,18 @@ var UNTRUSTED_REPOSITORY_PROTECTIONS = {
|
|
|
222871
222912
|
bareRepository: { args: ["-c", "safe.bareRepository=explicit"] },
|
|
222872
222913
|
// A partial clone fetches a missing object on demand, running the repository's transport commands.
|
|
222873
222914
|
lazyFetch: { env: { GIT_NO_LAZY_FETCH: "1" } },
|
|
222874
|
-
// An empty allow-list refuses every transport, for Git versions that predate GIT_NO_LAZY_FETCH.
|
|
222875
|
-
transports: { env: { GIT_ALLOW_PROTOCOL: "" } }
|
|
222876
|
-
|
|
222915
|
+
// An empty allow-list refuses every named transport, for Git versions that predate GIT_NO_LAZY_FETCH.
|
|
222916
|
+
transports: { env: { GIT_ALLOW_PROTOCOL: "" } },
|
|
222917
|
+
// The allow-list still holds an empty name, which a remote's helper gets from an empty `vcs` or a URL that starts
|
|
222918
|
+
// with `::`. Git runs that helper as `git remote-`, which falls back to the repository's `remote-` alias. The empty
|
|
222919
|
+
// value replaces the alias, for Git versions that predate GIT_NO_LAZY_FETCH.
|
|
222920
|
+
emptyRemoteHelper: { args: ["-c", "alias.remote-="] }
|
|
222921
|
+
}, minimumAppSecurityGitVersion = "2.38.0", protections = Object.values(UNTRUSTED_REPOSITORY_PROTECTIONS), protectionArguments = protections.flatMap((protection) => protection.args ?? []);
|
|
222877
222922
|
function protectionEnvironment() {
|
|
222878
222923
|
return Object.fromEntries(protections.flatMap((protection) => Object.entries(protection.env ?? {})));
|
|
222879
222924
|
}
|
|
222880
222925
|
async function runGit(directory, args) {
|
|
222926
|
+
await ensureGitVersionIsAtLeast(minimumAppSecurityGitVersion, { cwd: directory });
|
|
222881
222927
|
try {
|
|
222882
222928
|
let result = await captureOutputWithExitCode("git", [...protectionArguments, ...args], {
|
|
222883
222929
|
cwd: directory,
|
|
@@ -223182,11 +223228,11 @@ var CHECK_DOCS_BASE_URL = "https://shopify.dev/docs/apps/build/security/app-secu
|
|
|
223182
223228
|
},
|
|
223183
223229
|
{
|
|
223184
223230
|
id: "METAFIELD_OFFLINE_TOKEN",
|
|
223185
|
-
title: "Metafield write
|
|
223231
|
+
title: "Metafield write in an unverified offline token context",
|
|
223186
223232
|
severity: "high",
|
|
223187
223233
|
points: -15,
|
|
223188
|
-
description: "
|
|
223189
|
-
fix: "
|
|
223234
|
+
description: "Investigates metafield and metaobject writes made with an offline Admin API context that no verified request for the same shop authorizes.",
|
|
223235
|
+
fix: "Make the write from a request verified with authenticate.admin(request), or derive the shop and values from a verified source.",
|
|
223190
223236
|
guide: "https://shopify.dev/docs/apps/build/authentication-authorization/access-token-types/online-access-tokens",
|
|
223191
223237
|
docsUrl: `${CHECK_DOCS_BASE_URL}/metafield-offline-token`
|
|
223192
223238
|
},
|
|
@@ -223326,7 +223372,7 @@ var CHECK_DOCS_BASE_URL = "https://shopify.dev/docs/apps/build/security/app-secu
|
|
|
223326
223372
|
title: "Embedded app frame-ancestors uses a wildcard",
|
|
223327
223373
|
severity: "high",
|
|
223328
223374
|
points: -12,
|
|
223329
|
-
description: "Detects
|
|
223375
|
+
description: "Detects wildcard or static cross-shop frame-ancestors policies in embedded app code, whether written literally or built from variables.",
|
|
223330
223376
|
fix: "Restrict frame-ancestors to Shopify Admin and the authenticated shop origin.",
|
|
223331
223377
|
guide: "https://shopify.dev/docs/apps/build/security/set-up-iframe-protection",
|
|
223332
223378
|
requires: "embedded_app",
|
|
@@ -223525,7 +223571,8 @@ Rules:
|
|
|
223525
223571
|
- Record unresolved and not_applicable checks with a reason: { "code": "...", "message": "..." }.
|
|
223526
223572
|
- A not_applicable check can't have findings.
|
|
223527
223573
|
- An unsupported or unresolved check didn't pass. Never describe it as passing or complete.
|
|
223528
|
-
- If you can't prove exploitability or affected authority, record the check as unresolved
|
|
223574
|
+
- If you can't prove exploitability or affected authority for a specific candidate, don't report a finding: record the check as unresolved and name the candidate in the reason.
|
|
223575
|
+
- If you investigated and the code establishes the boundary the check asks about, record the check as executed. An unprovable hypothetical is not a reason to leave a check unresolved.
|
|
223529
223576
|
- Don't report things you couldn't confirm \u2014 uncertainty is not a finding.`, catalogEntry = (checkId) => {
|
|
223530
223577
|
let entry = RULE_CATALOG.find((candidate) => candidate.id === checkId);
|
|
223531
223578
|
if (!entry)
|
|
@@ -223872,12 +223919,13 @@ async function listTrackedFiles(directory) {
|
|
|
223872
223919
|
return splitNullSeparated(listed.stdout);
|
|
223873
223920
|
}
|
|
223874
223921
|
async function listNestedRepository(directory) {
|
|
223922
|
+
let stats;
|
|
223875
223923
|
try {
|
|
223876
|
-
|
|
223877
|
-
return stats.isDirectory() || stats.isFile() ? await listGitIgnoredPaths(directory) : { status: "failed" };
|
|
223924
|
+
stats = lstatSync2(joinPath(directory, ".git"));
|
|
223878
223925
|
} catch (error) {
|
|
223879
223926
|
return isMissingFilesystemEntry(error) ? void 0 : { status: "failed" };
|
|
223880
223927
|
}
|
|
223928
|
+
return stats.isDirectory() || stats.isFile() ? listGitIgnoredPaths(directory) : { status: "failed" };
|
|
223881
223929
|
}
|
|
223882
223930
|
function splitNullSeparated(output) {
|
|
223883
223931
|
return output.split("\0").filter((path4) => path4 !== "");
|
|
@@ -224270,6 +224318,13 @@ function readRepositoryFile(absolutePath) {
|
|
|
224270
224318
|
let located = configuredReader().explicitInputs.has(path4) ? explicitInputPath(path4) : containedRepositoryPath(path4), result = located.path ? readBoundedFile(located.path) : located.failure;
|
|
224271
224319
|
return repositoryFileCache.set(path4, result), result.ok || recordSkippedFile(path4, result), result;
|
|
224272
224320
|
}
|
|
224321
|
+
function readFileContainedBy(directory, path4) {
|
|
224322
|
+
let inspected = inspectRepositoryPath(directory, path4);
|
|
224323
|
+
if (inspected.status === "missing")
|
|
224324
|
+
return;
|
|
224325
|
+
let result = inspected.status === "file" ? readBoundedFile(inspected.path) : repositoryPathFailure(inspected.reason);
|
|
224326
|
+
return result.ok || recordSkippedFile(joinPath(directory, path4), result), result;
|
|
224327
|
+
}
|
|
224273
224328
|
function readRepositoryText(absolutePath) {
|
|
224274
224329
|
let result = readRepositoryFile(absolutePath);
|
|
224275
224330
|
return result.ok ? result.content.toString() : void 0;
|
|
@@ -224372,15 +224427,14 @@ function isProbablyBinary(content) {
|
|
|
224372
224427
|
return sample.length > 0 && suspiciousControlBytes / sample.length > 0.1;
|
|
224373
224428
|
}
|
|
224374
224429
|
function findSensitiveFiles(appRoot, repositoryFiles, selectedAppConfigPath) {
|
|
224375
|
-
return repositoryFiles.filter(isSensitiveFile).filter((path4) => !LOCKFILE_MANAGERS.has(path4)).filter((path4) => !isValidFormatAppConfigurationFileName(basename(path4)) || path4 === selectedAppConfigPath).flatMap((path4) => {
|
|
224430
|
+
return repositoryFiles.filter(isSensitiveFile).filter((path4) => !LOCKFILE_MANAGERS.has(basename(path4))).filter((path4) => !isValidFormatAppConfigurationFileName(basename(path4)) || path4 === selectedAppConfigPath).flatMap((path4) => {
|
|
224376
224431
|
let absolutePath = joinPath(appRoot, path4), result = readRepositoryFile(absolutePath);
|
|
224377
224432
|
return result.ok ? isProbablyBinary(result.content) ? [] : [{ path: path4, absolutePath, ext: extname(path4), content: result.content.toString() }] : [{ path: path4, absolutePath, ext: extname(path4), content: void 0 }];
|
|
224378
224433
|
});
|
|
224379
224434
|
}
|
|
224380
|
-
function
|
|
224435
|
+
function dependencyAutomationRoot(appRoot) {
|
|
224381
224436
|
let marker = findRepositoryMarker(appRoot);
|
|
224382
|
-
|
|
224383
|
-
return marker.status === "ambiguous" ? marker.reason : marker.directory === appRoot ? void 0 : "App root is nested below a parent Git repository";
|
|
224437
|
+
return marker.status === "ambiguous" ? { unresolvedReason: marker.reason } : { directory: marker.status === "found" ? marker.directory : appRoot };
|
|
224384
224438
|
}
|
|
224385
224439
|
function findDependencyAutomationInputs(appRoot, gatheredPaths) {
|
|
224386
224440
|
let canonicalRoot;
|
|
@@ -224390,25 +224444,28 @@ function findDependencyAutomationInputs(appRoot, gatheredPaths) {
|
|
|
224390
224444
|
} catch (error) {
|
|
224391
224445
|
return { files: [], unresolvedReason: inspectErrorReason("app root", error) };
|
|
224392
224446
|
}
|
|
224393
|
-
let
|
|
224394
|
-
if (
|
|
224395
|
-
return { files: [], unresolvedReason:
|
|
224396
|
-
let gathered = new Set(gatheredPaths), files = [], unresolvedReason;
|
|
224397
|
-
for (let
|
|
224398
|
-
|
|
224399
|
-
|
|
224400
|
-
let absolutePath = joinPath(canonicalRoot, relative), result = readRepositoryFile(absolutePath);
|
|
224401
|
-
if (!result.ok) {
|
|
224402
|
-
unresolvedReason ??= result.reason === "too_large" ? `${relative} is too large to inspect` : result.detail ?? `Could not read ${relative}`;
|
|
224447
|
+
let configurationRoot = dependencyAutomationRoot(canonicalRoot);
|
|
224448
|
+
if ("unresolvedReason" in configurationRoot)
|
|
224449
|
+
return { files: [], unresolvedReason: configurationRoot.unresolvedReason };
|
|
224450
|
+
let repositoryRoot = configurationRoot.directory, { scanDirectories } = configuredReader(), isScanned = (absolutePath) => repositoryRoot === canonicalRoot || scanDirectories.some((directory) => isSubpath(directory, absolutePath)), gathered = new Set(gatheredPaths), files = [], unresolvedReason;
|
|
224451
|
+
for (let configurationPath of DEPENDENCY_AUTOMATION_CONFIG_PATHS) {
|
|
224452
|
+
let absolutePath = joinPath(repositoryRoot, configurationPath), relative = normalizePath(relativePath(canonicalRoot, absolutePath)), scanned = isScanned(absolutePath);
|
|
224453
|
+
if (scanned && !gathered.has(relative))
|
|
224403
224454
|
continue;
|
|
224455
|
+
let result = scanned ? readRepositoryFile(absolutePath) : readFileContainedBy(repositoryRoot, configurationPath);
|
|
224456
|
+
if (result !== void 0) {
|
|
224457
|
+
if (!result.ok) {
|
|
224458
|
+
unresolvedReason ??= result.reason === "too_large" ? `${relative} is too large to inspect` : result.detail ?? `Could not read ${relative}`;
|
|
224459
|
+
continue;
|
|
224460
|
+
}
|
|
224461
|
+
files.push({
|
|
224462
|
+
path: relative,
|
|
224463
|
+
absolutePath,
|
|
224464
|
+
ext: extname(relative),
|
|
224465
|
+
content: result.content.toString()
|
|
224466
|
+
});
|
|
224467
|
+
break;
|
|
224404
224468
|
}
|
|
224405
|
-
files.push({
|
|
224406
|
-
path: relative,
|
|
224407
|
-
absolutePath,
|
|
224408
|
-
ext: extname(relative),
|
|
224409
|
-
content: result.content.toString()
|
|
224410
|
-
});
|
|
224411
|
-
break;
|
|
224412
224469
|
}
|
|
224413
224470
|
return files.length > 0 ? { files } : { files, ...unresolvedReason ? { unresolvedReason } : {} };
|
|
224414
224471
|
}
|
|
@@ -224454,6 +224511,7 @@ function findManifests(appRoot, discoveredPaths) {
|
|
|
224454
224511
|
|
|
224455
224512
|
// ../app/dist/cli/services/app-security-engine/capabilities/detect.js
|
|
224456
224513
|
init_cjs_shims();
|
|
224514
|
+
var REACT_ROUTER_PACKAGE = "@shopify/shopify-app-react-router";
|
|
224457
224515
|
function detectCapabilities(appToml, extensions, sourceFiles, appTomls = appToml ? [appToml] : []) {
|
|
224458
224516
|
let themeExtension = extensions.some((extension) => extension.type === "theme"), appEmbed = extensions.some((extension) => extension.type === "theme" && hasAppEmbedBlock(extension)), embeddedApp = appTomls.some((configuration) => configuration.raw.embedded === !0), scriptTags = sourceFiles.some((file) => file.content ? /script[_-]?tags?|ScriptTag/i.test(file.content) : !1), storefrontMetafieldWrites = sourceFiles.some((file) => file.content ? /metafields?Set|metafields?\/.*(?:POST|PUT|create|update)|write.*metafield|metafield.*write/i.test(file.content) : !1), hasBackend = sourceFiles.some(detectRouteDefinitions);
|
|
224459
224517
|
return {
|
|
@@ -224469,11 +224527,49 @@ function detectCapabilities(appToml, extensions, sourceFiles, appTomls = appToml
|
|
|
224469
224527
|
checkout_extension: extensions.some((extension) => extension.type === "checkout_ui" || extension.type === "checkout_ui_extension")
|
|
224470
224528
|
};
|
|
224471
224529
|
}
|
|
224472
|
-
function
|
|
224473
|
-
let
|
|
224474
|
-
|
|
224475
|
-
|
|
224476
|
-
|
|
224530
|
+
function detectReactRouterRoots(manifests, candidates, otherAppDirectories = []) {
|
|
224531
|
+
let declaringManifests = manifests.filter((manifest) => manifest.dependencies[REACT_ROUTER_PACKAGE] !== void 0 || manifest.devDependencies?.[REACT_ROUTER_PACKAGE] !== void 0);
|
|
224532
|
+
if (declaringManifests.length === 0)
|
|
224533
|
+
return [];
|
|
224534
|
+
let candidatePaths = candidates.map((candidate) => candidate.path);
|
|
224535
|
+
return [.../* @__PURE__ */ new Set([".", ...declaringManifests.map((manifest) => dirname(manifest.path))])].filter((root) => hasReactRouterStructure(root, candidatePaths)).filter((root) => !belongsToOtherApp(root, otherAppDirectories)).sort();
|
|
224536
|
+
}
|
|
224537
|
+
function isReactRouterServerPath(root, path4) {
|
|
224538
|
+
let pathInRoot = pathWithinRoot(root, path4);
|
|
224539
|
+
return pathInRoot !== void 0 && /^app\/shopify\.server\.[cm]?[jt]sx?$/.test(pathInRoot);
|
|
224540
|
+
}
|
|
224541
|
+
function isReactRouterSourcePath(path4, reactRouterRoots, otherAppDirectories) {
|
|
224542
|
+
let otherAppCode = otherAppCodeDirectories(otherAppDirectories).filter((directory) => !isInsideReactRouterRoot(directory, reactRouterRoots));
|
|
224543
|
+
return (!climbsOutOfDirectory(path4) || reactRouterRoots.some((root) => pathWithinRoot(root, path4) !== void 0)) && !otherAppCode.some((directory) => pathWithinRoot(directory, path4) !== void 0);
|
|
224544
|
+
}
|
|
224545
|
+
function isInsideReactRouterRoot(directory, reactRouterRoots) {
|
|
224546
|
+
return reactRouterRoots.some((root) => root === "." ? !climbsOutOfDirectory(directory) : directory === root || pathWithinRoot(root, directory) !== void 0);
|
|
224547
|
+
}
|
|
224548
|
+
function climbsOutOfDirectory(path4) {
|
|
224549
|
+
return path4 === ".." || path4.startsWith("../");
|
|
224550
|
+
}
|
|
224551
|
+
function pathWithinRoot(root, path4) {
|
|
224552
|
+
if (root === ".")
|
|
224553
|
+
return path4;
|
|
224554
|
+
if (!path4.startsWith(`${root}/`))
|
|
224555
|
+
return;
|
|
224556
|
+
let pathInRoot = path4.slice(root.length + 1);
|
|
224557
|
+
return climbsOutOfDirectory(pathInRoot) ? void 0 : pathInRoot;
|
|
224558
|
+
}
|
|
224559
|
+
function hasReactRouterStructure(root, paths) {
|
|
224560
|
+
return paths.some((path4) => pathWithinRoot(root, path4)?.startsWith("app/routes/")) && paths.some((path4) => isReactRouterServerPath(root, path4));
|
|
224561
|
+
}
|
|
224562
|
+
function belongsToOtherApp(root, otherAppDirectories) {
|
|
224563
|
+
return root === "." ? !1 : otherAppDirectories.includes(root) || otherAppCodeDirectories(otherAppDirectories).some((directory) => root === directory || pathWithinRoot(directory, root) !== void 0);
|
|
224564
|
+
}
|
|
224565
|
+
function otherAppCodeDirectories(otherAppDirectories) {
|
|
224566
|
+
return otherAppDirectories.flatMap((directory) => isAncestorOfAppDirectory(directory) ? [`${directory}/app`, `${directory}/web`] : [directory]);
|
|
224567
|
+
}
|
|
224568
|
+
function isAncestorOfAppDirectory(directory) {
|
|
224569
|
+
return directory.split("/").every((segment) => segment === "..");
|
|
224570
|
+
}
|
|
224571
|
+
function detectProject(extensions, candidates, reactRouterRoots) {
|
|
224572
|
+
let reactRouter = reactRouterRoots.length > 0, themeExtensions = extensions.filter((extension) => extension.type === "theme"), themeExtension = themeExtensions.length > 0, themePaths = new Set(themeExtensions.flatMap((extension) => extension.files.map((file) => file.path))), hasSources = candidates.length > 0, surface;
|
|
224477
224573
|
reactRouter && themeExtension ? surface = "mixed" : reactRouter ? surface = "react_router" : themeExtension && candidates.some((candidate) => !themePaths.has(candidate.path)) ? surface = "mixed" : themeExtension ? surface = "theme_app_extension" : hasSources ? surface = "unknown" : surface = "config_only";
|
|
224478
224574
|
let framework;
|
|
224479
224575
|
reactRouter ? framework = "react_router" : surface === "config_only" || surface === "theme_app_extension" ? framework = "none" : surface === "mixed" ? framework = "mixed" : framework = "unknown";
|
|
@@ -225133,11 +225229,11 @@ function scanEolApiVersions(context, referenceDate = /* @__PURE__ */ new Date())
|
|
|
225133
225229
|
]);
|
|
225134
225230
|
if (context.detection.framework !== "react_router")
|
|
225135
225231
|
return configIssues;
|
|
225136
|
-
let sourceIssues = context.sourceFiles.flatMap((file) => scanReactRouterApiVersion(file, referenceDate));
|
|
225232
|
+
let sourceIssues = context.sourceFiles.flatMap((file) => scanReactRouterApiVersion(file, context.reactRouterRoots, referenceDate));
|
|
225137
225233
|
return [...configIssues, ...sourceIssues];
|
|
225138
225234
|
}
|
|
225139
|
-
function scanReactRouterApiVersion(file, referenceDate) {
|
|
225140
|
-
if (!file.content ||
|
|
225235
|
+
function scanReactRouterApiVersion(file, reactRouterRoots, referenceDate) {
|
|
225236
|
+
if (!file.content || !reactRouterRoots.some((root) => isReactRouterServerPath(root, file.path)))
|
|
225141
225237
|
return [];
|
|
225142
225238
|
let content = maskStringsExceptVersions(stripComments4(file.content));
|
|
225143
225239
|
return [
|
|
@@ -226082,7 +226178,7 @@ var JAVASCRIPT_EXTENSIONS6 = [".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx", ".mt
|
|
|
226082
226178
|
configRule(missingComplianceWebhooks),
|
|
226083
226179
|
{
|
|
226084
226180
|
id: "MISSING_DEPENDENCY_SECURITY_AUTOMATION",
|
|
226085
|
-
version:
|
|
226181
|
+
version: 2,
|
|
226086
226182
|
lifecycle: "active",
|
|
226087
226183
|
analysisMode: "structured_config",
|
|
226088
226184
|
target: "dependency_automation",
|
|
@@ -226090,7 +226186,7 @@ var JAVASCRIPT_EXTENSIONS6 = [".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx", ".mt
|
|
|
226090
226186
|
},
|
|
226091
226187
|
{
|
|
226092
226188
|
id: "EOL_API_VERSION",
|
|
226093
|
-
version:
|
|
226189
|
+
version: 2,
|
|
226094
226190
|
lifecycle: "active",
|
|
226095
226191
|
analysisMode: "regex",
|
|
226096
226192
|
target: "config_and_source",
|
|
@@ -226098,16 +226194,16 @@ var JAVASCRIPT_EXTENSIONS6 = [".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx", ".mt
|
|
|
226098
226194
|
runner: (context) => scanEolApiVersions(context)
|
|
226099
226195
|
},
|
|
226100
226196
|
{
|
|
226101
|
-
...jsCheck("EXPIRING_OFFLINE_TOKEN", (context) => scanExpiringOfflineTokens(context)),
|
|
226197
|
+
...jsCheck("EXPIRING_OFFLINE_TOKEN", (context) => scanExpiringOfflineTokens(context), "source", 2),
|
|
226102
226198
|
extensions: [...JAVASCRIPT_EXTENSIONS6, ".prisma"]
|
|
226103
226199
|
},
|
|
226104
226200
|
{
|
|
226105
|
-
...jsCheck("UNAUTHENTICATED_ENDPOINT", (context) => scanUnauthenticatedEndpoints(context.sourceFiles), "source",
|
|
226201
|
+
...jsCheck("UNAUTHENTICATED_ENDPOINT", (context) => scanUnauthenticatedEndpoints(context.sourceFiles), "source", 3),
|
|
226106
226202
|
requires: "has_backend"
|
|
226107
226203
|
},
|
|
226108
|
-
jsCheck("REQUEST_CONTROLLED_ADMIN_CONTEXT", (context) => scanRequestControlledAdminContext(context.sourceFiles), "source",
|
|
226204
|
+
jsCheck("REQUEST_CONTROLLED_ADMIN_CONTEXT", (context) => scanRequestControlledAdminContext(context.sourceFiles), "source", 4),
|
|
226109
226205
|
{
|
|
226110
|
-
...configRule(deprecatedScriptTagScope),
|
|
226206
|
+
...configRule(deprecatedScriptTagScope, 2),
|
|
226111
226207
|
target: "config_and_source",
|
|
226112
226208
|
analysisMode: "regex",
|
|
226113
226209
|
extensions: JAVASCRIPT_EXTENSIONS6,
|
|
@@ -226119,14 +226215,14 @@ var JAVASCRIPT_EXTENSIONS6 = [".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx", ".mt
|
|
|
226119
226215
|
configRule(insecureWebhookUrl, 2),
|
|
226120
226216
|
{
|
|
226121
226217
|
id: "COMMITTED_SECRET",
|
|
226122
|
-
version:
|
|
226218
|
+
version: 4,
|
|
226123
226219
|
lifecycle: "active",
|
|
226124
226220
|
analysisMode: "regex",
|
|
226125
226221
|
target: "secrets",
|
|
226126
226222
|
runner: (context) => scanCommittedSecrets(context.sensitiveFiles, context.appRoot, context.gitIgnoreListing)
|
|
226127
226223
|
},
|
|
226128
|
-
jsCheck("CREDENTIAL_LOG_LEAKAGE", (context) => scanCredentialLogLeakage(context.sourceFiles)),
|
|
226129
|
-
jsCheck("CREDENTIAL_BROWSER_LEAKAGE", (context) => scanCredentialBrowserLeakage(context.sourceFiles)),
|
|
226224
|
+
jsCheck("CREDENTIAL_LOG_LEAKAGE", (context) => scanCredentialLogLeakage(context.sourceFiles), "source", 2),
|
|
226225
|
+
jsCheck("CREDENTIAL_BROWSER_LEAKAGE", (context) => scanCredentialBrowserLeakage(context.sourceFiles), "source", 2),
|
|
226130
226226
|
{
|
|
226131
226227
|
id: "LIQUID_UNSAFE_RENDER",
|
|
226132
226228
|
version: 1,
|
|
@@ -226138,16 +226234,16 @@ var JAVASCRIPT_EXTENSIONS6 = [".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx", ".mt
|
|
|
226138
226234
|
runner: (context) => liquidRunner(context, "LIQUID_UNSAFE_RENDER")
|
|
226139
226235
|
},
|
|
226140
226236
|
{
|
|
226141
|
-
...jsCheck("UNSAFE_INNERHTML", unsafeInnerHtmlRunner, "source_and_theme",
|
|
226237
|
+
...jsCheck("UNSAFE_INNERHTML", unsafeInnerHtmlRunner, "source_and_theme", 3),
|
|
226142
226238
|
analysisMode: "regex",
|
|
226143
226239
|
extensions: [...JAVASCRIPT_EXTENSIONS6, ".liquid", ".html"]
|
|
226144
226240
|
},
|
|
226145
226241
|
{
|
|
226146
|
-
...jsCheck("APP_PROXY_LIQUID_INJECTION", (context) => scanAppProxyLiquidInjection(context.sourceFiles), "source",
|
|
226242
|
+
...jsCheck("APP_PROXY_LIQUID_INJECTION", (context) => scanAppProxyLiquidInjection(context.sourceFiles), "source", 3),
|
|
226147
226243
|
requires: "app_proxy"
|
|
226148
226244
|
},
|
|
226149
226245
|
{
|
|
226150
|
-
...jsCheck("STATIC_FRAME_ANCESTORS", (context) => scanStaticFrameAncestors(context.sourceFiles), "app_source"),
|
|
226246
|
+
...jsCheck("STATIC_FRAME_ANCESTORS", (context) => scanStaticFrameAncestors(context.sourceFiles), "app_source", 2),
|
|
226151
226247
|
requires: "embedded_app"
|
|
226152
226248
|
}
|
|
226153
226249
|
];
|
|
@@ -226255,8 +226351,11 @@ function appSourceFiles(context) {
|
|
|
226255
226351
|
let themePaths = new Set(themeFiles(context).map((file) => file.path));
|
|
226256
226352
|
return context.sourceFiles.filter((file) => !themePaths.has(file.path));
|
|
226257
226353
|
}
|
|
226354
|
+
function isReactRouterFilePath(path4, context) {
|
|
226355
|
+
return context.detection.framework !== "react_router" || isReactRouterSourcePath(path4, context.reactRouterRoots, context.otherAppDirectories);
|
|
226356
|
+
}
|
|
226258
226357
|
function reactRouterFiles(context) {
|
|
226259
|
-
return appSourceFiles(context);
|
|
226358
|
+
return appSourceFiles(context).filter((file) => isReactRouterFilePath(file.path, context));
|
|
226260
226359
|
}
|
|
226261
226360
|
function selectedFiles(definition, context) {
|
|
226262
226361
|
let configurations = context.appTomls.map((toml) => relativePath(context.appRoot, toml.path).replace(/\\/g, "/"));
|
|
@@ -226363,8 +226462,8 @@ function manifestHasDependencies(manifest) {
|
|
|
226363
226462
|
return Object.keys(manifest.dependencies).length > 0 || Object.keys(manifest.devDependencies ?? {}).length > 0;
|
|
226364
226463
|
}
|
|
226365
226464
|
function skippedInputsForCheck(definition, context, skippedFiles2) {
|
|
226366
|
-
let themeDirectories = context.extensions.filter((extension) => extension.type === "theme").map((extension) => extension.path.replace(/shopify\.extension\.toml$/, "")), isThemePath = (path4) => themeDirectories.some((directory) => path4.startsWith(directory)) || path4.endsWith("shopify.extension.toml"), isSourcePath = (path4) => !isThemePath(path4) && !!definition.extensions?.some((extension) => path4.endsWith(extension)), isConfig = (path4) => /^shopify\.app(?:\.[^/]+)?\.toml$/.test(path4), isDependencyAutomationInput = (path4) => /(^|\/)package\.json$/.test(path4) || context.dependencyAutomation.files.some((file) => file.path === path4), isSecretInput = (file) => !file.detail?.includes("could not be parsed") && (context.sourceCandidates.some((candidate) => candidate.path === file.path) || context.sensitiveFiles.some((sensitiveFile) => sensitiveFile.path === file.path) || /(^|\/)(?:\.env(?:\.[^/]+)?|secrets\.json|credentials\.json)$/.test(file.path));
|
|
226367
|
-
return skippedFiles2.filter((file) => definition.target === "config" ? isConfig(file.path) : definition.target === "dependency_automation" ? isDependencyAutomationInput(file.path) : definition.target === "config_and_source" ? isConfig(file.path) ||
|
|
226465
|
+
let themeDirectories = context.extensions.filter((extension) => extension.type === "theme").map((extension) => extension.path.replace(/shopify\.extension\.toml$/, "")), isThemePath = (path4) => themeDirectories.some((directory) => path4.startsWith(directory)) || path4.endsWith("shopify.extension.toml"), isSourcePath = (path4) => !isThemePath(path4) && !!definition.extensions?.some((extension) => path4.endsWith(extension)), isReactRouterInput = (path4) => isSourcePath(path4) && isReactRouterFilePath(path4, context), isConfig = (path4) => /^shopify\.app(?:\.[^/]+)?\.toml$/.test(path4), isDependencyAutomationInput = (path4) => /(^|\/)package\.json$/.test(path4) || context.dependencyAutomation.files.some((file) => file.path === path4), isSecretInput = (file) => !file.detail?.includes("could not be parsed") && (context.sourceCandidates.some((candidate) => candidate.path === file.path) || context.sensitiveFiles.some((sensitiveFile) => sensitiveFile.path === file.path) || /(^|\/)(?:\.env(?:\.[^/]+)?|secrets\.json|credentials\.json)$/.test(file.path));
|
|
226466
|
+
return skippedFiles2.filter((file) => definition.target === "config" ? isConfig(file.path) : definition.target === "dependency_automation" ? isDependencyAutomationInput(file.path) : definition.target === "config_and_source" ? isConfig(file.path) || isReactRouterInput(file.path) : definition.target === "source" ? isReactRouterInput(file.path) : definition.target === "app_source" ? isSourcePath(file.path) : definition.target === "theme" ? isThemePath(file.path) : definition.target === "source_and_theme" ? isReactRouterInput(file.path) || isThemePath(file.path) : isSecretInput(file));
|
|
226368
226467
|
}
|
|
226369
226468
|
function skippedInputReason(definition, files) {
|
|
226370
226469
|
return {
|
|
@@ -226403,7 +226502,7 @@ async function scan(input, options = {}) {
|
|
|
226403
226502
|
scanDirectories,
|
|
226404
226503
|
explicitInputs: new Set(appConfigFilePath ? [appConfigFilePath] : [])
|
|
226405
226504
|
});
|
|
226406
|
-
let selectedAppConfigPath = appConfigFilePath ? normalizePath(relativePath(appRoot, appConfigFilePath)) : void 0, appToml = appConfigFilePath ? loadAppToml(appConfigFilePath, appRoot) : null, appTomls = appToml ? [appToml] : [], { paths: repositoryFiles, ignoredScanDirectories, otherAppDirectories, listingStatus } = await gatherScanPaths(input, options), extensions = findExtensions(appRoot, repositoryFiles), sourceCandidates = findSourceCandidates(repositoryFiles), sourceFiles = findAppSourceFiles(appRoot, repositoryFiles), sensitiveFiles = findSensitiveFiles(appRoot, repositoryFiles, selectedAppConfigPath), manifestPaths = findManifestPaths(repositoryFiles), manifests = findManifests(appRoot, manifestPaths), dependencyAutomation = manifests.some(manifestHasDependencies) ? findDependencyAutomationInputs(appRoot, repositoryFiles) : { files: [] }, capabilities = detectCapabilities(appToml, extensions, sourceFiles, appTomls),
|
|
226505
|
+
let selectedAppConfigPath = appConfigFilePath ? normalizePath(relativePath(appRoot, appConfigFilePath)) : void 0, appToml = appConfigFilePath ? loadAppToml(appConfigFilePath, appRoot) : null, appTomls = appToml ? [appToml] : [], { paths: repositoryFiles, ignoredScanDirectories, otherAppDirectories, listingStatus } = await gatherScanPaths(input, options), extensions = findExtensions(appRoot, repositoryFiles), sourceCandidates = findSourceCandidates(repositoryFiles), sourceFiles = findAppSourceFiles(appRoot, repositoryFiles), sensitiveFiles = findSensitiveFiles(appRoot, repositoryFiles, selectedAppConfigPath), manifestPaths = findManifestPaths(repositoryFiles), manifests = findManifests(appRoot, manifestPaths), dependencyAutomation = manifests.some(manifestHasDependencies) ? findDependencyAutomationInputs(appRoot, repositoryFiles) : { files: [] }, capabilities = detectCapabilities(appToml, extensions, sourceFiles, appTomls), relativeOtherAppDirectories = otherAppDirectories.map((directory) => normalizePath(relativePath(appRoot, directory))), reactRouterRoots = detectReactRouterRoots(manifests, sourceCandidates, relativeOtherAppDirectories), detection = detectProject(extensions, sourceCandidates, reactRouterRoots), context = {
|
|
226407
226506
|
appRoot,
|
|
226408
226507
|
appToml,
|
|
226409
226508
|
appTomls,
|
|
@@ -226414,6 +226513,8 @@ async function scan(input, options = {}) {
|
|
|
226414
226513
|
sensitiveFiles,
|
|
226415
226514
|
capabilities,
|
|
226416
226515
|
detection,
|
|
226516
|
+
reactRouterRoots,
|
|
226517
|
+
otherAppDirectories: relativeOtherAppDirectories,
|
|
226417
226518
|
sourceCandidates,
|
|
226418
226519
|
gitIgnoreListing: listingStatus
|
|
226419
226520
|
}, issues = [], checksExecuted = [], requiredCheckIds = /* @__PURE__ */ new Set();
|
|
@@ -228801,7 +228902,7 @@ var defaultDependencies3 = {
|
|
|
228801
228902
|
recordMetadata: recordAppSecurityMetadata
|
|
228802
228903
|
};
|
|
228803
228904
|
async function instructionsDestination(options, dependencies, canPrompt, agentCheckCount) {
|
|
228804
|
-
return options.skipInstructions ? "nothing" : options.
|
|
228905
|
+
return options.skipInstructions ? "nothing" : options.printInstructions ? "print" : canPrompt ? dependencies.selectInstructionsDestination(agentCheckCount) : "nothing";
|
|
228805
228906
|
}
|
|
228806
228907
|
function securityReportInput(execution, artifacts, verbose, commands2, selection, scanDirectories) {
|
|
228807
228908
|
return {
|
|
@@ -228898,8 +228999,17 @@ async function securityCheck(options, dependencies = defaultDependencies3) {
|
|
|
228898
228999
|
var import_core32 = __toESM(require_lib(), 1);
|
|
228899
229000
|
var SecurityCheck = class _SecurityCheck extends base_command_default {
|
|
228900
229001
|
static summary = "Check an app for Shopify-specific security issues and write deterministic-findings.json and agent-checks.json.";
|
|
228901
|
-
static descriptionWithMarkdown = "Runs an app security check locally and writes `deterministic-findings.json` and `agent-checks.json` to the results directory, `.shopify/app-security/<results key>/`. The results key is `--client-id` when you pass it, and otherwise the name of the app configuration file without `.toml`; the other `app security` commands take the same selection flags and find the same directory. Every run replaces both files, so it's always safe to run the check again.\n\n`deterministic-findings.json` holds the deterministic scan results. `agent-checks.json` holds the checks for your coding agent to investigate; the agent's results are recorded with `shopify app security record`. Use `--config` to select a specific app configuration when the project has multiple `shopify.app*.toml` files; the check inspects only that configuration. Use `--client-id` to replace the configuration's client ID for this run. `--client-id` is checked against your Shopify account before anything is scanned, so it needs you to be logged in. When no app configuration exists, use `--without-app-config --client-id <client-id>` to scan `--path` anyway with config checks skipped; in an interactive terminal the command offers to do this.\n\nThe check scans the app directory and each `--include-dir`. Git ignore rules apply by default: a file or directory that Git ignores is skipped, using the rules of the repository that contains it, while files that Git tracks are always scanned. Use `--no-git-ignore` to turn Git ignore rules off for every scanned directory.\n\nUse `--exclude` to skip more paths. Each value is a glob that is matched against the path relative to the working directory, so a path above it starts with `../`, and a name at any depth needs `**/`, for example `--exclude '**/generated'`. Repeat the flag to add globs. An exclusion can't remove the selected app configuration file. Quote each value so your shell doesn't expand `*`. The coding-agent instructions this check offers repeat the globs. Other `app security` commands don't take `--exclude` or `--no-git-ignore`, so pass the same flags each time you run the check.\n\nUse `--list-files` to check the scope before scanning: it prints the files the check would gather, one path per line and relative to the app directory, and then stops. It writes no results and never prompts. `--client-id` is still checked, but doesn't change the list.\n\nIn interactive terminals, the command offers to copy the coding-agent instructions, print them, or choose nothing; copying is the default. In CI and other non-interactive environments, instructions aren't offered unless you pass `--
|
|
229002
|
+
static descriptionWithMarkdown = "Runs an app security check locally and writes `deterministic-findings.json` and `agent-checks.json` to the results directory, `.shopify/app-security/<results key>/`. The results key is `--client-id` when you pass it, and otherwise the name of the app configuration file without `.toml`; the other `app security` commands take the same selection flags and find the same directory. Every run replaces both files, so it's always safe to run the check again.\n\n`deterministic-findings.json` holds the deterministic scan results. `agent-checks.json` holds the checks for your coding agent to investigate; the agent's results are recorded with `shopify app security record`. Use `--config` to select a specific app configuration when the project has multiple `shopify.app*.toml` files; the check inspects only that configuration. Use `--client-id` to replace the configuration's client ID for this run. `--client-id` is checked against your Shopify account before anything is scanned, so it needs you to be logged in. When no app configuration exists, use `--without-app-config --client-id <client-id>` to scan `--path` anyway with config checks skipped; in an interactive terminal the command offers to do this.\n\nThe check scans the app directory and each `--include-dir`. Git ignore rules apply by default: a file or directory that Git ignores is skipped, using the rules of the repository that contains it, while files that Git tracks are always scanned. Use `--no-git-ignore` to turn Git ignore rules off for every scanned directory. When the check uses Git, it requires Git 2.38.0 or later.\n\nUse `--exclude` to skip more paths. Each value is a glob that is matched against the path relative to the working directory, so a path above it starts with `../`, and a name at any depth needs `**/`, for example `--exclude '**/generated'`. Repeat the flag to add globs. An exclusion can't remove the selected app configuration file. Quote each value so your shell doesn't expand `*`. The coding-agent instructions this check offers repeat the globs. Other `app security` commands don't take `--exclude` or `--no-git-ignore`, so pass the same flags each time you run the check.\n\nUse `--list-files` to check the scope before scanning: it prints the files the check would gather, one path per line and relative to the app directory, and then stops. It writes no results and never prompts. `--client-id` is still checked, but doesn't change the list.\n\nIn interactive terminals, the command offers to copy the coding-agent instructions, print them, or choose nothing; copying is the default. In CI and other non-interactive environments, instructions aren't offered unless you pass `--print-instructions`, which prints them. You can also run `shopify app security instructions` to print, copy, or write them later.\n\nReports the number of findings to Shopify as usage telemetry, but not finding details. See [usage reporting](https://shopify.dev/docs/api/shopify-cli#usage-reporting) for details.";
|
|
228902
229003
|
static description = this.descriptionWithoutMarkdown();
|
|
229004
|
+
static examples = [
|
|
229005
|
+
"<%= config.bin %> <%= command.id %>",
|
|
229006
|
+
"<%= config.bin %> <%= command.id %> --include-dir ../backend",
|
|
229007
|
+
"<%= config.bin %> <%= command.id %> --path extensions --config production --include-dir .",
|
|
229008
|
+
"<%= config.bin %> <%= command.id %> --without-app-config --client-id <client-id>",
|
|
229009
|
+
'<%= config.bin %> <%= command.id %> --path app --include-dir . --exclude marketing --exclude "**/generated"',
|
|
229010
|
+
"<%= config.bin %> <%= command.id %> --no-git-ignore --exclude local-data",
|
|
229011
|
+
"<%= config.bin %> <%= command.id %> --include-dir ../backend --list-files"
|
|
229012
|
+
];
|
|
228903
229013
|
static flags = {
|
|
228904
229014
|
...globalFlags,
|
|
228905
229015
|
...appSecuritySelectionFlags,
|
|
@@ -228922,19 +229032,26 @@ var SecurityCheck = class _SecurityCheck extends base_command_default {
|
|
|
228922
229032
|
"list-files": import_core32.Flags.boolean({
|
|
228923
229033
|
description: "Print the files the check would gather, one path per line, and stop. Nothing is scanned, no results are written, and nothing is prompted for.",
|
|
228924
229034
|
env: "SHOPIFY_FLAG_LIST_FILES",
|
|
228925
|
-
exclusive: ["
|
|
229035
|
+
exclusive: ["print-instructions", "skip-instructions", "blocking"]
|
|
228926
229036
|
}),
|
|
228927
229037
|
...appSecurityBlockingFlag,
|
|
228928
|
-
|
|
228929
|
-
description: "Print coding-agent instructions without prompting.",
|
|
229038
|
+
"print-instructions": import_core32.Flags.boolean({
|
|
229039
|
+
description: "Print coding-agent instructions without prompting for how to deliver them.",
|
|
228930
229040
|
default: !1,
|
|
228931
229041
|
exclusive: ["skip-instructions"],
|
|
229042
|
+
env: "SHOPIFY_FLAG_APP_SECURITY_PRINT_INSTRUCTIONS"
|
|
229043
|
+
}),
|
|
229044
|
+
yes: import_core32.Flags.boolean({
|
|
229045
|
+
description: "Print coding-agent instructions without prompting.",
|
|
229046
|
+
hidden: !0,
|
|
229047
|
+
deprecated: { to: "--print-instructions" },
|
|
229048
|
+
exclusive: ["skip-instructions", "list-files"],
|
|
228932
229049
|
env: "SHOPIFY_FLAG_YES"
|
|
228933
229050
|
}),
|
|
228934
229051
|
"skip-instructions": import_core32.Flags.boolean({
|
|
228935
|
-
description: "Don't offer
|
|
229052
|
+
description: "Don't offer the coding-agent instructions after the scan. Use it when you want only the deterministic scan results.",
|
|
228936
229053
|
default: !1,
|
|
228937
|
-
exclusive: ["
|
|
229054
|
+
exclusive: ["print-instructions"],
|
|
228938
229055
|
env: "SHOPIFY_FLAG_APP_SECURITY_SKIP_INSTRUCTIONS"
|
|
228939
229056
|
})
|
|
228940
229057
|
};
|
|
@@ -228947,7 +229064,7 @@ var SecurityCheck = class _SecurityCheck extends base_command_default {
|
|
|
228947
229064
|
withoutAppConfig: !!flags["without-app-config"],
|
|
228948
229065
|
verbose: !!flags.verbose,
|
|
228949
229066
|
blocking: flags.blocking,
|
|
228950
|
-
|
|
229067
|
+
printInstructions: !!(flags["print-instructions"] || flags.yes),
|
|
228951
229068
|
skipInstructions: flags["skip-instructions"],
|
|
228952
229069
|
includeDirs: flags["include-dir"] ?? [],
|
|
228953
229070
|
excludePatterns: flags.exclude ?? [],
|
|
@@ -229184,7 +229301,7 @@ function renderSecurityRecordResult(result, selection, path4) {
|
|
|
229184
229301
|
// ../app/dist/cli/commands/app/security/record.js
|
|
229185
229302
|
var SecurityRecord = class _SecurityRecord extends base_command_default {
|
|
229186
229303
|
static summary = "Record agent findings from an app security check.";
|
|
229187
|
-
static descriptionWithMarkdown = "Reads a coding agent's complete findings document from stdin, validates it, and replaces `agent-findings.json` in the results directory, `.shopify/app-security/<results key>/`. The results key is `--client-id` when you pass it, and otherwise the name of the app configuration file without `.toml`. `--client-id` is checked against your Shopify account before anything is read, so it needs you to be logged in.\n\nThe document must include a `scope` with the `include_dirs`, `excludes` and `no_git_ignore` values of the `check` run it describes, exactly as typed. It's recorded as reported and never compared with the scan's files.\n\nThe document is recorded all or nothing: if anything is invalid, the command fails with every error, writes nothing, and exits with a non-zero code. It needs the results directory that `shopify app security check` creates.";
|
|
229304
|
+
static descriptionWithMarkdown = "Reads a coding agent's complete findings document from stdin, validates it, and replaces `agent-findings.json` in the results directory, `.shopify/app-security/<results key>/`. The results key is `--client-id` when you pass it, and otherwise the name of the app configuration file without `.toml`. `--client-id` is checked against your Shopify account before anything is read, so it needs you to be logged in.\n\nThe document must include a `scope` with the `include_dirs`, `excludes` and `no_git_ignore` values of the `check` run it describes, exactly as typed. It's recorded as reported and never compared with the scan's files.\n\nThe document is recorded all or nothing: if anything is invalid, the command fails with every error, writes nothing, and exits with a non-zero code. It needs the results directory that `shopify app security check` creates.\n\nReports the number of findings to Shopify as usage telemetry, but not finding details. See [usage reporting](https://shopify.dev/docs/api/shopify-cli#usage-reporting) for details.";
|
|
229188
229305
|
static description = this.descriptionForHelp();
|
|
229189
229306
|
static flags = {
|
|
229190
229307
|
...globalFlags,
|
|
@@ -229560,7 +229677,7 @@ async function securityReview(options, dependencies = defaultDependencies6) {
|
|
|
229560
229677
|
var import_core35 = __toESM(require_lib(), 1);
|
|
229561
229678
|
var SecurityReview = class _SecurityReview extends base_command_default {
|
|
229562
229679
|
static summary = "Show the combined app security check results.";
|
|
229563
|
-
static descriptionWithMarkdown = "Combines the deterministic results (`deterministic-findings.json`, written by `shopify app security check`) with the recorded agent results (`agent-findings.json`, written by `shopify app security record`) and shows one view of every check: its findings, status and source. Both files are in the results directory, `.shopify/app-security/<results key>/`. `--client-id` is checked against your Shopify account before any results are read, so it needs you to be logged in.\n\nThe summary shows the scan directories and the scope of the latest scan, and the scope the agent reported. It notes when the agent findings were recorded for a different scope than the latest scan; that doesn't change the exit code.\n\nThe agent results are optional. Use `--check-id` to narrow the review to specific checks, `--verbose` for full reasoning, evidence and suppressed findings, and `--blocking` to exit with code 1 when a check with findings is at or above a severity.";
|
|
229680
|
+
static descriptionWithMarkdown = "Combines the deterministic results (`deterministic-findings.json`, written by `shopify app security check`) with the recorded agent results (`agent-findings.json`, written by `shopify app security record`) and shows one view of every check: its findings, status and source. Both files are in the results directory, `.shopify/app-security/<results key>/`. `--client-id` is checked against your Shopify account before any results are read, so it needs you to be logged in.\n\nThe summary shows the scan directories and the scope of the latest scan, and the scope the agent reported. It notes when the agent findings were recorded for a different scope than the latest scan; that doesn't change the exit code.\n\nThe agent results are optional. Use `--check-id` to narrow the review to specific checks, `--verbose` for full reasoning, evidence and suppressed findings, and `--blocking` to exit with code 1 when a check with findings is at or above a severity.\n\nReports the number of findings to Shopify as usage telemetry, but not finding details. See [usage reporting](https://shopify.dev/docs/api/shopify-cli#usage-reporting) for details.";
|
|
229564
229681
|
static description = this.descriptionForHelp();
|
|
229565
229682
|
static flags = {
|
|
229566
229683
|
...globalFlags,
|