1
0
Fork 0

Replace server.js with json-server.

Replace uuid with id most places.
This commit is contained in:
Brian D 2024-12-08 14:40:46 -05:00
parent bb03a2ea5f
commit f5195e8a48
12 changed files with 555 additions and 139 deletions

497
package-lock.json generated
View file

@ -31,6 +31,7 @@
"eslint": "^9.14.0",
"eslint-plugin-vue": "^9.30.0",
"jsdom": "^25.0.1",
"json-server": "^1.0.0-beta.3",
"npm-run-all2": "^7.0.1",
"postcss": "^8.4.49",
"prettier": "^3.3.3",
@ -1592,6 +1593,244 @@
"win32"
]
},
"node_modules/@tinyhttp/accepts": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@tinyhttp/accepts/-/accepts-2.2.3.tgz",
"integrity": "sha512-9pQN6pJAJOU3McmdJWTcyq7LLFW8Lj5q+DadyKcvp+sxMkEpktKX5sbfJgJuOvjk6+1xWl7pe0YL1US1vaO/1w==",
"dev": true,
"dependencies": {
"mime": "4.0.4",
"negotiator": "^0.6.3"
},
"engines": {
"node": ">=12.20.0"
},
"funding": {
"type": "individual",
"url": "https://github.com/tinyhttp/tinyhttp?sponsor=1"
}
},
"node_modules/@tinyhttp/app": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@tinyhttp/app/-/app-2.4.0.tgz",
"integrity": "sha512-vOPiCemQRJq5twnl06dde6XnWiNbVMdVRFJWW/yC/9G0qgvV2TvzNNTxrdlz6YmyB7vIC7Fg3qS6m6gx8RbBNQ==",
"dev": true,
"dependencies": {
"@tinyhttp/cookie": "2.1.1",
"@tinyhttp/proxy-addr": "2.2.0",
"@tinyhttp/req": "2.2.4",
"@tinyhttp/res": "2.2.4",
"@tinyhttp/router": "2.2.3",
"header-range-parser": "1.1.3",
"regexparam": "^2.0.2"
},
"engines": {
"node": ">=14.21.3"
},
"funding": {
"type": "individual",
"url": "https://github.com/tinyhttp/tinyhttp?sponsor=1"
}
},
"node_modules/@tinyhttp/content-disposition": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tinyhttp/content-disposition/-/content-disposition-2.2.2.tgz",
"integrity": "sha512-crXw1txzrS36huQOyQGYFvhTeLeG0Si1xu+/l6kXUVYpE0TjFjEZRqTbuadQLfKGZ0jaI+jJoRyqaWwxOSHW2g==",
"dev": true,
"engines": {
"node": ">=12.20.0"
},
"funding": {
"type": "individual",
"url": "https://github.com/tinyhttp/tinyhttp?sponsor=1"
}
},
"node_modules/@tinyhttp/content-type": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/@tinyhttp/content-type/-/content-type-0.1.4.tgz",
"integrity": "sha512-dl6f3SHIJPYbhsW1oXdrqOmLSQF/Ctlv3JnNfXAE22kIP7FosqJHxkz/qj2gv465prG8ODKH5KEyhBkvwrueKQ==",
"dev": true,
"engines": {
"node": ">=12.4"
}
},
"node_modules/@tinyhttp/cookie": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@tinyhttp/cookie/-/cookie-2.1.1.tgz",
"integrity": "sha512-h/kL9jY0e0Dvad+/QU3efKZww0aTvZJslaHj3JTPmIPC9Oan9+kYqmh3M6L5JUQRuTJYFK2nzgL2iJtH2S+6dA==",
"dev": true,
"engines": {
"node": ">=12.20.0"
},
"funding": {
"type": "individual",
"url": "https://github.com/tinyhttp/tinyhttp?sponsor=1"
}
},
"node_modules/@tinyhttp/cookie-signature": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@tinyhttp/cookie-signature/-/cookie-signature-2.1.1.tgz",
"integrity": "sha512-VDsSMY5OJfQJIAtUgeQYhqMPSZptehFSfvEEtxr+4nldPA8IImlp3QVcOVuK985g4AFR4Hl1sCbWCXoqBnVWnw==",
"dev": true,
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/cors": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@tinyhttp/cors/-/cors-2.0.1.tgz",
"integrity": "sha512-qrmo6WJuaiCzKWagv2yA/kw6hIISfF/hOqPWwmI6w0o8apeTMmRN3DoCFvQ/wNVuWVdU5J4KU7OX8aaSOEq51A==",
"dev": true,
"dependencies": {
"@tinyhttp/vary": "^0.1.3"
},
"engines": {
"node": ">=12.20 || 14.x || >=16"
}
},
"node_modules/@tinyhttp/encode-url": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@tinyhttp/encode-url/-/encode-url-2.1.1.tgz",
"integrity": "sha512-AhY+JqdZ56qV77tzrBm0qThXORbsVjs/IOPgGCS7x/wWnsa/Bx30zDUU/jPAUcSzNOzt860x9fhdGpzdqbUeUw==",
"dev": true,
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/etag": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@tinyhttp/etag/-/etag-2.1.2.tgz",
"integrity": "sha512-j80fPKimGqdmMh6962y+BtQsnYPVCzZfJw0HXjyH70VaJBHLKGF+iYhcKqzI3yef6QBNa8DKIPsbEYpuwApXTw==",
"dev": true,
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/forwarded": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@tinyhttp/forwarded/-/forwarded-2.1.1.tgz",
"integrity": "sha512-nO3kq0R1LRl2+CAMlnggm22zE6sT8gfvGbNvSitV6F9eaUSurHP0A8YZFMihSkugHxK+uIegh1TKrqgD8+lyGQ==",
"dev": true,
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/logger": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tinyhttp/logger/-/logger-2.0.0.tgz",
"integrity": "sha512-8DfLQjGDIaIJeivYamVrrpmwmsGwS8wt2DGvzlcY5HEBagdiI4QJy/veAFcUHuaJqufn4wLwmn4q5VUkW8BCpQ==",
"dev": true,
"dependencies": {
"colorette": "^2.0.20",
"dayjs": "^1.11.10",
"http-status-emojis": "^2.2.0"
},
"engines": {
"node": ">=14.18 || >=16.20"
}
},
"node_modules/@tinyhttp/proxy-addr": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@tinyhttp/proxy-addr/-/proxy-addr-2.2.0.tgz",
"integrity": "sha512-WM/PPL9xNvrs7/8Om5nhKbke5FHrP3EfjOOR+wBnjgESfibqn0K7wdUTnzSLp1lBmemr88os1XvzwymSgaibyA==",
"dev": true,
"dependencies": {
"@tinyhttp/forwarded": "2.1.1",
"ipaddr.js": "^2.2.0"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/req": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tinyhttp/req/-/req-2.2.4.tgz",
"integrity": "sha512-lQAZIAo0NOeghxFOZS57tQzxpHSPPLs9T68Krq2BncEBImKwqaDKUt7M9Y5Kb+rvC/GwIL3LeErhkg7f5iG4IQ==",
"dev": true,
"dependencies": {
"@tinyhttp/accepts": "2.2.3",
"@tinyhttp/type-is": "2.2.4",
"@tinyhttp/url": "2.1.1",
"header-range-parser": "^1.1.3"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/res": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tinyhttp/res/-/res-2.2.4.tgz",
"integrity": "sha512-ETBRShnO19oJyIg2XQHQoofXPWeTXPAuwnIVYkU8WaftvXd/Vz4y5+WFQDHUzKlmdGOw5fAFnrEU7pIVMeFeVA==",
"dev": true,
"dependencies": {
"@tinyhttp/content-disposition": "2.2.2",
"@tinyhttp/cookie": "2.1.1",
"@tinyhttp/cookie-signature": "2.1.1",
"@tinyhttp/encode-url": "2.1.1",
"@tinyhttp/req": "2.2.4",
"@tinyhttp/send": "2.2.3",
"@tinyhttp/vary": "^0.1.3",
"es-escape-html": "^0.1.1",
"mime": "4.0.4"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/router": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@tinyhttp/router/-/router-2.2.3.tgz",
"integrity": "sha512-O0MQqWV3Vpg/uXsMYg19XsIgOhwjyhTYWh51Qng7bxqXixxx2PEvZWnFjP7c84K7kU/nUX41KpkEBTLnznk9/Q==",
"dev": true,
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/send": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@tinyhttp/send/-/send-2.2.3.tgz",
"integrity": "sha512-o4cVHHGQ8WjVBS8UT0EE/2WnjoybrfXikHwsRoNlG1pfrC/Sd01u1N4Te8cOd/9aNGLr4mGxWb5qTm2RRtEi7g==",
"dev": true,
"dependencies": {
"@tinyhttp/content-type": "^0.1.4",
"@tinyhttp/etag": "2.1.2",
"mime": "4.0.4"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/type-is": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@tinyhttp/type-is/-/type-is-2.2.4.tgz",
"integrity": "sha512-7F328NheridwjIfefBB2j1PEcKKABpADgv7aCJaE8x8EON77ZFrAkI3Rir7pGjopV7V9MBmW88xUQigBEX2rmQ==",
"dev": true,
"dependencies": {
"@tinyhttp/content-type": "^0.1.4",
"mime": "4.0.4"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/url": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@tinyhttp/url/-/url-2.1.1.tgz",
"integrity": "sha512-POJeq2GQ5jI7Zrdmj22JqOijB5/GeX+LEX7DUdml1hUnGbJOTWDx7zf2b5cCERj7RoXL67zTgyzVblBJC+NJWg==",
"dev": true,
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/vary": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@tinyhttp/vary/-/vary-0.1.3.tgz",
"integrity": "sha512-SoL83sQXAGiHN1jm2VwLUWQSQeDAAl1ywOm6T0b0Cg1CZhVsjoiZadmjhxF6FHCCY7OHHVaLnTgSMxTPIDLxMg==",
"dev": true,
"engines": {
"node": ">=12.20"
}
},
"node_modules/@tsconfig/node22": {
"version": "22.0.0",
"resolved": "https://registry.npmjs.org/@tsconfig/node22/-/node22-22.0.0.tgz",
@ -2675,6 +2914,12 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/colorette": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
"dev": true
},
"node_modules/colorjs.io": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz",
@ -2793,6 +3038,12 @@
"node": ">=18"
}
},
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
"dev": true
},
"node_modules/de-indent": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
@ -2896,6 +3147,33 @@
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
},
"node_modules/dot-prop": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz",
"integrity": "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==",
"dev": true,
"dependencies": {
"type-fest": "^4.18.2"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/dot-prop/node_modules/type-fest": {
"version": "4.30.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.30.0.tgz",
"integrity": "sha512-G6zXWS1dLj6eagy6sVhOMQiLtJdxQBHIA9Z6HFUNLOlr6MFOgzV8wvmidtPONfPtEUv0uZsy77XJNzTAfwPDaA==",
"dev": true,
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@ -2965,6 +3243,15 @@
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/es-escape-html": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/es-escape-html/-/es-escape-html-0.1.1.tgz",
"integrity": "sha512-yUx1o+8RsG7UlszmYPtks+dm6Lho2m8lgHMOsLJQsFI0R8XwUJwiMhM1M4E/S8QLeGyf6MkDV/pWgjQ0tdTSyQ==",
"dev": true,
"engines": {
"node": ">=12.x"
}
},
"node_modules/es-module-lexer": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
@ -3306,6 +3593,18 @@
"node": ">=0.10.0"
}
},
"node_modules/eta": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/eta/-/eta-3.5.0.tgz",
"integrity": "sha512-e3x3FBvGzeCIHhF+zhK8FZA2vC5uFn6b4HJjegUbIWrDb4mJ7JjTGMJY9VGIbRVpmSwHopNiaJibhjIr+HfLug==",
"dev": true,
"engines": {
"node": ">=6.0.0"
},
"funding": {
"url": "https://github.com/eta-dev/eta?sponsor=1"
}
},
"node_modules/execa": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
@ -3635,6 +3934,15 @@
"he": "bin/he"
}
},
"node_modules/header-range-parser": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/header-range-parser/-/header-range-parser-1.1.3.tgz",
"integrity": "sha512-B9zCFt3jH8g09LR1vHL4pcAn8yMEtlSlOUdQemzHMRKMImNIhhszdeosYFfNW0WXKQtXIlWB+O4owHJKvEJYaA==",
"dev": true,
"engines": {
"node": ">=12.22.0"
}
},
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
@ -3678,6 +3986,12 @@
"node": ">= 14"
}
},
"node_modules/http-status-emojis": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/http-status-emojis/-/http-status-emojis-2.2.0.tgz",
"integrity": "sha512-ompKtgwpx8ff0hsbpIB7oE4ax1LXoHmftsHHStMELX56ivG3GhofTX8ZHWlUaFKfGjcGjw6G3rPk7dJRXMmbbg==",
"dev": true
},
"node_modules/https-proxy-agent": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
@ -3752,12 +4066,30 @@
"node": ">=0.8.19"
}
},
"node_modules/inflection": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/inflection/-/inflection-3.0.0.tgz",
"integrity": "sha512-1zEJU1l19SgJlmwqsEyFTbScw/tkMHFenUo//Y0i+XEP83gDFdMvPizAD/WGcE+l1ku12PcTVHQhO6g5E0UCMw==",
"dev": true,
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
"node_modules/ipaddr.js": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
"integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==",
"dev": true,
"engines": {
"node": ">= 10"
}
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@ -4053,6 +4385,87 @@
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
},
"node_modules/json-server": {
"version": "1.0.0-beta.3",
"resolved": "https://registry.npmjs.org/json-server/-/json-server-1.0.0-beta.3.tgz",
"integrity": "sha512-DwE69Ep5ccwIJZBUIWEENC30Yj8bwr4Ax9W9VoIWAYnB8Sj4ReptscO8/DRHv/nXwVlmb3Bk73Ls86+VZdYkkA==",
"dev": true,
"dependencies": {
"@tinyhttp/app": "^2.4.0",
"@tinyhttp/cors": "^2.0.1",
"@tinyhttp/logger": "^2.0.0",
"chalk": "^5.3.0",
"chokidar": "^4.0.1",
"dot-prop": "^9.0.0",
"eta": "^3.5.0",
"inflection": "^3.0.0",
"json5": "^2.2.3",
"lowdb": "^7.0.1",
"milliparsec": "^4.0.0",
"sirv": "^2.0.4",
"sort-on": "^6.1.0"
},
"bin": {
"json-server": "lib/bin.js"
},
"engines": {
"node": ">=18.3"
}
},
"node_modules/json-server/node_modules/chalk": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
"dev": true,
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/json-server/node_modules/chokidar": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz",
"integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==",
"dev": true,
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/json-server/node_modules/readdirp": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
"integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==",
"dev": true,
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/json-server/node_modules/sirv": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz",
"integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==",
"dev": true,
"dependencies": {
"@polka/url": "^1.0.0-next.24",
"mrmime": "^2.0.0",
"totalist": "^3.0.0"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
@ -4157,6 +4570,21 @@
"integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==",
"dev": true
},
"node_modules/lowdb": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/lowdb/-/lowdb-7.0.1.tgz",
"integrity": "sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==",
"dev": true,
"dependencies": {
"steno": "^4.0.2"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
@ -4205,6 +4633,30 @@
"node": ">=8.6"
}
},
"node_modules/milliparsec": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/milliparsec/-/milliparsec-4.0.0.tgz",
"integrity": "sha512-/wk9d4Z6/9ZvoEH/6BI4TrTCgmkpZPuSRN/6fI9aUHOfXdNTuj/VhLS7d+NqG26bi6L9YmGXutVYvWC8zQ0qtA==",
"dev": true,
"engines": {
"node": ">=20"
}
},
"node_modules/mime": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz",
"integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==",
"dev": true,
"funding": [
"https://github.com/sponsors/broofa"
],
"bin": {
"mime": "bin/cli.js"
},
"engines": {
"node": ">=16"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@ -4320,6 +4772,15 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"node_modules/negotiator": {
"version": "0.6.4",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
"integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/node-releases": {
"version": "2.0.18",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
@ -5025,6 +5486,15 @@
"node": ">=8.10.0"
}
},
"node_modules/regexparam": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.2.tgz",
"integrity": "sha512-A1PeDEYMrkLrfyOwv2jwihXbo9qxdGD3atBYQA9JJgreAx8/7rC6IUkWOw2NQlOxLp2wL0ifQbh1HuidDfYA6w==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
@ -5619,6 +6089,21 @@
"node": ">=18"
}
},
"node_modules/sort-on": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/sort-on/-/sort-on-6.1.0.tgz",
"integrity": "sha512-WTECP0nYNWO1n2g5bpsV0yZN9cBmZsF8ThHFbOqVN0HBFRoaQZLLEMvMmJlKHNPYQeVngeI5+jJzIfFqOIo1OA==",
"dev": true,
"dependencies": {
"dot-prop": "^9.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@ -5648,6 +6133,18 @@
"integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==",
"dev": true
},
"node_modules/steno": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/steno/-/steno-4.0.2.tgz",
"integrity": "sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A==",
"dev": true,
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",

