Compare commits
12 Commits
5707fa59b8
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 237f57cf36 | |||
| a893cd326f | |||
| 92f636f247 | |||
| 66c711916e | |||
| 5b6db0eece | |||
| a5f9b1542c | |||
| 688536d0ac | |||
| 6d75973835 | |||
| 62514fa20e | |||
| 17e0c1b707 | |||
| f738390d76 | |||
| 096eb80999 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
**/node_modules/**
|
||||
dist/**
|
||||
desktop.ini
|
||||
.continue/**
|
||||
453
package-lock.json
generated
453
package-lock.json
generated
@ -28,18 +28,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
||||
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
||||
"version": "0.3.12",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
|
||||
"integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/set-array": "^1.2.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0",
|
||||
"@jridgewell/trace-mapping": "^0.3.24"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/resolve-uri": {
|
||||
@ -52,20 +48,10 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/set-array": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/source-map": {
|
||||
"version": "0.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
||||
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
||||
"version": "0.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz",
|
||||
"integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -74,16 +60,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
|
||||
"integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.25",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||
"version": "0.3.29",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
|
||||
"integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -114,16 +100,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/google-apps-script": {
|
||||
"version": "1.0.85",
|
||||
"resolved": "https://registry.npmjs.org/@types/google-apps-script/-/google-apps-script-1.0.85.tgz",
|
||||
"integrity": "sha512-O5w3PxI75uqU4d7t24ukQtU87OZ2j0vQp3VWmx9sJ6PTwBRvGhMA+qWShKNetofI8TYaVd8tFzBQXgv3e7ycCQ==",
|
||||
"version": "1.0.99",
|
||||
"resolved": "https://registry.npmjs.org/@types/google-apps-script/-/google-apps-script-1.0.99.tgz",
|
||||
"integrity": "sha512-JrOXCWxYmY1ePWZXQxegrVMdXS0vuN69AMUfDIvfz5aLZ+El5JcYllwzeXeFC1YoM3lMWtPNGjgeTxlz8jih6w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@ -135,13 +121,13 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz",
|
||||
"integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==",
|
||||
"version": "24.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz",
|
||||
"integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.8"
|
||||
"undici-types": "~7.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/ast": {
|
||||
@ -367,9 +353,9 @@
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
@ -379,31 +365,65 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-import-phases": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
|
||||
"integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"acorn": "^8.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv-keywords": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"node_modules/ajv-formats": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
|
||||
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "^8.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"ajv": "^6.9.1"
|
||||
"ajv": "^8.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"ajv": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ajv-keywords": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
||||
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"ajv": "^8.8.2"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
@ -430,9 +450,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -453,9 +473,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
|
||||
"integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==",
|
||||
"version": "4.25.1",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
|
||||
"integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -473,10 +493,10 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001669",
|
||||
"electron-to-chromium": "^1.5.41",
|
||||
"node-releases": "^2.0.18",
|
||||
"update-browserslist-db": "^1.1.1"
|
||||
"caniuse-lite": "^1.0.30001726",
|
||||
"electron-to-chromium": "^1.5.173",
|
||||
"node-releases": "^2.0.19",
|
||||
"update-browserslist-db": "^1.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"browserslist": "cli.js"
|
||||
@ -493,9 +513,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001680",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz",
|
||||
"integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==",
|
||||
"version": "1.0.30001731",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz",
|
||||
"integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -590,9 +610,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.5",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz",
|
||||
"integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==",
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -605,16 +625,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.57",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.57.tgz",
|
||||
"integrity": "sha512-xS65H/tqgOwUBa5UmOuNSLuslDo7zho0y/lgQw35pnrqiZh7UOWHCeL/Bt6noJATbA6tpQJGCifsFsIRZj1Fqg==",
|
||||
"version": "1.5.194",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.194.tgz",
|
||||
"integrity": "sha512-SdnWJwSUot04UR51I2oPD8kuP2VI37/CADR1OHsFOUzZIvfWJBO6q11k5P/uKNyTT3cdOsnyjkrZ+DDShqYqJA==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.17.1",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
|
||||
"integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
|
||||
"version": "5.18.2",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz",
|
||||
"integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -639,9 +659,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/es-module-lexer": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
|
||||
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
|
||||
"integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@ -677,27 +697,6 @@
|
||||
"source-map": "~0.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/escodegen/node_modules/estraverse": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/escodegen/node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-scope": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
||||
@ -712,6 +711,16 @@
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-scope/node_modules/estraverse": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
@ -753,7 +762,7 @@
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esrecurse/node_modules/estraverse": {
|
||||
"node_modules/estraverse": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||
@ -763,16 +772,6 @@
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/estraverse": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esutils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
@ -800,12 +799,22 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"node_modules/fast-uri": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
|
||||
"integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/fastest-levenshtein": {
|
||||
"version": "1.0.16",
|
||||
@ -876,16 +885,6 @@
|
||||
"estraverse": "5.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/gas-entry-generator/node_modules/estraverse": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/gas-webpack-plugin": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/gas-webpack-plugin/-/gas-webpack-plugin-2.6.0.tgz",
|
||||
@ -914,9 +913,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/graphql": {
|
||||
"version": "16.9.0",
|
||||
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz",
|
||||
"integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==",
|
||||
"version": "16.11.0",
|
||||
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz",
|
||||
"integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
@ -994,9 +993,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
|
||||
"integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
|
||||
"version": "2.16.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
||||
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -1088,9 +1087,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@ -1195,9 +1194,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.18",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
|
||||
"integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
|
||||
"version": "2.0.19",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
|
||||
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@ -1300,16 +1299,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@ -1333,20 +1322,33 @@
|
||||
"node": ">= 10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-from-string": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.8",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
||||
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
|
||||
"version": "1.22.10",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
||||
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.13.0",
|
||||
"is-core-module": "^2.16.0",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"resolve": "bin/resolve"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
@ -1396,15 +1398,16 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/schema-utils": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz",
|
||||
"integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.8",
|
||||
"ajv": "^6.12.5",
|
||||
"ajv-keywords": "^3.5.2"
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"ajv": "^8.9.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"ajv-keywords": "^5.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
@ -1415,9 +1418,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
@ -1475,7 +1478,7 @@
|
||||
},
|
||||
"node_modules/shopify-admin-api-typings": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "git+ssh://git@github.com/beepmill/shopify-admin-api-typings.git#e8ba51acff0a4e66c31ee61d62f5244ad4f4233a",
|
||||
"resolved": "git+ssh://git@github.com/beepmill/shopify-admin-api-typings.git#1641fa805ac6d185abfa33515f7ed265837743df",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
@ -1493,13 +1496,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
|
||||
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
@ -1513,16 +1516,6 @@
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support/node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
@ -1550,9 +1543,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz",
|
||||
"integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -1560,14 +1553,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.36.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz",
|
||||
"integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==",
|
||||
"version": "5.43.1",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz",
|
||||
"integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.8.2",
|
||||
"acorn": "^8.14.0",
|
||||
"commander": "^2.20.0",
|
||||
"source-map-support": "~0.5.20"
|
||||
},
|
||||
@ -1579,17 +1572,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser-webpack-plugin": {
|
||||
"version": "5.3.10",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
|
||||
"integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
|
||||
"version": "5.3.14",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz",
|
||||
"integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "^0.3.20",
|
||||
"@jridgewell/trace-mapping": "^0.3.25",
|
||||
"jest-worker": "^27.4.5",
|
||||
"schema-utils": "^3.1.1",
|
||||
"serialize-javascript": "^6.0.1",
|
||||
"terser": "^5.26.0"
|
||||
"schema-utils": "^4.3.0",
|
||||
"serialize-javascript": "^6.0.2",
|
||||
"terser": "^5.31.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
@ -1627,9 +1620,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader": {
|
||||
"version": "9.5.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz",
|
||||
"integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==",
|
||||
"version": "9.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.2.tgz",
|
||||
"integrity": "sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -1647,6 +1640,16 @@
|
||||
"webpack": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/source-map": {
|
||||
"version": "0.7.6",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
|
||||
"integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
@ -1655,9 +1658,9 @@
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.6.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
|
||||
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
|
||||
"version": "5.9.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
|
||||
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
@ -1670,16 +1673,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
"version": "7.8.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
|
||||
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/update-browserslist-db": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
|
||||
"integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
|
||||
"integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -1698,7 +1701,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"escalade": "^3.2.0",
|
||||
"picocolors": "^1.1.0"
|
||||
"picocolors": "^1.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"update-browserslist-db": "cli.js"
|
||||
@ -1707,20 +1710,10 @@
|
||||
"browserslist": ">= 4.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
|
||||
"integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz",
|
||||
"integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -1732,21 +1725,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.96.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz",
|
||||
"integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==",
|
||||
"version": "5.101.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.0.tgz",
|
||||
"integrity": "sha512-B4t+nJqytPeuZlHuIKTbalhljIFXeNRqrUGAQgTGlfOl2lXXKXw+yZu6bicycP+PUlM44CxBjCFD6aciKFT3LQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.7",
|
||||
"@types/estree": "^1.0.6",
|
||||
"@webassemblyjs/ast": "^1.12.1",
|
||||
"@webassemblyjs/wasm-edit": "^1.12.1",
|
||||
"@webassemblyjs/wasm-parser": "^1.12.1",
|
||||
"acorn": "^8.14.0",
|
||||
"@types/estree": "^1.0.8",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"@webassemblyjs/ast": "^1.14.1",
|
||||
"@webassemblyjs/wasm-edit": "^1.14.1",
|
||||
"@webassemblyjs/wasm-parser": "^1.14.1",
|
||||
"acorn": "^8.15.0",
|
||||
"acorn-import-phases": "^1.0.3",
|
||||
"browserslist": "^4.24.0",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "^5.17.1",
|
||||
"enhanced-resolve": "^5.17.2",
|
||||
"es-module-lexer": "^1.2.1",
|
||||
"eslint-scope": "5.1.1",
|
||||
"events": "^3.2.0",
|
||||
@ -1756,11 +1751,11 @@
|
||||
"loader-runner": "^4.2.0",
|
||||
"mime-types": "^2.1.27",
|
||||
"neo-async": "^2.6.2",
|
||||
"schema-utils": "^3.2.0",
|
||||
"schema-utils": "^4.3.2",
|
||||
"tapable": "^2.1.1",
|
||||
"terser-webpack-plugin": "^5.3.10",
|
||||
"terser-webpack-plugin": "^5.3.11",
|
||||
"watchpack": "^2.4.1",
|
||||
"webpack-sources": "^3.2.3"
|
||||
"webpack-sources": "^3.3.3"
|
||||
},
|
||||
"bin": {
|
||||
"webpack": "bin/webpack.js"
|
||||
@ -1850,9 +1845,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-sources": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
||||
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
|
||||
"integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
||||
@ -9,7 +9,8 @@
|
||||
],
|
||||
"settings": {
|
||||
"prettier.semi": false,
|
||||
"cloudcode.duetAI.project": "beepmill-code",
|
||||
"cloudcode.project": "beepmill-code"
|
||||
"cloudcode.project": "beepmill-code",
|
||||
"geminicodeassist.project": "beepmill-code",
|
||||
"typescript.tsdk": "product_inventory\\node_modules\\typescript\\lib"
|
||||
}
|
||||
}
|
||||
@ -43,37 +43,24 @@ export function columnOnEditHandler(e: GoogleAppsScript.Events.SheetsOnEdit) {
|
||||
for (let row = e.range.getRow(); row <= e.range.getLastRow(); row++) {
|
||||
console.log("row: " + row)
|
||||
let updateString = "updating " + header + " on row " + row
|
||||
switch (header) {
|
||||
case "shopify_status":
|
||||
let shopifyUpdateColumns = [
|
||||
"shopify_status",
|
||||
"title",
|
||||
"product_type",
|
||||
"tags",
|
||||
"description",
|
||||
"base_price",
|
||||
"original_price",
|
||||
"weight_grams",
|
||||
"product_height_cm",
|
||||
"product_width_cm",
|
||||
"product_depth_cm"
|
||||
]
|
||||
if (shopifyUpdateColumns.includes(header)) {
|
||||
// Accumulate changes for 30s before updating
|
||||
toastAndLog(updateString)
|
||||
updateProductToShopify(row)
|
||||
break
|
||||
case "title":
|
||||
toastAndLog(updateString)
|
||||
updateProductToShopify(row)
|
||||
break
|
||||
case "product_type":
|
||||
toastAndLog(updateString)
|
||||
updateProductToShopify(row)
|
||||
break
|
||||
case "tags":
|
||||
toastAndLog(updateString)
|
||||
updateProductToShopify(row)
|
||||
break
|
||||
case "description":
|
||||
toastAndLog(updateString)
|
||||
updateProductToShopify(row)
|
||||
break
|
||||
case "price":
|
||||
toastAndLog(updateString)
|
||||
updateProductToShopify(row)
|
||||
break
|
||||
case "compare_at_price":
|
||||
toastAndLog(updateString)
|
||||
updateProductToShopify(row)
|
||||
break
|
||||
default:
|
||||
continue
|
||||
}
|
||||
toastAndLog("completed " + updateString)
|
||||
}
|
||||
|
||||
217
src/Product.ts
217
src/Product.ts
@ -5,22 +5,27 @@ import {
|
||||
ShopifyProductsQuery,
|
||||
ShopifyProductsResponse,
|
||||
ShopifyProductSetInput,
|
||||
ShopifyVariant,
|
||||
ShopifyProductVariant,
|
||||
ShopifyProductSetQuery,
|
||||
ShopifyVariant,
|
||||
VariantOptionValueInput,
|
||||
formatGqlForJSON,
|
||||
} from "./shopifyApi"
|
||||
import * as shopify from 'shopify-admin-api-typings'
|
||||
import { getCellRangeByColumnName, getRowByColumnValue } from "./sheetUtils"
|
||||
import * as shopify from "shopify-admin-api-typings"
|
||||
import {
|
||||
getCellRangeByColumnName,
|
||||
getRowByColumnValue,
|
||||
vlookupByColumns,
|
||||
} from "./sheetUtils"
|
||||
import { Config } from "./config"
|
||||
|
||||
|
||||
export class Product {
|
||||
shopify_id: string = ""
|
||||
title: string = ""
|
||||
style: string[] = []
|
||||
tags: string = ""
|
||||
category: string = ""
|
||||
ebay_category_id: string = ""
|
||||
product_type: string = ""
|
||||
description: string = ""
|
||||
sku: string = ""
|
||||
@ -30,6 +35,9 @@ export class Product {
|
||||
function: string = ""
|
||||
type: string = ""
|
||||
weight_grams: number = 0
|
||||
product_width_cm: number = 0
|
||||
product_depth_cm: number = 0
|
||||
product_height_cm: number = 0
|
||||
photos: string = ""
|
||||
shopify_product: shopify.Product
|
||||
shopify_default_variant_id: string = ""
|
||||
@ -110,10 +118,26 @@ export class Product {
|
||||
)
|
||||
}
|
||||
|
||||
ShopifyCategory(): string {
|
||||
return vlookupByColumns(
|
||||
"values",
|
||||
"product_type",
|
||||
this.product_type,
|
||||
"shopify_category"
|
||||
)
|
||||
}
|
||||
|
||||
EbayCategory(): string {
|
||||
return vlookupByColumns(
|
||||
"values",
|
||||
"product_type",
|
||||
this.product_type,
|
||||
"ebay_category_id"
|
||||
)
|
||||
}
|
||||
|
||||
ToShopifyProductSet() {
|
||||
let sps = new ShopifyProductSetInput()
|
||||
//TODO: map category IDs
|
||||
//sps.category = this.category
|
||||
if (this.shopify_id != "") {
|
||||
sps.id = this.shopify_id
|
||||
}
|
||||
@ -121,6 +145,10 @@ export class Product {
|
||||
sps.status = this.shopify_status
|
||||
}
|
||||
sps.productType = this.product_type
|
||||
let category = this.ShopifyCategory()
|
||||
if (category !== "") {
|
||||
sps.category = this.ShopifyCategory()
|
||||
}
|
||||
sps.tags = this.tags
|
||||
sps.title = this.title
|
||||
sps.descriptionHtml = this.description
|
||||
@ -174,12 +202,136 @@ export class Product {
|
||||
response = this.PublishToShopifyOnlineStore(shop)
|
||||
console.log("UpdateShopifyProduct: setting defaults on inventory item")
|
||||
shop.SetInventoryItemDefaults(item, config)
|
||||
if (this.weight_grams > 0) {
|
||||
console.log("UpdateShopifyProduct: setting weight on inventory item")
|
||||
shop.SetInventoryItemWeight(
|
||||
item,
|
||||
config,
|
||||
this.weight_grams,
|
||||
shopify.WeightUnit.GRAMS
|
||||
)
|
||||
}
|
||||
if (newProduct) {
|
||||
console.log("UpdateShopifyProduct: setting defaults on new product")
|
||||
console.log("UpdateShopifyProduct: adjusting inventory item quantity")
|
||||
shop.UpdateInventoryItemQuantity(item, 1, config)
|
||||
console.log(JSON.stringify(response, null, 2))
|
||||
}
|
||||
// update all metafields
|
||||
this.UpdateAllMetafields(shop);
|
||||
// create product photo folder
|
||||
this.CreatePhotoFolder();
|
||||
}
|
||||
|
||||
UpdateAllMetafields(shop: Shop) {
|
||||
console.log("UpdateAllMetafields()")
|
||||
if (!this.shopify_id) {
|
||||
console.log("Cannot update metafields without a Shopify Product ID.")
|
||||
return
|
||||
}
|
||||
|
||||
const metafieldsToSet: shopify.MetafieldsSetInput[] = []
|
||||
|
||||
// eBay Category Metafield
|
||||
if (this.product_type) {
|
||||
this.ebay_category_id = this.EbayCategory()
|
||||
if (this.ebay_category_id) {
|
||||
metafieldsToSet.push({
|
||||
key: "ebay_category_id",
|
||||
namespace: "custom",
|
||||
ownerId: this.shopify_id,
|
||||
type: "single_line_text_field",
|
||||
value: this.ebay_category_id.toString(),
|
||||
})
|
||||
} else {
|
||||
console.log(
|
||||
`No eBay category defined for product type '${this.product_type}'`
|
||||
)
|
||||
}
|
||||
} else {
|
||||
console.log("No product type set, skipping eBay category metafield.")
|
||||
}
|
||||
|
||||
// Dimension Metafields
|
||||
if (this.product_height_cm > 0) {
|
||||
metafieldsToSet.push({
|
||||
key: "product_height_cm",
|
||||
namespace: "custom",
|
||||
ownerId: this.shopify_id,
|
||||
type: "dimension",
|
||||
value: JSON.stringify({
|
||||
value: this.product_height_cm,
|
||||
unit: "cm",
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
if (this.product_width_cm > 0) {
|
||||
metafieldsToSet.push({
|
||||
key: "product_width_cm",
|
||||
namespace: "custom",
|
||||
ownerId: this.shopify_id,
|
||||
type: "dimension",
|
||||
value: JSON.stringify({
|
||||
value: this.product_width_cm,
|
||||
unit: "cm",
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
if (this.product_depth_cm > 0) {
|
||||
metafieldsToSet.push({
|
||||
key: "product_depth_cm",
|
||||
namespace: "custom",
|
||||
ownerId: this.shopify_id,
|
||||
type: "dimension",
|
||||
value: JSON.stringify({
|
||||
value: this.product_depth_cm,
|
||||
unit: "cm",
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
if (metafieldsToSet.length === 0) {
|
||||
console.log("No metafields to update.")
|
||||
return
|
||||
}
|
||||
|
||||
const query = /* GraphQL */ `
|
||||
mutation metafieldsSet($metafields: [MetafieldsSetInput!]!) {
|
||||
metafieldsSet(metafields: $metafields) {
|
||||
metafields {
|
||||
id
|
||||
key
|
||||
namespace
|
||||
value
|
||||
}
|
||||
userErrors {
|
||||
field
|
||||
message
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const variables = {
|
||||
metafields: metafieldsToSet,
|
||||
}
|
||||
|
||||
const json = `{
|
||||
"query": ${formatGqlForJSON(String(query))},
|
||||
"variables": ${JSON.stringify(variables)}
|
||||
}`
|
||||
|
||||
console.log("Setting metafields with query:\n" + json)
|
||||
const response = shop.shopifyGraphQLAPI(JSON.parse(json))
|
||||
console.log("metafieldsSet response: " + JSON.stringify(response, null, 2))
|
||||
}
|
||||
|
||||
CreatePhotoFolder() {
|
||||
console.log("Product.CreatePhotoFolder()");
|
||||
createPhotoFolderForSku(new(Config), this.sku);
|
||||
}
|
||||
|
||||
PublishToShopifyOnlineStore(shop: Shop) {
|
||||
@ -226,3 +378,56 @@ export class Product {
|
||||
// TODO: shopify_status
|
||||
}
|
||||
}
|
||||
|
||||
export function createPhotoFolderForSku(config: Config, sku: string) {
|
||||
console.log(`createPhotoFolderForSku('${sku}')`)
|
||||
if (!config.productPhotosFolderId) {
|
||||
console.log(
|
||||
"productPhotoFolderId not set in config. Skipping folder creation."
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const productInventorySheet =
|
||||
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("product_inventory")
|
||||
const row = getRowByColumnValue("product_inventory", "sku", sku)
|
||||
if (!row) {
|
||||
console.log(`SKU '${sku}' not found in sheet. Cannot create folder.`)
|
||||
return
|
||||
}
|
||||
const photosCell = getCellRangeByColumnName(
|
||||
productInventorySheet,
|
||||
"photos",
|
||||
row
|
||||
)
|
||||
const folderUrl = photosCell.getRichTextValue().getLinkUrl()
|
||||
console.log(`Folder URL from cell: ${folderUrl}`)
|
||||
|
||||
if (folderUrl && folderUrl.includes("drive.google.com")) {
|
||||
console.log(`Photo folder already exists: ${folderUrl}`)
|
||||
return
|
||||
} else {
|
||||
console.log(`Creating photo folder for SKU: ${sku}`)
|
||||
}
|
||||
|
||||
const parentFolder = DriveApp.getFolderById(config.productPhotosFolderId)
|
||||
const folderName = sku
|
||||
let newFolder: GoogleAppsScript.Drive.Folder
|
||||
|
||||
const existingFolders = parentFolder.getFoldersByName(folderName)
|
||||
if (existingFolders.hasNext()) {
|
||||
newFolder = existingFolders.next()
|
||||
console.log(`Found existing photo folder: '${folderName}'`)
|
||||
} else {
|
||||
newFolder = parentFolder.createFolder(folderName)
|
||||
console.log(`Created new photo folder: '${folderName}'`)
|
||||
}
|
||||
let url = newFolder.getUrl()
|
||||
console.log(`Folder URL: ${url}`)
|
||||
|
||||
let linkValue = SpreadsheetApp.newRichTextValue()
|
||||
.setText(folderName)
|
||||
.setLinkUrl(url)
|
||||
.build()
|
||||
photosCell.setRichTextValue(linkValue)
|
||||
}
|
||||
|
||||
@ -1,56 +1,32 @@
|
||||
import { createPhotoFolderForSku } from "./Product"
|
||||
import { getColumnRichTextByName, getColumnValuesByName, toastAndLog } from "./sheetUtils"
|
||||
import { Config } from "./config"
|
||||
import {
|
||||
getCellRangeByColumnName,
|
||||
getColumnValuesByName,
|
||||
toastAndLog,
|
||||
} from "./sheetUtils"
|
||||
|
||||
export function createMissingPhotoFolders() {
|
||||
let ss = SpreadsheetApp.getActive()
|
||||
let s = ss.getSheetByName("product_inventory")
|
||||
let config = new Config()
|
||||
let photoParent = DriveApp.getFolderById(config.productPhotosFolderId)
|
||||
const ss = SpreadsheetApp.getActive()
|
||||
const s = ss.getSheetByName("product_inventory")
|
||||
if (!s) {
|
||||
toastAndLog("Could not find 'product_inventory' sheet.")
|
||||
return
|
||||
}
|
||||
|
||||
let skus = getColumnValuesByName(s, "sku")
|
||||
let photoLinks = getColumnValuesByName(s, "photos")
|
||||
let created: string[] = []
|
||||
let photos = getColumnRichTextByName(s, "photos")
|
||||
let config = new Config()
|
||||
|
||||
let folderItr = photoParent.getFolders()
|
||||
let folderNames: string[] = []
|
||||
console.log("getting list of existing folders...")
|
||||
while (folderItr.hasNext()) {
|
||||
let folder = folderItr.next()
|
||||
folderNames.push(folder.getName())
|
||||
}
|
||||
console.log("existing folders: " + folderNames.join(", "))
|
||||
|
||||
for (let i = 0; i < skus.length; i++) {
|
||||
let sku = String(skus[i][0])
|
||||
let updateLink: boolean = false
|
||||
if (null == sku || sku == "") {
|
||||
// Process rows backward, as that is where the missing folders are most likely to occur
|
||||
for (let i = skus.length - 1; i >= 0; i--) {
|
||||
const sku = String(skus[i][0])
|
||||
if (!sku) {
|
||||
continue
|
||||
}
|
||||
if (folderNames.includes(sku)) {
|
||||
console.log("folder '" + sku + "' already exists")
|
||||
} else {
|
||||
console.log("creating folder '" + skus[i] + "'")
|
||||
photoParent.createFolder(sku)
|
||||
created.push(sku)
|
||||
updateLink = true
|
||||
}
|
||||
|
||||
// Update photos cell
|
||||
if (photoLinks[i][0] != "" && !updateLink) {
|
||||
let folderUrl = photos[i][0].getLinkUrl()
|
||||
if (folderUrl && folderUrl.includes("drive.google.com")) {
|
||||
console.log(`Photo folder already exists for SKU: ${sku}`)
|
||||
continue
|
||||
}
|
||||
console.log("updating photos cell for '" + sku + "'")
|
||||
let photosCell = getCellRangeByColumnName(s, "photos", i + 2)
|
||||
let folder = photoParent.getFoldersByName(sku).next()
|
||||
let url = folder.getUrl()
|
||||
let linkValue = SpreadsheetApp.newRichTextValue()
|
||||
.setText(sku)
|
||||
.setLinkUrl(url)
|
||||
.build()
|
||||
photosCell.setRichTextValue(linkValue)
|
||||
|
||||
createPhotoFolderForSku(config, sku)
|
||||
}
|
||||
toastAndLog("created " + created.length + " folders: " + created.join(", "))
|
||||
toastAndLog("Finished creating missing photo folders.")
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
/// <reference types="@types/google-apps-script" />
|
||||
|
||||
import { onOpen } from "./onOpen"
|
||||
import { matchProductToShopifyOnEditHandler } from "./OnEditHandler"
|
||||
import { getShopifyProducts } from "./shopifyApi"
|
||||
import { runShopifyOrders } from "./shopifyApi"
|
||||
import {
|
||||
@ -13,6 +14,10 @@ import { createMissingPhotoFolders } from "./createMissingPhotoFolders"
|
||||
import { reinstallTriggers } from "./triggers"
|
||||
import { newSkuHandler } from "./newSku"
|
||||
import { columnOnEditHandler } from "./OnEditHandler"
|
||||
import {
|
||||
onEditQueue,
|
||||
processBatchedEdits
|
||||
} from "./onEditQueue"
|
||||
import { fillProductFromTemplate } from "./fillProductFromTemplate"
|
||||
|
||||
// prettier-ignore
|
||||
@ -24,6 +29,8 @@ import { fillProductFromTemplate } from "./fillProductFromTemplate"
|
||||
;(global as any).matchProductToShopifyOnEditHandler = matchProductToShopifyOnEditHandler
|
||||
;(global as any).updateShopifyProductHandler = updateShopifyProductHandler
|
||||
;(global as any).columnOnEditHandler = columnOnEditHandler
|
||||
;(global as any).onEditQueue = onEditQueue
|
||||
;(global as any).processBatchedEdits = processBatchedEdits
|
||||
;(global as any).reauthorizeScript = reauthorizeScript
|
||||
;(global as any).reinstallTriggers = reinstallTriggers
|
||||
;(global as any).newSkuHandler = newSkuHandler
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { createPhotoFolderForSku } from "./Product"
|
||||
import { Config } from "./config"
|
||||
import {
|
||||
getColumnByName,
|
||||
getCellRangeByColumnName,
|
||||
@ -5,6 +7,7 @@ import {
|
||||
getColumnValuesByName,
|
||||
} from "./sheetUtils"
|
||||
|
||||
const LOCK_TIMEOUT_MS = 1000 * 10
|
||||
|
||||
export function newSkuHandler(e: GoogleAppsScript.Events.SheetsOnEdit) {
|
||||
var sheet = SpreadsheetApp.getActive().getActiveSheet()
|
||||
@ -20,7 +23,19 @@ export function newSkuHandler(e: GoogleAppsScript.Events.SheetsOnEdit) {
|
||||
console.log("new ID was not requested, returning")
|
||||
return
|
||||
}
|
||||
newSku(row)
|
||||
// Acquire a user lock to prevent multiple onEdit calls from clashing
|
||||
const documentLock = LockService.getDocumentLock()
|
||||
try {
|
||||
const config = new (Config);
|
||||
documentLock.waitLock(LOCK_TIMEOUT_MS)
|
||||
const sku = newSku(row)
|
||||
console.log("new sku: " + sku)
|
||||
createPhotoFolderForSku(config, String(sku))
|
||||
} catch (error) {
|
||||
console.log("Error in newSkuHandler: " + error.message)
|
||||
} finally {
|
||||
documentLock.releaseLock()
|
||||
}
|
||||
}
|
||||
|
||||
export function newSku(row: number) {
|
||||
@ -62,4 +77,6 @@ export function newSku(row: number) {
|
||||
let newId = maxId + 1
|
||||
console.log("newId: " + newId)
|
||||
idCell.setValue(newId)
|
||||
|
||||
return `${skuPrefixCellValue}-${newId.toString().padStart(4, "0")}`
|
||||
}
|
||||
|
||||
119
src/onEditQueue.ts
Normal file
119
src/onEditQueue.ts
Normal file
@ -0,0 +1,119 @@
|
||||
import { getCellValueByColumnName } from "./sheetUtils"
|
||||
import { Product } from "./Product"
|
||||
import { Shop } from "./shopifyApi"
|
||||
|
||||
// --- Constants ---
|
||||
const BATCH_INTERVAL_MS = 30 * 1000 // 30 seconds
|
||||
const LOCK_TIMEOUT_MS = 10 * 1000 // 10 seconds for lock acquisition
|
||||
const CACHE_KEY_EDITS = "pendingEdits"
|
||||
const CACHE_KEY_LAST_EDIT_TIME = "lastEditTime"
|
||||
const SCRIPT_PROPERTY_TRIGGER_SCHEDULED = "batchTriggerScheduled"
|
||||
|
||||
export function onEditQueue(e) {
|
||||
const sheet = e.source.getActiveSheet()
|
||||
if (sheet.getName() !== "product_inventory") {
|
||||
console.log("skipping edit on sheet " + sheet.getName())
|
||||
return
|
||||
}
|
||||
const range = e.range
|
||||
const row = range.getRow()
|
||||
const sku = getCellValueByColumnName(sheet, "sku", row)
|
||||
if (!sku) {
|
||||
console.log("No SKU found for row " + row)
|
||||
return
|
||||
}
|
||||
// Make sure SKU conforms to expected patterns
|
||||
if (sku.match(`\\?`) || sku.match(`n$`)) {
|
||||
console.log("SKU is a placeholder ('?' or 'n...'), skipping batching.")
|
||||
return
|
||||
}
|
||||
// Acquire a user lock to prevent multiple onEdit calls from clashing
|
||||
const documentLock = LockService.getDocumentLock()
|
||||
try {
|
||||
documentLock.waitLock(LOCK_TIMEOUT_MS)
|
||||
|
||||
const scriptProperties = PropertiesService.getScriptProperties() // Shared cache for all users
|
||||
|
||||
// 1. Accumulate edits in cache
|
||||
let pendingEdits = []
|
||||
try {
|
||||
pendingEdits = JSON.parse(
|
||||
scriptProperties.getProperty(CACHE_KEY_EDITS) || "[]"
|
||||
)
|
||||
} catch (e) {
|
||||
console.log("Cache corruption: " + e.message)
|
||||
scriptProperties.setProperty(CACHE_KEY_EDITS, "[]")
|
||||
}
|
||||
const existingIndex = pendingEdits.findIndex((item) => item.sku === sku)
|
||||
if (existingIndex !== -1) {
|
||||
console.log("New edit on queued SKU '"+sku+"', resetting timer...")
|
||||
pendingEdits[existingIndex].timestamp = Date.now()
|
||||
} else {
|
||||
console.log("New SKU '"+sku+"' added to queue.")
|
||||
pendingEdits.push({ sku, timestamp: Date.now() })
|
||||
}
|
||||
scriptProperties.setProperty(CACHE_KEY_EDITS, JSON.stringify(pendingEdits))
|
||||
} catch (error) {
|
||||
console.log(
|
||||
"Error in onEdit (lock acquisition or cache operation): " + error.message
|
||||
)
|
||||
} finally {
|
||||
documentLock.releaseLock()
|
||||
}
|
||||
}
|
||||
|
||||
export function processBatchedEdits() {
|
||||
const scriptLock = LockService.getScriptLock() // Use script lock for the processing function
|
||||
try {
|
||||
scriptLock.waitLock(LOCK_TIMEOUT_MS)
|
||||
|
||||
const scriptProperties = PropertiesService.getScriptProperties()
|
||||
|
||||
let pendingEdits = []
|
||||
try {
|
||||
const pendingEditsStr = scriptProperties.getProperty(CACHE_KEY_EDITS)
|
||||
pendingEdits = pendingEditsStr ? JSON.parse(pendingEditsStr) : []
|
||||
} catch (e) {
|
||||
console.log("Cache corruption: " + e.message)
|
||||
scriptProperties.setProperty(CACHE_KEY_EDITS, "[]")
|
||||
}
|
||||
|
||||
console.log(`Total SKUs in queue: ${pendingEdits.length}`)
|
||||
const now = Date.now()
|
||||
const toProcess = pendingEdits.filter(
|
||||
(edit) => now - edit.timestamp > BATCH_INTERVAL_MS
|
||||
)
|
||||
if (toProcess.length > 0) {
|
||||
let shop = new Shop()
|
||||
console.log(`Processing ${toProcess.length} SKUs...`)
|
||||
toProcess.forEach((edit) => {
|
||||
console.log(
|
||||
`Processing SKU ${edit.sku}, Timestamp: ${new Date(edit.timestamp)}`
|
||||
)
|
||||
// Make sure SKU conforms to expected patterns
|
||||
if (!edit.sku.match(/^\w+-\d{4}$/)) {
|
||||
console.log(`SKU ${edit.sku} is not valid, skipping processing.`)
|
||||
return
|
||||
}
|
||||
let p = new Product(edit.sku)
|
||||
p.UpdateShopifyProduct(shop)
|
||||
})
|
||||
|
||||
pendingEdits = pendingEdits.filter(
|
||||
edit => !toProcess.some(p => p.sku === edit.sku)
|
||||
);
|
||||
scriptProperties.setProperty(CACHE_KEY_EDITS, JSON.stringify(pendingEdits));
|
||||
|
||||
console.log(`Processed ${toProcess.length} edits.`)
|
||||
} else {
|
||||
console.log("No pending edits to process.")
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(
|
||||
"Error in processBatchedEdits (lock acquisition or processing): " +
|
||||
error.message
|
||||
)
|
||||
} finally {
|
||||
scriptLock.releaseLock()
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,10 @@ export function productTemplate(row: number) {
|
||||
"tags",
|
||||
"base_price",
|
||||
"shipping",
|
||||
"weight (grams)",
|
||||
"weight_grams",
|
||||
"product_width_cm",
|
||||
"product_depth_cm",
|
||||
"product_height_cm",
|
||||
]
|
||||
|
||||
let productInventorySheet =
|
||||
|
||||
@ -50,6 +50,16 @@ export function getColumnValuesByName(
|
||||
}
|
||||
}
|
||||
|
||||
export function getColumnRichTextByName(
|
||||
sheet: GoogleAppsScript.Spreadsheet.Sheet,
|
||||
columnName: string
|
||||
) {
|
||||
let column = getColumnRangeByName(sheet, columnName)
|
||||
if (column != null) {
|
||||
return column.getRichTextValues()
|
||||
}
|
||||
}
|
||||
|
||||
export function vlookupByColumns(
|
||||
sheetName: string,
|
||||
searchColumn: string,
|
||||
|
||||
@ -671,6 +671,43 @@ export class Shop {
|
||||
return newItem
|
||||
}
|
||||
|
||||
SetInventoryItemWeight(item: shopify.InventoryItem, config: Config, weight: number, weight_unit: shopify.WeightUnit) {
|
||||
let gql = /* GraphQL */ `
|
||||
mutation inventoryItemUpdate($id: ID!, $input: InventoryItemInput!) {
|
||||
inventoryItemUpdate(id: $id, input: $input) {
|
||||
inventoryItem {
|
||||
id
|
||||
measurement {
|
||||
weight {
|
||||
value
|
||||
unit
|
||||
}
|
||||
}
|
||||
}
|
||||
userErrors {
|
||||
field
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
let variables = {
|
||||
id: item.id,
|
||||
input: {
|
||||
measurement: {
|
||||
weight: {
|
||||
value: weight,
|
||||
unit: weight_unit
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
let query = buildGqlQuery(gql, variables)
|
||||
let response = this.shopifyGraphQLAPI(query)
|
||||
let newItem: shopify.InventoryItem = response.content
|
||||
return newItem
|
||||
}
|
||||
|
||||
shopifyAPI(endpoint: string, query: {}, next = "") {
|
||||
var options: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions = {
|
||||
method: "get",
|
||||
@ -890,6 +927,8 @@ export class ShopifyVariant {
|
||||
compareAtPrice?: number
|
||||
barcode?: string
|
||||
position?: number
|
||||
metafields?: shopify.Metafield[]
|
||||
inventory_item?: shopify.InventoryItemInput
|
||||
nodes?: ShopifyProductVariant[]
|
||||
//TODO: support multiple options
|
||||
optionValues: [{}] = [
|
||||
@ -1016,6 +1055,7 @@ export class ShopifyProductSetInput {
|
||||
title: string
|
||||
vendor: string
|
||||
variants: ShopifyVariant[]
|
||||
metafields: shopify.MetafieldInput[]
|
||||
//TODO: Support multiple product options
|
||||
productOptions: [{}] = [
|
||||
{
|
||||
|
||||
@ -10,5 +10,11 @@ export function reinstallTriggers() {
|
||||
.forSpreadsheet(ss)
|
||||
.onEdit()
|
||||
.create()
|
||||
ScriptApp.newTrigger("columnOnEditHandler").forSpreadsheet(ss).onEdit().create()
|
||||
// ScriptApp.newTrigger("columnOnEditHandler").forSpreadsheet(ss).onEdit().create()
|
||||
// ScriptApp.newTrigger("onEditQueue").forSpreadsheet(ss).onEdit().create()
|
||||
ScriptApp.newTrigger("onEditQueue").forSpreadsheet(ss).onEdit().create()
|
||||
ScriptApp.newTrigger("processBatchedEdits")
|
||||
.timeBased()
|
||||
.everyMinutes(1)
|
||||
.create()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user