Update supported Node.js versions and dependencies, implement TypeScript JSDoc types.
This commit is contained in:
parent
a56972742c
commit
86e5609e60
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"typescript.disableAutomaticTypeAcquisition": true,
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"typescript.tsdk": "api/node_modules/typescript/lib"
|
||||
}
|
||||
@ -1 +1,3 @@
|
||||
// @ts-check
|
||||
|
||||
export default new URL("../uploads/", import.meta.url);
|
||||
|
||||
11
api/jsconfig.json
Normal file
11
api/jsconfig.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"maxNodeModuleJsDepth": 10,
|
||||
"module": "nodenext",
|
||||
"noEmit": true,
|
||||
"strict": true
|
||||
},
|
||||
"typeAcquisition": {
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
325
api/package-lock.json
generated
325
api/package-lock.json
generated
@ -10,19 +10,22 @@
|
||||
"apollo-server-koa": "^3.7.0",
|
||||
"dotenv": "^16.0.1",
|
||||
"graphql": "^16.5.0",
|
||||
"graphql-upload": "^13.0.0",
|
||||
"graphql-upload": "^14.0.0",
|
||||
"koa": "^2.13.4",
|
||||
"make-dir": "^3.1.0",
|
||||
"shortid": "^2.2.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/koa": "^2.13.4",
|
||||
"@types/node": "^17.0.35",
|
||||
"eslint": "^8.16.0",
|
||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||
"nodemon": "^2.0.16",
|
||||
"prettier": "^2.6.2"
|
||||
"prettier": "^2.6.2",
|
||||
"typescript": "^4.7.1-rc"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >= 16.0.0",
|
||||
"node": "^14.17.0 || ^16.0.0 || >= 18.0.0",
|
||||
"npm": ">= 7"
|
||||
},
|
||||
"funding": {
|
||||
@ -283,6 +286,14 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/busboy": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-0.3.2.tgz",
|
||||
"integrity": "sha512-iEvdm9Z9KdSs/ozuh1Z7ZsXrOl8F4M/CLMXPZHr3QuJ4d6Bjn+HBMC5EMKpwpAo8oi8iK9GZfFoHaIMrrZgwVw==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/connect": {
|
||||
"version": "3.4.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
|
||||
@ -397,6 +408,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz",
|
||||
"integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg=="
|
||||
},
|
||||
"node_modules/@types/object-path": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/object-path/-/object-path-0.11.1.tgz",
|
||||
"integrity": "sha512-219LSCO9HPcoXcRTC6DbCs0FRhZgBnEMzf16RRqkT40WbkKx3mOeQuz3e2XqbfhOz/AHfbru0kzB1n1RCAsIIg=="
|
||||
},
|
||||
"node_modules/@types/qs": {
|
||||
"version": "6.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||
@ -1018,14 +1034,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/cookies/node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/copy-to": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz",
|
||||
@ -1119,11 +1127,11 @@
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/destroy": {
|
||||
@ -1649,23 +1657,36 @@
|
||||
}
|
||||
},
|
||||
"node_modules/graphql-upload": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-13.0.0.tgz",
|
||||
"integrity": "sha512-YKhx8m/uOtKu4Y1UzBFJhbBGJTlk7k4CydlUUiNrtxnwZv0WigbRHP+DVhRNKt7u7DXOtcKZeYJlGtnMXvreXA==",
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-14.0.0.tgz",
|
||||
"integrity": "sha512-l3utaN0p/VLUFFrUAijwEfmsSxEolVri5uuD91yhbOkxRD6q5l0rsy1F4Naq4TKWFSKsGciCjyrc1ZhCT2Ew7A==",
|
||||
"dependencies": {
|
||||
"@types/busboy": "^0.3.2",
|
||||
"@types/node": "*",
|
||||
"@types/object-path": "^0.11.1",
|
||||
"busboy": "^0.3.1",
|
||||
"fs-capacitor": "^6.2.0",
|
||||
"http-errors": "^1.8.1",
|
||||
"http-errors": "^2.0.0",
|
||||
"object-path": "^0.11.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >= 16.0.0"
|
||||
"node": "^14.17.0 || ^16.0.0 || >= 18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jaydenseric"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"graphql": "0.13.1 - 16"
|
||||
"@types/express": "^4.0.29",
|
||||
"@types/koa": "^2.11.4",
|
||||
"graphql": "^16.3.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/express": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/koa": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/has": {
|
||||
@ -1734,13 +1755,15 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-cache-semantics": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
|
||||
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
|
||||
"dev": true
|
||||
"node_modules/http-assert/node_modules/depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"node_modules/http-assert/node_modules/http-errors": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
|
||||
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
|
||||
@ -1755,6 +1778,35 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-assert/node_modules/statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-cache-semantics": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
|
||||
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||
"dependencies": {
|
||||
"depd": "2.0.0",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"toidentifier": "1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
@ -2100,12 +2152,35 @@
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/koa/node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
|
||||
"node_modules/koa/node_modules/http-errors": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
|
||||
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
|
||||
"dependencies": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/koa/node_modules/http-errors/node_modules/depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/koa/node_modules/statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/latest-version": {
|
||||
@ -2623,37 +2698,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body/node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body/node_modules/http-errors": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||
"dependencies": {
|
||||
"depd": "2.0.0",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"toidentifier": "1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body/node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/rc": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||
@ -2883,11 +2927,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/streamsearch": {
|
||||
@ -3058,6 +3102,19 @@
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.7.1-rc",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.1-rc.tgz",
|
||||
"integrity": "sha512-EQd2NVelDe6ZVc2sO1CSpuSs+RHzY8c2n/kTNQAHw4um/eAXY+ZY4IKoUpNK0wO6C5hN+XcUXR7yqT8VbwwNIQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undefsafe": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
|
||||
@ -3528,6 +3585,14 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/busboy": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-0.3.2.tgz",
|
||||
"integrity": "sha512-iEvdm9Z9KdSs/ozuh1Z7ZsXrOl8F4M/CLMXPZHr3QuJ4d6Bjn+HBMC5EMKpwpAo8oi8iK9GZfFoHaIMrrZgwVw==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/connect": {
|
||||
"version": "3.4.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
|
||||
@ -3642,6 +3707,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz",
|
||||
"integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg=="
|
||||
},
|
||||
"@types/object-path": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/object-path/-/object-path-0.11.1.tgz",
|
||||
"integrity": "sha512-219LSCO9HPcoXcRTC6DbCs0FRhZgBnEMzf16RRqkT40WbkKx3mOeQuz3e2XqbfhOz/AHfbru0kzB1n1RCAsIIg=="
|
||||
},
|
||||
"@types/qs": {
|
||||
"version": "6.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||
@ -4109,13 +4179,6 @@
|
||||
"requires": {
|
||||
"depd": "~2.0.0",
|
||||
"keygrip": "~1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"copy-to": {
|
||||
@ -4191,9 +4254,9 @@
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||
},
|
||||
"destroy": {
|
||||
"version": "1.2.0",
|
||||
@ -4587,13 +4650,16 @@
|
||||
}
|
||||
},
|
||||
"graphql-upload": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-13.0.0.tgz",
|
||||
"integrity": "sha512-YKhx8m/uOtKu4Y1UzBFJhbBGJTlk7k4CydlUUiNrtxnwZv0WigbRHP+DVhRNKt7u7DXOtcKZeYJlGtnMXvreXA==",
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-14.0.0.tgz",
|
||||
"integrity": "sha512-l3utaN0p/VLUFFrUAijwEfmsSxEolVri5uuD91yhbOkxRD6q5l0rsy1F4Naq4TKWFSKsGciCjyrc1ZhCT2Ew7A==",
|
||||
"requires": {
|
||||
"@types/busboy": "^0.3.2",
|
||||
"@types/node": "*",
|
||||
"@types/object-path": "^0.11.1",
|
||||
"busboy": "^0.3.1",
|
||||
"fs-capacitor": "^6.2.0",
|
||||
"http-errors": "^1.8.1",
|
||||
"http-errors": "^2.0.0",
|
||||
"object-path": "^0.11.8"
|
||||
}
|
||||
},
|
||||
@ -4637,6 +4703,30 @@
|
||||
"requires": {
|
||||
"deep-equal": "~1.0.1",
|
||||
"http-errors": "~1.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
|
||||
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.1"
|
||||
}
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
}
|
||||
}
|
||||
},
|
||||
"http-cache-semantics": {
|
||||
@ -4646,14 +4736,14 @@
|
||||
"dev": true
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
|
||||
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"depd": "2.0.0",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"statuses": "2.0.1",
|
||||
"toidentifier": "1.0.1"
|
||||
}
|
||||
},
|
||||
@ -4898,10 +4988,29 @@
|
||||
"vary": "^1.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||
"http-errors": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
|
||||
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
|
||||
}
|
||||
}
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -5291,30 +5400,6 @@
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||
"requires": {
|
||||
"depd": "2.0.0",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"toidentifier": "1.0.1"
|
||||
}
|
||||
},
|
||||
"statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"rc": {
|
||||
@ -5483,9 +5568,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
|
||||
},
|
||||
"streamsearch": {
|
||||
"version": "0.1.2",
|
||||
@ -5610,6 +5695,12 @@
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.7.1-rc",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.1-rc.tgz",
|
||||
"integrity": "sha512-EQd2NVelDe6ZVc2sO1CSpuSs+RHzY8c2n/kTNQAHw4um/eAXY+ZY4IKoUpNK0wO6C5hN+XcUXR7yqT8VbwwNIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"undefsafe": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
|
||||
|
||||
@ -16,29 +16,33 @@
|
||||
"bugs": "https://github.com/jaydenseric/apollo-upload-examples/issues",
|
||||
"funding": "https://github.com/sponsors/jaydenseric",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >= 16.0.0",
|
||||
"node": "^14.17.0 || ^16.0.0 || >= 18.0.0",
|
||||
"npm": ">= 7"
|
||||
},
|
||||
"dependencies": {
|
||||
"apollo-server-koa": "^3.7.0",
|
||||
"dotenv": "^16.0.1",
|
||||
"graphql": "^16.5.0",
|
||||
"graphql-upload": "^13.0.0",
|
||||
"graphql-upload": "^14.0.0",
|
||||
"koa": "^2.13.4",
|
||||
"make-dir": "^3.1.0",
|
||||
"shortid": "^2.2.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/koa": "^2.13.4",
|
||||
"@types/node": "^17.0.35",
|
||||
"eslint": "^8.16.0",
|
||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||
"nodemon": "^2.0.16",
|
||||
"prettier": "^2.6.2"
|
||||
"prettier": "^2.6.2",
|
||||
"typescript": "^4.7.1-rc"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "nodemon",
|
||||
"start": "node -r dotenv/config server.mjs",
|
||||
"eslint": "eslint .",
|
||||
"prettier": "prettier -c .",
|
||||
"test": "npm run eslint && npm run prettier"
|
||||
"types": "tsc -p jsconfig.json",
|
||||
"test": "npm run eslint && npm run prettier && npm run types"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// @ts-check
|
||||
|
||||
import { GraphQLNonNull, GraphQLObjectType, GraphQLString } from "graphql";
|
||||
|
||||
import UPLOAD_DIRECTORY_URL from "../config/UPLOAD_DIRECTORY_URL.mjs";
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
// @ts-check
|
||||
|
||||
import { GraphQLList, GraphQLNonNull, GraphQLObjectType } from "graphql";
|
||||
import GraphQLUpload from "graphql-upload/public/GraphQLUpload.js";
|
||||
import GraphQLUpload from "graphql-upload/GraphQLUpload.js";
|
||||
|
||||
import storeUpload from "../storeUpload.mjs";
|
||||
import FileType from "./FileType.mjs";
|
||||
@ -29,15 +31,25 @@ export default new GraphQLObjectType({
|
||||
),
|
||||
},
|
||||
},
|
||||
async resolve(parent, { files }) {
|
||||
async resolve(
|
||||
parent,
|
||||
/**
|
||||
* @type {{ files: Array<
|
||||
* Promise<import("graphql-upload/processRequest.js").FileUpload>
|
||||
* >}}
|
||||
*/
|
||||
{ files }
|
||||
) {
|
||||
/** @type {Array<string>} */
|
||||
const storedFileNames = [];
|
||||
|
||||
// Ensure an error storing one upload doesn’t prevent storing the rest.
|
||||
const results = await Promise.allSettled(files.map(storeUpload));
|
||||
return results.reduce((storedFiles, { value, reason }) => {
|
||||
if (value) storedFiles.push(value);
|
||||
for (const result of await Promise.allSettled(files.map(storeUpload)))
|
||||
if ("value" in result) storedFileNames.push(result.value);
|
||||
// Realistically you would do more than just log an error.
|
||||
else console.error(`Failed to store upload: ${reason}`);
|
||||
return storedFiles;
|
||||
}, []);
|
||||
else console.error(`Failed to store upload: ${result.reason}`);
|
||||
|
||||
return storedFileNames;
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// @ts-check
|
||||
|
||||
import fs from "fs";
|
||||
import { GraphQLList, GraphQLNonNull, GraphQLObjectType } from "graphql";
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// @ts-check
|
||||
|
||||
import { GraphQLSchema } from "graphql";
|
||||
|
||||
import MutationType from "./MutationType.mjs";
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
// @ts-check
|
||||
|
||||
import { ApolloServer } from "apollo-server-koa";
|
||||
import graphqlUploadKoa from "graphql-upload/public/graphqlUploadKoa.js";
|
||||
import graphqlUploadKoa from "graphql-upload/graphqlUploadKoa.js";
|
||||
import Koa from "koa";
|
||||
import makeDir from "make-dir";
|
||||
import { fileURLToPath } from "url";
|
||||
@ -7,9 +9,7 @@ import { fileURLToPath } from "url";
|
||||
import UPLOAD_DIRECTORY_URL from "./config/UPLOAD_DIRECTORY_URL.mjs";
|
||||
import schema from "./schema/index.mjs";
|
||||
|
||||
/**
|
||||
* Starts the API server.
|
||||
*/
|
||||
/** Starts the API server. */
|
||||
async function startServer() {
|
||||
// Ensure the upload directory exists.
|
||||
await makeDir(fileURLToPath(UPLOAD_DIRECTORY_URL));
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// @ts-check
|
||||
|
||||
import { createWriteStream, unlink } from "fs";
|
||||
import shortId from "shortid";
|
||||
|
||||
@ -5,7 +7,9 @@ import UPLOAD_DIRECTORY_URL from "./config/UPLOAD_DIRECTORY_URL.mjs";
|
||||
|
||||
/**
|
||||
* Stores a GraphQL file upload in the filesystem.
|
||||
* @param {Promise<object>} upload GraphQL file upload.
|
||||
* @param {Promise<
|
||||
* import("graphql-upload/processRequest.js").FileUpload
|
||||
* >} upload GraphQL file upload.
|
||||
* @returns {Promise<string>} Resolves the stored file name.
|
||||
*/
|
||||
export default async function storeUpload(upload) {
|
||||
|
||||
@ -1,6 +1,14 @@
|
||||
// @ts-check
|
||||
|
||||
import { createElement as h } from "react";
|
||||
|
||||
import styles from "./Header.module.css";
|
||||
|
||||
export const Header = (props) =>
|
||||
h("header", { ...props, className: styles.header });
|
||||
/**
|
||||
* React component for a header.
|
||||
* @param {object} props Props.
|
||||
* @param {import("react").ReactNode} [props.children] Children.
|
||||
*/
|
||||
export default function Header({ children }) {
|
||||
return h("header", { className: styles.header }, children);
|
||||
}
|
||||
|
||||
@ -1,11 +1,19 @@
|
||||
import Head from "next/head";
|
||||
import PropTypes from "prop-types";
|
||||
// @ts-check
|
||||
|
||||
import nextHead from "next/head.js";
|
||||
import { createElement as h, Fragment } from "react";
|
||||
|
||||
export const Page = ({ title, children }) =>
|
||||
h(Fragment, null, h(Head, null, h("title", null, title)), children);
|
||||
|
||||
Page.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
/**
|
||||
* React component for a page.
|
||||
* @param {object} props Props.
|
||||
* @param {string} props.title Title.
|
||||
* @param {import("react").ReactNode} [props.children] Children.
|
||||
*/
|
||||
export default function Page({ title, children }) {
|
||||
return h(
|
||||
Fragment,
|
||||
null,
|
||||
h(nextHead.default, null, h("title", null, title)),
|
||||
children
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,6 +1,14 @@
|
||||
// @ts-check
|
||||
|
||||
import { createElement as h } from "react";
|
||||
|
||||
import styles from "./Section.module.css";
|
||||
|
||||
export const Section = (props) =>
|
||||
h("section", { ...props, className: styles.section });
|
||||
/**
|
||||
* React component for a section.
|
||||
* @param {object} props Props.
|
||||
* @param {import("react").ReactNode} [props.children] Children.
|
||||
*/
|
||||
export default function Section({ children }) {
|
||||
return h("section", { className: styles.section }, children);
|
||||
}
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
import { gql, useApolloClient, useMutation } from "@apollo/client";
|
||||
// @ts-check
|
||||
|
||||
import { gql } from "@apollo/client/core";
|
||||
import { useApolloClient } from "@apollo/client/react/hooks/useApolloClient.js";
|
||||
import { useMutation } from "@apollo/client/react/hooks/useMutation.js";
|
||||
import ButtonSubmit from "device-agnostic-ui/ButtonSubmit.mjs";
|
||||
import Code from "device-agnostic-ui/Code.mjs";
|
||||
import Fieldset from "device-agnostic-ui/Fieldset.mjs";
|
||||
@ -13,7 +17,8 @@ const SINGLE_UPLOAD_MUTATION = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export function UploadBlob() {
|
||||
/** React component for a uploading a blob. */
|
||||
export default function UploadBlob() {
|
||||
const [name, setName] = useState("");
|
||||
const [content, setContent] = useState("");
|
||||
const [singleUploadMutation, { loading }] = useMutation(
|
||||
@ -21,18 +26,36 @@ export function UploadBlob() {
|
||||
);
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const onNameChange = ({ target: { value } }) => setName(value);
|
||||
const onContentChange = ({ target: { value } }) => setContent(value);
|
||||
const onSubmit = (event) => {
|
||||
/**
|
||||
* @type {import("react").ChangeEventHandler<
|
||||
* HTMLInputElement | HTMLTextAreaElement
|
||||
* >}
|
||||
*/
|
||||
function onNameChange({ target: { value } }) {
|
||||
setName(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {import("react").ChangeEventHandler<
|
||||
* HTMLInputElement | HTMLTextAreaElement
|
||||
* >}
|
||||
*/
|
||||
function onContentChange({ target: { value } }) {
|
||||
setContent(value);
|
||||
}
|
||||
|
||||
/** @type {import("react").FormEventHandler<HTMLFormElement>} */
|
||||
function onSubmit(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const file = new Blob([content], { type: "text/plain" });
|
||||
file.name = `${name}.txt`;
|
||||
|
||||
singleUploadMutation({ variables: { file } }).then(() => {
|
||||
singleUploadMutation({
|
||||
variables: {
|
||||
file: new File([content], `${name}.txt`, { type: "text/plain" }),
|
||||
},
|
||||
}).then(() => {
|
||||
apolloClient.resetStore();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return h(
|
||||
"form",
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
import { gql, useApolloClient, useMutation } from "@apollo/client";
|
||||
// @ts-check
|
||||
|
||||
import { gql } from "@apollo/client/core";
|
||||
import { useApolloClient } from "@apollo/client/react/hooks/useApolloClient.js";
|
||||
import { useMutation } from "@apollo/client/react/hooks/useMutation.js";
|
||||
import { createElement as h } from "react";
|
||||
|
||||
const SINGLE_UPLOAD_MUTATION = gql`
|
||||
@ -9,20 +13,18 @@ const SINGLE_UPLOAD_MUTATION = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export function UploadFile() {
|
||||
/** React component for a uploading a single file. */
|
||||
export default function UploadFile() {
|
||||
const [uploadFileMutation] = useMutation(SINGLE_UPLOAD_MUTATION);
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const onChange = ({
|
||||
target: {
|
||||
validity,
|
||||
files: [file],
|
||||
},
|
||||
}) =>
|
||||
validity.valid &&
|
||||
uploadFileMutation({ variables: { file } }).then(() => {
|
||||
apolloClient.resetStore();
|
||||
});
|
||||
/** @type {import("react").ChangeEventHandler<HTMLInputElement>} */
|
||||
function onChange({ target: { validity, files } }) {
|
||||
if (validity.valid && files && files[0])
|
||||
uploadFileMutation({ variables: { file: files[0] } }).then(() => {
|
||||
apolloClient.resetStore();
|
||||
});
|
||||
}
|
||||
|
||||
return h("input", { type: "file", required: true, onChange });
|
||||
}
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
import { gql, useApolloClient, useMutation } from "@apollo/client";
|
||||
// @ts-check
|
||||
|
||||
import { gql } from "@apollo/client/core";
|
||||
import { useApolloClient } from "@apollo/client/react/hooks/useApolloClient.js";
|
||||
import { useMutation } from "@apollo/client/react/hooks/useMutation.js";
|
||||
import { createElement as h } from "react";
|
||||
|
||||
const MULTIPLE_UPLOAD_MUTATION = gql`
|
||||
@ -9,15 +13,33 @@ const MULTIPLE_UPLOAD_MUTATION = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export function UploadFileList() {
|
||||
const [multipleUploadMutation] = useMutation(MULTIPLE_UPLOAD_MUTATION);
|
||||
/**
|
||||
* @typedef {{
|
||||
* multipleUpload: {
|
||||
* id: string,
|
||||
* },
|
||||
* }} MultipleUploadMutationData
|
||||
*/
|
||||
|
||||
/** React component for a uploading a file list. */
|
||||
export default function UploadFileList() {
|
||||
const [multipleUploadMutation] =
|
||||
/**
|
||||
* @type {import("@apollo/client/react/types/types.js").MutationTuple<
|
||||
* MultipleUploadMutationData,
|
||||
* { files: FileList }
|
||||
* >}
|
||||
*/
|
||||
(useMutation(MULTIPLE_UPLOAD_MUTATION));
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const onChange = ({ target: { validity, files } }) =>
|
||||
validity.valid &&
|
||||
multipleUploadMutation({ variables: { files } }).then(() => {
|
||||
apolloClient.resetStore();
|
||||
});
|
||||
/** @type {import("react").ChangeEventHandler<HTMLInputElement>} */
|
||||
function onChange({ target: { validity, files } }) {
|
||||
if (validity.valid && files && files[0])
|
||||
multipleUploadMutation({ variables: { files } }).then(() => {
|
||||
apolloClient.resetStore();
|
||||
});
|
||||
}
|
||||
|
||||
return h("input", { type: "file", multiple: true, required: true, onChange });
|
||||
}
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
import { gql, useQuery } from "@apollo/client";
|
||||
// @ts-check
|
||||
|
||||
import { gql } from "@apollo/client/core";
|
||||
import { useQuery } from "@apollo/client/react/hooks/useQuery.js";
|
||||
import Scroll from "device-agnostic-ui/Scroll.mjs";
|
||||
import Table from "device-agnostic-ui/Table.mjs";
|
||||
import { createElement as h } from "react";
|
||||
@ -12,8 +15,24 @@ const UPLOADS_QUERY = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export function Uploads() {
|
||||
const { data: { uploads = [] } = {} } = useQuery(UPLOADS_QUERY);
|
||||
/**
|
||||
* @typedef {{
|
||||
* uploads: Array<{
|
||||
* id: string,
|
||||
* url: string
|
||||
* }>,
|
||||
* }} UploadsQueryData
|
||||
*/
|
||||
|
||||
/** React component for displaying uploads. */
|
||||
export default function Uploads() {
|
||||
const { data: { uploads = [] } = {} } =
|
||||
/**
|
||||
* @type {import("@apollo/client/react/types/types.js").QueryResult<
|
||||
* UploadsQueryData
|
||||
* >}
|
||||
*/
|
||||
(useQuery(UPLOADS_QUERY));
|
||||
|
||||
return h(
|
||||
Scroll,
|
||||
|
||||
11
app/jsconfig.json
Normal file
11
app/jsconfig.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"maxNodeModuleJsDepth": 10,
|
||||
"module": "nodenext",
|
||||
"noEmit": true,
|
||||
"strict": true
|
||||
},
|
||||
"typeAcquisition": {
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
// @ts-check
|
||||
|
||||
export default {
|
||||
env: {
|
||||
API_URI: process.env.API_URI,
|
||||
|
||||
116
app/package-lock.json
generated
116
app/package-lock.json
generated
@ -12,12 +12,14 @@
|
||||
"device-agnostic-ui": "~10.0.0",
|
||||
"graphql": "^16.5.0",
|
||||
"next": "^12.1.6",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.17.0",
|
||||
"@types/node": "^17.0.35",
|
||||
"@types/react": "^17.0.45",
|
||||
"@types/react-dom": "^17.0.17",
|
||||
"babel-plugin-graphql-tag": "^3.3.0",
|
||||
"eslint": "^8.16.0",
|
||||
"eslint-plugin-react-hooks": "^4.5.0",
|
||||
@ -25,10 +27,11 @@
|
||||
"prettier": "^2.6.2",
|
||||
"stylelint": "^14.8.3",
|
||||
"stylelint-config-recommended": "^7.0.0",
|
||||
"stylelint-prettier": "^2.0.0"
|
||||
"stylelint-prettier": "^2.0.0",
|
||||
"typescript": "^4.7.1-rc"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >= 16.0.0",
|
||||
"node": "^14.17.0 || ^16.0.0 || >= 18.0.0",
|
||||
"npm": ">= 7"
|
||||
},
|
||||
"funding": {
|
||||
@ -764,6 +767,12 @@
|
||||
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "17.0.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz",
|
||||
"integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/normalize-package-data": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
|
||||
@ -776,6 +785,38 @@
|
||||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "17.0.45",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.45.tgz",
|
||||
"integrity": "sha512-YfhQ22Lah2e3CHPsb93tRwIGNiSwkuz1/blk4e6QrWS0jQzCSNbGLtOEYhPg02W0yGTTmpajp7dCTbBAMN3qsg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
"version": "17.0.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.17.tgz",
|
||||
"integrity": "sha512-VjnqEmqGnasQKV0CWLevqMTXBYG9GbwuE6x3VetERLh0cq2LTptFE73MrQi2S7GkKXCf2GgwItB/melLnxfnsg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/react": "^17"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/scheduler": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@wry/context": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@wry/context/-/context-0.6.1.tgz",
|
||||
@ -1181,6 +1222,12 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
|
||||
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@ -3637,6 +3684,19 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.7.1-rc",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.1-rc.tgz",
|
||||
"integrity": "sha512-EQd2NVelDe6ZVc2sO1CSpuSs+RHzY8c2n/kTNQAHw4um/eAXY+ZY4IKoUpNK0wO6C5hN+XcUXR7yqT8VbwwNIQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
@ -4234,6 +4294,12 @@
|
||||
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "17.0.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz",
|
||||
"integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/normalize-package-data": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
|
||||
@ -4246,6 +4312,38 @@
|
||||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "17.0.45",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.45.tgz",
|
||||
"integrity": "sha512-YfhQ22Lah2e3CHPsb93tRwIGNiSwkuz1/blk4e6QrWS0jQzCSNbGLtOEYhPg02W0yGTTmpajp7dCTbBAMN3qsg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"version": "17.0.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.17.tgz",
|
||||
"integrity": "sha512-VjnqEmqGnasQKV0CWLevqMTXBYG9GbwuE6x3VetERLh0cq2LTptFE73MrQi2S7GkKXCf2GgwItB/melLnxfnsg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "^17"
|
||||
}
|
||||
},
|
||||
"@types/scheduler": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
|
||||
"dev": true
|
||||
},
|
||||
"@wry/context": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@wry/context/-/context-0.6.1.tgz",
|
||||
@ -4530,6 +4628,12 @@
|
||||
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"csstype": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
|
||||
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@ -6316,6 +6420,12 @@
|
||||
"integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==",
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.7.1-rc",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.1-rc.tgz",
|
||||
"integrity": "sha512-EQd2NVelDe6ZVc2sO1CSpuSs+RHzY8c2n/kTNQAHw4um/eAXY+ZY4IKoUpNK0wO6C5hN+XcUXR7yqT8VbwwNIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
|
||||
@ -16,22 +16,24 @@
|
||||
"bugs": "https://github.com/jaydenseric/apollo-upload-examples/issues",
|
||||
"funding": "https://github.com/sponsors/jaydenseric",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >= 16.0.0",
|
||||
"node": "^14.17.0 || ^16.0.0 || >= 18.0.0",
|
||||
"npm": ">= 7"
|
||||
},
|
||||
"browserslist": "Node 12.22 - 13 and Node < 13, Node 14.17 - 15 and Node < 15, Node >= 16, > 0.5%, not OperaMini all, not IE > 0, not dead",
|
||||
"browserslist": "Node 14.17 - 15 and Node < 15, Node 16 - 17 and Node < 17, Node >= 18, > 0.5%, not OperaMini all, not IE > 0, not dead",
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.6.4",
|
||||
"apollo-upload-client": "^17.0.0",
|
||||
"device-agnostic-ui": "~10.0.0",
|
||||
"graphql": "^16.5.0",
|
||||
"next": "^12.1.6",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.17.0",
|
||||
"@types/node": "^17.0.35",
|
||||
"@types/react": "^17.0.45",
|
||||
"@types/react-dom": "^17.0.17",
|
||||
"babel-plugin-graphql-tag": "^3.3.0",
|
||||
"eslint": "^8.16.0",
|
||||
"eslint-plugin-react-hooks": "^4.5.0",
|
||||
@ -39,7 +41,8 @@
|
||||
"prettier": "^2.6.2",
|
||||
"stylelint": "^14.8.3",
|
||||
"stylelint-config-recommended": "^7.0.0",
|
||||
"stylelint-prettier": "^2.0.0"
|
||||
"stylelint-prettier": "^2.0.0",
|
||||
"typescript": "^4.7.1-rc"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
@ -48,6 +51,7 @@
|
||||
"eslint": "eslint .",
|
||||
"stylelint": "stylelint '**/*.css'",
|
||||
"prettier": "prettier -c .",
|
||||
"test": "npm run eslint && npm run stylelint && npm run prettier"
|
||||
"types": "tsc -p jsconfig.json",
|
||||
"test": "npm run eslint && npm run stylelint && npm run prettier && npm run types"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// @ts-check
|
||||
|
||||
import "device-agnostic-ui/theme.css";
|
||||
import "device-agnostic-ui/global.css";
|
||||
import "device-agnostic-ui/Button.css";
|
||||
@ -11,12 +13,18 @@ import "device-agnostic-ui/Scroll.css";
|
||||
import "device-agnostic-ui/Table.css";
|
||||
import "device-agnostic-ui/Textbox.css";
|
||||
|
||||
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client";
|
||||
import { InMemoryCache } from "@apollo/client/cache/inmemory/inMemoryCache.js";
|
||||
import { ApolloClient } from "@apollo/client/core/ApolloClient.js";
|
||||
import { ApolloProvider } from "@apollo/client/react/context/ApolloProvider.js";
|
||||
import { createUploadLink } from "apollo-upload-client";
|
||||
import Head from "next/head";
|
||||
import PropTypes from "prop-types";
|
||||
import { createElement as h } from "react";
|
||||
import nextApp from "next/app.js";
|
||||
import nextHead from "next/head.js";
|
||||
import { createElement as h, Fragment } from "react";
|
||||
|
||||
/**
|
||||
* Creates an Apollo Client instance.
|
||||
* @param {{ [key: string]: unknown }} [cache] Apollo Client initial cache.
|
||||
*/
|
||||
const createApolloClient = (cache = {}) =>
|
||||
new ApolloClient({
|
||||
ssrMode: typeof window === "undefined",
|
||||
@ -24,64 +32,75 @@ const createApolloClient = (cache = {}) =>
|
||||
link: createUploadLink({ uri: process.env.API_URI }),
|
||||
});
|
||||
|
||||
const App = ({
|
||||
/**
|
||||
* React component for the Next.js app.
|
||||
* @param {import("next/app.js").AppProps & AppCustomProps} props Props.
|
||||
*/
|
||||
function App({
|
||||
Component,
|
||||
pageProps,
|
||||
apolloCache,
|
||||
apolloClient = createApolloClient(apolloCache),
|
||||
}) =>
|
||||
h(
|
||||
ApolloProvider,
|
||||
{ client: apolloClient },
|
||||
h(
|
||||
Head,
|
||||
}) {
|
||||
return h(ApolloProvider, {
|
||||
client: apolloClient,
|
||||
children: h(
|
||||
Fragment,
|
||||
null,
|
||||
h("meta", {
|
||||
name: "viewport",
|
||||
content: "width=device-width, initial-scale=1",
|
||||
}),
|
||||
h("meta", { name: "color-scheme", content: "light dark" }),
|
||||
h("meta", { name: "theme-color", content: "white" }),
|
||||
h("link", { rel: "manifest", href: "/manifest.webmanifest" })
|
||||
h(
|
||||
nextHead.default,
|
||||
null,
|
||||
h("meta", {
|
||||
name: "viewport",
|
||||
content: "width=device-width, initial-scale=1",
|
||||
}),
|
||||
h("meta", { name: "color-scheme", content: "light dark" }),
|
||||
h("meta", { name: "theme-color", content: "white" }),
|
||||
h("link", { rel: "manifest", href: "/manifest.webmanifest" })
|
||||
),
|
||||
h(Component, pageProps)
|
||||
),
|
||||
h(Component, pageProps)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
App.getInitialProps = async (context) => {
|
||||
const props = {
|
||||
pageProps: context.Component.getInitialProps
|
||||
? await context.Component.getInitialProps(context)
|
||||
: {},
|
||||
};
|
||||
if (typeof window === "undefined")
|
||||
App.getInitialProps =
|
||||
/** @param {import("next/app.js").AppContext} context */
|
||||
async function getInitialProps(context) {
|
||||
const apolloClient = createApolloClient();
|
||||
const [props, { default: ReactDOMServer }, { getMarkupFromTree }] =
|
||||
await Promise.all([
|
||||
nextApp.default.getInitialProps(context),
|
||||
import("react-dom/server.js"),
|
||||
import("@apollo/client/react/ssr/getDataFromTree.js"),
|
||||
]);
|
||||
|
||||
if (context.ctx.req) {
|
||||
const apolloClient = createApolloClient();
|
||||
try {
|
||||
const { getDataFromTree } = await import("@apollo/client/react/ssr");
|
||||
await getDataFromTree(
|
||||
h(App, {
|
||||
...props,
|
||||
apolloClient,
|
||||
router: context.router,
|
||||
Component: context.Component,
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
// Prevent crash from GraphQL errors.
|
||||
console.error(error);
|
||||
}
|
||||
try {
|
||||
await getMarkupFromTree({
|
||||
tree: h(App, {
|
||||
...props,
|
||||
apolloClient,
|
||||
router: context.router,
|
||||
Component: context.Component,
|
||||
}),
|
||||
renderFunction: ReactDOMServer.renderToStaticMarkup,
|
||||
});
|
||||
} catch (error) {
|
||||
// Prevent crash from GraphQL errors.
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
props.apolloCache = apolloClient.cache.extract();
|
||||
}
|
||||
|
||||
return props;
|
||||
};
|
||||
|
||||
App.propTypes = {
|
||||
Component: PropTypes.elementType.isRequired,
|
||||
pageProps: PropTypes.object,
|
||||
apolloCache: PropTypes.object,
|
||||
apolloClient: PropTypes.instanceOf(ApolloClient),
|
||||
};
|
||||
return {
|
||||
...props,
|
||||
apolloCache: apolloClient.cache.extract(),
|
||||
};
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
||||
/**
|
||||
* Next.js app custom props.
|
||||
* @typedef {object} AppCustomProps
|
||||
* @prop {{ [key: string]: unknown }} [apolloCache] Apollo Client initial cache.
|
||||
* @prop {ApolloClient<any>} apolloClient Apollo Client.
|
||||
*/
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
// @ts-check
|
||||
|
||||
import Code from "device-agnostic-ui/Code.mjs";
|
||||
import Heading from "device-agnostic-ui/Heading.mjs";
|
||||
import Margin from "device-agnostic-ui/Margin.mjs";
|
||||
import { createElement as h } from "react";
|
||||
|
||||
import { Header } from "../components/Header.mjs";
|
||||
import { Page } from "../components/Page.mjs";
|
||||
import { Section } from "../components/Section.mjs";
|
||||
import { UploadBlob } from "../components/UploadBlob.mjs";
|
||||
import { UploadFile } from "../components/UploadFile.mjs";
|
||||
import { UploadFileList } from "../components/UploadFileList.mjs";
|
||||
import { Uploads } from "../components/Uploads.mjs";
|
||||
import Header from "../components/Header.mjs";
|
||||
import Page from "../components/Page.mjs";
|
||||
import Section from "../components/Section.mjs";
|
||||
import UploadBlob from "../components/UploadBlob.mjs";
|
||||
import UploadFile from "../components/UploadFile.mjs";
|
||||
import UploadFileList from "../components/UploadFileList.mjs";
|
||||
import Uploads from "../components/Uploads.mjs";
|
||||
|
||||
export default function IndexPage() {
|
||||
return h(
|
||||
|
||||
4
app/typings.d.ts
vendored
Normal file
4
app/typings.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
declare module "*.module.css" {
|
||||
const classes: { [key: string]: string };
|
||||
export default classes;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user