View file

@ -4,7 +4,7 @@
"private": true,
"type": "module",
"scripts": {
"server": "node server.js",
"server": "npx json-server --port 8000 db.json",
"dev": "vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
@ -38,6 +38,7 @@
"eslint": "^9.14.0",
"eslint-plugin-vue": "^9.30.0",
"jsdom": "^25.0.1",
"json-server": "^1.0.0-beta.3",
"npm-run-all2": "^7.0.1",
"postcss": "^8.4.49",
"prettier": "^3.3.3",

View file

@ -1,84 +0,0 @@
import http from "http";
const host = '127.0.0.1';
const port = 8000;
const users = {
"joe": {
name: "Joe User",
sticker_ids: [],
username: "joe",
},
"jen": {
name: "Jen User",
sticker_ids: ["38dafe9b-5563-4112-afa8-c895adc68e5b"],
username: "jen",
}
};
const stickers = {
"88ae126f-b19a-4287-abe0-a8f5ac763cb7": {
color: "780606",
layout: "layout1",
message1: "I ♥ Medicare All",
owner: null,
uuid: "88ae126f-b19a-4287-abe0-a8f5ac763cb7",
},
"38dafe9b-5563-4112-afa8-c895adc68e5b": {
color: "008800",
layout: "layout1",
message1: "I am a treehugger!",
owner: null,
uuid: "38dafe9b-5563-4112-afa8-c895adc68e5b",
},
}
const requestListener = function (req, res) {
res.setHeader("Content-Type", "application/json");
const urlParts = req.url.split("/");
console.log(urlParts);
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
if (body) {
body = JSON.parse(body);
}
console.log('body', body);
switch (urlParts[1]) {
case "login":
res.writeHead(200);
res.end(JSON.stringify(users[body["username"]]));
break;
case "sticker":
if (!(urlParts[2] in stickers)) {
res.writeHead(404);
res.end('not found')
break;
}
res.writeHead(200);
const sticker = stickers[urlParts[2]];
const response = JSON.stringify(sticker);
res.end(response);
break;
case "user":
if (!(urlParts[2] in users)) {
res.writeHead(404);
res.end('not found')
break;
}
res.writeHead(200);
res.end(JSON.stringify(users[urlParts[2]]));
break;
default:
res.writeHead(200);
res.end(JSON.stringify({nothing: 'here'}));
}
});
};
const server = http.createServer(requestListener);
server.listen(port, host, () => {
console.log(`Server is running on http://${host}:${port}`);
});

View file

View file

@ -12,21 +12,21 @@ import {
export function useSticker() {
let sticker: Ref<StickerType> = ref<StickerType>(activist);
const route = useRoute();
if (!("uuid" in route.params)) {
if (!("id" in route.params)) {
return sticker;
}
const uuid = ref<string>(route.params.uuid as string);
const id = ref<string>(route.params.id as string);
const stickersStore = useStickersStore();
const { getSticker } = stickersStore;
onBeforeMount(async () => {
await stickersStore.fetch(uuid.value);
let sticker2 = getSticker(uuid.value);
await stickersStore.fetch(id.value);
let sticker2 = getSticker(id.value);
if (!sticker2) {
return
}
sticker.value = sticker2;
stickersStore.activeSticker = uuid.value
stickersStore.activeSticker = id.value
});
return sticker;

View file

@ -10,7 +10,7 @@ import StickerView from '../views/StickerView.vue'
import WelcomeView from '../views/WelcomeView.vue'
const uuid: string = ':uuid([0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12})'
const id: string = ':id([0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12})'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@ -45,8 +45,8 @@ const router = createRouter({
title: 'Sticker Builder',
},
name: 'stickerbuilder',
path: `/stickerbuilder/${uuid}`,
// TODO: Consider using /:uuid/edit
path: `/stickerbuilder/${id}`,
// TODO: Consider using /:id/edit
},
{
component: StickerView,
@ -54,7 +54,7 @@ const router = createRouter({
title: 'Sticker',
},
name: 'sticker',
path: `/${uuid}`,
path: `/${id}`,
},
{
component: LoginView,

View file

@ -22,22 +22,21 @@ export const useSessionStore = defineStore('session', {
actions: {
async login(username: string, password: string) {
const response = await fetch(
`/api/login`,
`/api/session`,
{
method: 'POST',
body: JSON.stringify({username, password}),
},
);
const json = await response.json();
console.log('login', json);
// this.user.name = json.name;
this.user = {
name: json.name,
sticker_ids: json.sticker_ids,
username: json.username,
};
console.log('session created', json);
// Fetch the user record.
const userStore= useUserStore();
userStore.addUser(this.user);
let user = await userStore.fetch(json.username);
console.log('user', user);
if (user) {
this.user = user;
}
},
logout() {
console.log('logout');

View file

@ -12,7 +12,7 @@ export interface Sticker {
message3: string | null,
message4: string | null,
owner: string | null,
uuid: string,
id: string,
}
export const activist: Sticker = {
@ -23,34 +23,34 @@ export const activist: Sticker = {
message3: null,
message4: null,
owner: null,
uuid: '6dcd2dae-7be2-4f79-8b10-caeb379452fc',
id: '6dcd2dae-7be2-4f79-8b10-caeb379452fc',
};
export interface State {
activeSticker: string | null; // uuid
activeSticker: string | null; // id
stickers: Sticker[];
}
export const useStickersStore = defineStore('stickers', {
actions: {
async fetch(uuid: string) {
if (this.getSticker(uuid)) {
async fetch(id: string) {
if (this.getSticker(id)) {
return;
}
// TODO: Check if we have it already and if it's stale.
const response = await fetch(
`/api/sticker/${uuid}`,
`/api/sticker/${id}`,
);
const json = await response.json();
this.stickers.push(json);
},
async put(uuid: string) {
const sticker = this.getSticker(uuid)
async put(id: string) {
const sticker = this.getSticker(id)
if (!sticker) {
return;
}
const response = await fetch(
`/api/sticker/${uuid}`,
`/api/sticker/${id}`,
{
body: JSON.stringify(sticker),
method: 'PUT',
@ -62,15 +62,15 @@ export const useStickersStore = defineStore('stickers', {
},
setOwner(sticker: Sticker, user: User) {
sticker.owner = user.username;
this.put(sticker.uuid);
this.put(sticker.id);
const userStore= useUserStore();
userStore.addSticker(user.username, sticker.uuid);
userStore.addSticker(user.username, sticker.id);
},
},
getters: {
getSticker: (state: State) => {
return (uuid: string): Sticker | undefined => {
return state.stickers.find((sticker: Sticker) => sticker.uuid === uuid)
return (id: string): Sticker | undefined => {
return state.stickers.find((sticker: Sticker) => sticker.id === id)
};
},
},

View file

@ -10,10 +10,10 @@ export interface State {
export const useUserStore = defineStore('user', {
actions: {
addSticker(username: string, uuid: string) {
addSticker(username: string, id: string) {
let user = this.getUser(username);
if (user) {
user.sticker_ids.push(uuid);
user.sticker_ids.push(id);
}
},
addUser(user: User) {
@ -21,20 +21,23 @@ export const useUserStore = defineStore('user', {
},
async fetch(username: string) {
let user = this.getUser(username);
if (user) {
return user;
}
// TODO: Check if we have it already and if it's stale.
const response = await fetch(
`/api/user/${username}`,
);
const json = await response.json();
this.users.push(json);
if (!user) {
// TODO: Check if we have it already and if it's stale.
const response = await fetch(
`/api/user/${username}`,
);
user = await response.json();
if (user) {
this.users.push(user);
const stickersStore = useStickersStore();
json.sticker_ids.forEach((sticker_id: string) => {
stickersStore.fetch(sticker_id);
})
// prepop sticker store with user stickers
const stickersStore = useStickersStore();
user.sticker_ids.forEach((sticker_id: string) => {
stickersStore.fetch(sticker_id);
})
}
}
return user;
},
},
getters: {

View file

@ -24,7 +24,7 @@ function handleLogin({ valid }) {
console.log('Input is not valid.')
return;
}
sessionStore.login(username.value, username.value).then(() => {
sessionStore.login(username.value, password.value).then(() => {
console.log(`go to ${next}`)
router.push(next);
}).catch((error) => {

View file

@ -75,7 +75,7 @@ const events = [{
<Panel header="Stickers">
<div class="stickers">
<div class="stickerWrapper" v-for="sticker_id in user?.sticker_ids">
<RouterLink :to="{ name: 'sticker', params: { uuid: sticker_id }}">
<RouterLink :to="{ name: 'sticker', params: { id: sticker_id }}">
<Sticker v-bind="stickersStore.getSticker(sticker_id)" />
</RouterLink>
</div>

View file

@ -18,21 +18,21 @@ const sessionStore = useSessionStore();
const stickersStore = useStickersStore();
const route = useRoute();
const uuid = ref<string>(route.params.uuid as string);
const id = ref<string>(route.params.id as string);
const { getSticker } = stickersStore;
let sticker = ref<StickerType>();
onBeforeMount(async () => {
await stickersStore.fetch(uuid.value);
sticker.value = getSticker(uuid.value);
await stickersStore.fetch(id.value);
sticker.value = getSticker(id.value);
});
const first = computed(() => {
const parts = uuid.value.split('-')
const parts = id.value.split('-')
return [parts[0], parts[1], parts[2]].join('-');
})
const second = computed(() => {
const parts = uuid.value.split('-')
const parts = id.value.split('-')
return [parts[3], parts[4]].join('-');
})
@ -76,7 +76,7 @@ function claimSticker() {
</span>
<Button
as="router-link"
:to="{ name: 'stickerbuilder', params: { uuid: stickersStore.activeSticker }}"
:to="{ name: 'stickerbuilder', params: { id: stickersStore.activeSticker }}"
v-bind:disabled="sessionStore.isAnonymous"
v-if="sticker?.owner == sessionStore.user.username">
Customize my sticker!