nexusbert commited on
Commit
cb429c5
·
1 Parent(s): 2b10722
package-lock.json CHANGED
@@ -18,6 +18,8 @@
18
  "jsonwebtoken": "^9.0.2",
19
  "pg": "^8.16.3",
20
  "reflect-metadata": "^0.2.2",
 
 
21
  "typeorm": "^0.3.27"
22
  },
23
  "devDependencies": {
@@ -26,11 +28,53 @@
26
  "@types/express": "^5.0.5",
27
  "@types/jsonwebtoken": "^9.0.10",
28
  "@types/node": "^24.9.2",
 
 
29
  "nodemon": "^3.1.10",
30
  "ts-node": "^10.9.2",
31
  "typescript": "^5.9.3"
32
  }
33
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  "node_modules/@cspotcode/source-map-support": {
35
  "version": "0.8.1",
36
  "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
@@ -84,6 +128,11 @@
84
  "@jridgewell/sourcemap-codec": "^1.4.10"
85
  }
86
  },
 
 
 
 
 
87
  "node_modules/@mapbox/node-pre-gyp": {
88
  "version": "1.0.11",
89
  "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
@@ -112,6 +161,12 @@
112
  "node": ">=14"
113
  }
114
  },
 
 
 
 
 
 
115
  "node_modules/@sqltools/formatter": {
116
  "version": "1.2.5",
117
  "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz",
@@ -207,6 +262,11 @@
207
  "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
208
  "dev": true
209
  },
 
 
 
 
 
210
  "node_modules/@types/jsonwebtoken": {
211
  "version": "9.0.10",
212
  "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz",
@@ -280,6 +340,22 @@
280
  "@types/node": "*"
281
  }
282
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
  "node_modules/abbrev": {
284
  "version": "1.1.1",
285
  "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@@ -407,6 +483,11 @@
407
  "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
408
  "devOptional": true
409
  },
 
 
 
 
 
410
  "node_modules/asynckit": {
411
  "version": "0.4.0",
412
  "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -604,6 +685,11 @@
604
  "url": "https://github.com/sponsors/ljharb"
605
  }
606
  },
 
 
 
 
 
607
  "node_modules/chokidar": {
608
  "version": "3.6.0",
609
  "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -763,6 +849,14 @@
763
  "node": ">= 0.8"
764
  }
765
  },
 
 
 
 
 
 
 
 
766
  "node_modules/concat-map": {
767
  "version": "0.0.1",
768
  "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -927,6 +1021,17 @@
927
  "node": ">=0.3.1"
928
  }
929
  },
 
 
 
 
 
 
 
 
 
 
 
930
  "node_modules/dotenv": {
931
  "version": "17.2.3",
932
  "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
@@ -1036,6 +1141,14 @@
1036
  "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
1037
  "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
1038
  },
 
 
 
 
 
 
 
 
1039
  "node_modules/etag": {
1040
  "version": "1.8.1",
1041
  "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -1666,6 +1779,17 @@
1666
  "@pkgjs/parseargs": "^0.11.0"
1667
  }
1668
  },
 
 
 
 
 
 
 
 
 
 
 
1669
  "node_modules/jsonwebtoken": {
1670
  "version": "9.0.2",
1671
  "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
@@ -1711,6 +1835,12 @@
1711
  "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
1712
  "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
1713
  },
 
 
 
 
 
 
1714
  "node_modules/lodash.includes": {
1715
  "version": "4.3.0",
1716
  "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -1721,6 +1851,12 @@
1721
  "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
1722
  "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
1723
  },
 
 
 
 
 
 
1724
  "node_modules/lodash.isinteger": {
1725
  "version": "4.0.4",
1726
  "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
@@ -1741,6 +1877,11 @@
1741
  "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
1742
  "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
1743
  },
 
 
 
 
 
1744
  "node_modules/lodash.once": {
1745
  "version": "4.1.1",
1746
  "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
@@ -2041,6 +2182,12 @@
2041
  "wrappy": "1"
2042
  }
2043
  },
 
 
 
 
 
 
2044
  "node_modules/package-json-from-dist": {
2045
  "version": "1.0.1",
2046
  "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
@@ -2786,6 +2933,98 @@
2786
  "node": ">=4"
2787
  }
2788
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2789
  "node_modules/tar": {
2790
  "version": "6.2.1",
2791
  "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
@@ -3099,6 +3338,14 @@
3099
  "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
3100
  "devOptional": true
3101
  },
 
 
 
 
 
 
 
 
3102
  "node_modules/vary": {
3103
  "version": "1.1.2",
3104
  "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -3310,6 +3557,14 @@
3310
  "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
3311
  "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
3312
  },
 
 
 
 
 
 
 
 
3313
  "node_modules/yargs": {
3314
  "version": "17.7.2",
3315
  "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
@@ -3380,6 +3635,34 @@
3380
  "engines": {
3381
  "node": ">=6"
3382
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3383
  }
3384
  }
3385
  }
 
18
  "jsonwebtoken": "^9.0.2",
19
  "pg": "^8.16.3",
20
  "reflect-metadata": "^0.2.2",
21
+ "swagger-jsdoc": "^6.2.8",
22
+ "swagger-ui-express": "^5.0.0",
23
  "typeorm": "^0.3.27"
24
  },
25
  "devDependencies": {
 
28
  "@types/express": "^5.0.5",
29
  "@types/jsonwebtoken": "^9.0.10",
30
  "@types/node": "^24.9.2",
31
+ "@types/swagger-jsdoc": "^6.0.4",
32
+ "@types/swagger-ui-express": "^4.1.6",
33
  "nodemon": "^3.1.10",
34
  "ts-node": "^10.9.2",
35
  "typescript": "^5.9.3"
36
  }
37
  },
38
+ "node_modules/@apidevtools/json-schema-ref-parser": {
39
+ "version": "9.1.2",
40
+ "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz",
41
+ "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==",
42
+ "dependencies": {
43
+ "@jsdevtools/ono": "^7.1.3",
44
+ "@types/json-schema": "^7.0.6",
45
+ "call-me-maybe": "^1.0.1",
46
+ "js-yaml": "^4.1.0"
47
+ }
48
+ },
49
+ "node_modules/@apidevtools/openapi-schemas": {
50
+ "version": "2.1.0",
51
+ "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz",
52
+ "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==",
53
+ "engines": {
54
+ "node": ">=10"
55
+ }
56
+ },
57
+ "node_modules/@apidevtools/swagger-methods": {
58
+ "version": "3.0.2",
59
+ "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz",
60
+ "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg=="
61
+ },
62
+ "node_modules/@apidevtools/swagger-parser": {
63
+ "version": "10.0.3",
64
+ "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz",
65
+ "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==",
66
+ "dependencies": {
67
+ "@apidevtools/json-schema-ref-parser": "^9.0.6",
68
+ "@apidevtools/openapi-schemas": "^2.0.4",
69
+ "@apidevtools/swagger-methods": "^3.0.2",
70
+ "@jsdevtools/ono": "^7.1.3",
71
+ "call-me-maybe": "^1.0.1",
72
+ "z-schema": "^5.0.1"
73
+ },
74
+ "peerDependencies": {
75
+ "openapi-types": ">=7"
76
+ }
77
+ },
78
  "node_modules/@cspotcode/source-map-support": {
79
  "version": "0.8.1",
80
  "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
 
128
  "@jridgewell/sourcemap-codec": "^1.4.10"
129
  }
130
  },
131
+ "node_modules/@jsdevtools/ono": {
132
+ "version": "7.1.3",
133
+ "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
134
+ "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="
135
+ },
136
  "node_modules/@mapbox/node-pre-gyp": {
137
  "version": "1.0.11",
138
  "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
 
161
  "node": ">=14"
162
  }
163
  },
164
+ "node_modules/@scarf/scarf": {
165
+ "version": "1.4.0",
166
+ "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz",
167
+ "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==",
168
+ "hasInstallScript": true
169
+ },
170
  "node_modules/@sqltools/formatter": {
171
  "version": "1.2.5",
172
  "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz",
 
262
  "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
263
  "dev": true
264
  },
265
+ "node_modules/@types/json-schema": {
266
+ "version": "7.0.15",
267
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
268
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
269
+ },
270
  "node_modules/@types/jsonwebtoken": {
271
  "version": "9.0.10",
272
  "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz",
 
340
  "@types/node": "*"
341
  }
342
  },
343
+ "node_modules/@types/swagger-jsdoc": {
344
+ "version": "6.0.4",
345
+ "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz",
346
+ "integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==",
347
+ "dev": true
348
+ },
349
+ "node_modules/@types/swagger-ui-express": {
350
+ "version": "4.1.8",
351
+ "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.8.tgz",
352
+ "integrity": "sha512-AhZV8/EIreHFmBV5wAs0gzJUNq9JbbSXgJLQubCC0jtIo6prnI9MIRRxnU4MZX9RB9yXxF1V4R7jtLl/Wcj31g==",
353
+ "dev": true,
354
+ "dependencies": {
355
+ "@types/express": "*",
356
+ "@types/serve-static": "*"
357
+ }
358
+ },
359
  "node_modules/abbrev": {
360
  "version": "1.1.1",
361
  "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
 
483
  "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
484
  "devOptional": true
485
  },
486
+ "node_modules/argparse": {
487
+ "version": "2.0.1",
488
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
489
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
490
+ },
491
  "node_modules/asynckit": {
492
  "version": "0.4.0",
493
  "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
 
685
  "url": "https://github.com/sponsors/ljharb"
686
  }
687
  },
688
+ "node_modules/call-me-maybe": {
689
+ "version": "1.0.2",
690
+ "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
691
+ "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ=="
692
+ },
693
  "node_modules/chokidar": {
694
  "version": "3.6.0",
695
  "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
 
849
  "node": ">= 0.8"
850
  }
851
  },
852
+ "node_modules/commander": {
853
+ "version": "6.2.0",
854
+ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz",
855
+ "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==",
856
+ "engines": {
857
+ "node": ">= 6"
858
+ }
859
+ },
860
  "node_modules/concat-map": {
861
  "version": "0.0.1",
862
  "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
 
1021
  "node": ">=0.3.1"
1022
  }
1023
  },
1024
+ "node_modules/doctrine": {
1025
+ "version": "3.0.0",
1026
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
1027
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
1028
+ "dependencies": {
1029
+ "esutils": "^2.0.2"
1030
+ },
1031
+ "engines": {
1032
+ "node": ">=6.0.0"
1033
+ }
1034
+ },
1035
  "node_modules/dotenv": {
1036
  "version": "17.2.3",
1037
  "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
 
1141
  "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
1142
  "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
1143
  },
1144
+ "node_modules/esutils": {
1145
+ "version": "2.0.3",
1146
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
1147
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
1148
+ "engines": {
1149
+ "node": ">=0.10.0"
1150
+ }
1151
+ },
1152
  "node_modules/etag": {
1153
  "version": "1.8.1",
1154
  "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
 
1779
  "@pkgjs/parseargs": "^0.11.0"
1780
  }
1781
  },
1782
+ "node_modules/js-yaml": {
1783
+ "version": "4.1.0",
1784
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
1785
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
1786
+ "dependencies": {
1787
+ "argparse": "^2.0.1"
1788
+ },
1789
+ "bin": {
1790
+ "js-yaml": "bin/js-yaml.js"
1791
+ }
1792
+ },
1793
  "node_modules/jsonwebtoken": {
1794
  "version": "9.0.2",
1795
  "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
 
1835
  "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
1836
  "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
1837
  },
1838
+ "node_modules/lodash.get": {
1839
+ "version": "4.4.2",
1840
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
1841
+ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
1842
+ "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead."
1843
+ },
1844
  "node_modules/lodash.includes": {
1845
  "version": "4.3.0",
1846
  "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
 
1851
  "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
1852
  "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
1853
  },
1854
+ "node_modules/lodash.isequal": {
1855
+ "version": "4.5.0",
1856
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
1857
+ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
1858
+ "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead."
1859
+ },
1860
  "node_modules/lodash.isinteger": {
1861
  "version": "4.0.4",
1862
  "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
 
1877
  "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
1878
  "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
1879
  },
1880
+ "node_modules/lodash.mergewith": {
1881
+ "version": "4.6.2",
1882
+ "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
1883
+ "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ=="
1884
+ },
1885
  "node_modules/lodash.once": {
1886
  "version": "4.1.1",
1887
  "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
 
2182
  "wrappy": "1"
2183
  }
2184
  },
2185
+ "node_modules/openapi-types": {
2186
+ "version": "12.1.3",
2187
+ "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
2188
+ "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
2189
+ "peer": true
2190
+ },
2191
  "node_modules/package-json-from-dist": {
2192
  "version": "1.0.1",
2193
  "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
 
2933
  "node": ">=4"
2934
  }
2935
  },
2936
+ "node_modules/swagger-jsdoc": {
2937
+ "version": "6.2.8",
2938
+ "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz",
2939
+ "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==",
2940
+ "dependencies": {
2941
+ "commander": "6.2.0",
2942
+ "doctrine": "3.0.0",
2943
+ "glob": "7.1.6",
2944
+ "lodash.mergewith": "^4.6.2",
2945
+ "swagger-parser": "^10.0.3",
2946
+ "yaml": "2.0.0-1"
2947
+ },
2948
+ "bin": {
2949
+ "swagger-jsdoc": "bin/swagger-jsdoc.js"
2950
+ },
2951
+ "engines": {
2952
+ "node": ">=12.0.0"
2953
+ }
2954
+ },
2955
+ "node_modules/swagger-jsdoc/node_modules/brace-expansion": {
2956
+ "version": "1.1.12",
2957
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
2958
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
2959
+ "dependencies": {
2960
+ "balanced-match": "^1.0.0",
2961
+ "concat-map": "0.0.1"
2962
+ }
2963
+ },
2964
+ "node_modules/swagger-jsdoc/node_modules/glob": {
2965
+ "version": "7.1.6",
2966
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
2967
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
2968
+ "deprecated": "Glob versions prior to v9 are no longer supported",
2969
+ "dependencies": {
2970
+ "fs.realpath": "^1.0.0",
2971
+ "inflight": "^1.0.4",
2972
+ "inherits": "2",
2973
+ "minimatch": "^3.0.4",
2974
+ "once": "^1.3.0",
2975
+ "path-is-absolute": "^1.0.0"
2976
+ },
2977
+ "engines": {
2978
+ "node": "*"
2979
+ },
2980
+ "funding": {
2981
+ "url": "https://github.com/sponsors/isaacs"
2982
+ }
2983
+ },
2984
+ "node_modules/swagger-jsdoc/node_modules/minimatch": {
2985
+ "version": "3.1.2",
2986
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
2987
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
2988
+ "dependencies": {
2989
+ "brace-expansion": "^1.1.7"
2990
+ },
2991
+ "engines": {
2992
+ "node": "*"
2993
+ }
2994
+ },
2995
+ "node_modules/swagger-parser": {
2996
+ "version": "10.0.3",
2997
+ "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz",
2998
+ "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==",
2999
+ "dependencies": {
3000
+ "@apidevtools/swagger-parser": "10.0.3"
3001
+ },
3002
+ "engines": {
3003
+ "node": ">=10"
3004
+ }
3005
+ },
3006
+ "node_modules/swagger-ui-dist": {
3007
+ "version": "5.30.1",
3008
+ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.30.1.tgz",
3009
+ "integrity": "sha512-4mNAUM31sr52K3JcK9qiGbfsFKNh/dm3PkEe+F9FAM31YY/NoRYUgsR/L6d7LLFn6PgZXtBG2ygp8+7UnpUIPg==",
3010
+ "dependencies": {
3011
+ "@scarf/scarf": "=1.4.0"
3012
+ }
3013
+ },
3014
+ "node_modules/swagger-ui-express": {
3015
+ "version": "5.0.1",
3016
+ "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz",
3017
+ "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==",
3018
+ "dependencies": {
3019
+ "swagger-ui-dist": ">=5.0.0"
3020
+ },
3021
+ "engines": {
3022
+ "node": ">= v0.10.32"
3023
+ },
3024
+ "peerDependencies": {
3025
+ "express": ">=4.0.0 || >=5.0.0-beta"
3026
+ }
3027
+ },
3028
  "node_modules/tar": {
3029
  "version": "6.2.1",
3030
  "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
 
3338
  "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
3339
  "devOptional": true
3340
  },
3341
+ "node_modules/validator": {
3342
+ "version": "13.15.20",
3343
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.20.tgz",
3344
+ "integrity": "sha512-KxPOq3V2LmfQPP4eqf3Mq/zrT0Dqp2Vmx2Bn285LwVahLc+CsxOM0crBHczm8ijlcjZ0Q5Xd6LW3z3odTPnlrw==",
3345
+ "engines": {
3346
+ "node": ">= 0.10"
3347
+ }
3348
+ },
3349
  "node_modules/vary": {
3350
  "version": "1.1.2",
3351
  "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
 
3557
  "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
3558
  "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
3559
  },
3560
+ "node_modules/yaml": {
3561
+ "version": "2.0.0-1",
3562
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz",
3563
+ "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==",
3564
+ "engines": {
3565
+ "node": ">= 6"
3566
+ }
3567
+ },
3568
  "node_modules/yargs": {
3569
  "version": "17.7.2",
3570
  "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
 
3635
  "engines": {
3636
  "node": ">=6"
3637
  }
3638
+ },
3639
+ "node_modules/z-schema": {
3640
+ "version": "5.0.5",
3641
+ "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz",
3642
+ "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==",
3643
+ "dependencies": {
3644
+ "lodash.get": "^4.4.2",
3645
+ "lodash.isequal": "^4.5.0",
3646
+ "validator": "^13.7.0"
3647
+ },
3648
+ "bin": {
3649
+ "z-schema": "bin/z-schema"
3650
+ },
3651
+ "engines": {
3652
+ "node": ">=8.0.0"
3653
+ },
3654
+ "optionalDependencies": {
3655
+ "commander": "^9.4.1"
3656
+ }
3657
+ },
3658
+ "node_modules/z-schema/node_modules/commander": {
3659
+ "version": "9.5.0",
3660
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
3661
+ "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
3662
+ "optional": true,
3663
+ "engines": {
3664
+ "node": "^12.20.0 || >=14"
3665
+ }
3666
  }
3667
  }
3668
  }
package.json CHANGED
@@ -27,6 +27,8 @@
27
  "jsonwebtoken": "^9.0.2",
28
  "pg": "^8.16.3",
29
  "reflect-metadata": "^0.2.2",
 
 
30
  "typeorm": "^0.3.27"
31
  },
32
  "devDependencies": {
@@ -35,6 +37,8 @@
35
  "@types/express": "^5.0.5",
36
  "@types/jsonwebtoken": "^9.0.10",
37
  "@types/node": "^24.9.2",
 
 
38
  "nodemon": "^3.1.10",
39
  "ts-node": "^10.9.2",
40
  "typescript": "^5.9.3"
 
27
  "jsonwebtoken": "^9.0.2",
28
  "pg": "^8.16.3",
29
  "reflect-metadata": "^0.2.2",
30
+ "swagger-jsdoc": "^6.2.8",
31
+ "swagger-ui-express": "^5.0.0",
32
  "typeorm": "^0.3.27"
33
  },
34
  "devDependencies": {
 
37
  "@types/express": "^5.0.5",
38
  "@types/jsonwebtoken": "^9.0.10",
39
  "@types/node": "^24.9.2",
40
+ "@types/swagger-jsdoc": "^6.0.4",
41
+ "@types/swagger-ui-express": "^4.1.6",
42
  "nodemon": "^3.1.10",
43
  "ts-node": "^10.9.2",
44
  "typescript": "^5.9.3"
src/index.ts CHANGED
@@ -2,6 +2,8 @@ import "reflect-metadata";
2
  import express from "express";
3
  import cors from "cors";
4
  import dotenv from "dotenv";
 
 
5
  import { AppDataSource } from "./utils/dataSource";
6
  import authRoute from "./routes/auth";
7
  import uploadRoute from "./routes/upload";
@@ -14,15 +16,191 @@ const app = express();
14
  app.use(cors());
15
  app.use(express.json({ limit: "10mb" }));
16
 
17
- app.use("/api/auth", authRoute);
18
- app.use("/api/profile", profileRoute);
19
- app.use("/api/upload", uploadRoute);
20
- app.use("/api/suggest", suggestRoute);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  app.get("/health", (req, res) => {
23
  res.json({ status: "healthy", database: AppDataSource.isInitialized });
24
  });
25
 
 
 
 
 
 
26
  const PORT = process.env.PORT || 7860;
27
 
28
  AppDataSource.initialize()
 
2
  import express from "express";
3
  import cors from "cors";
4
  import dotenv from "dotenv";
5
+ import swaggerJsdoc from "swagger-jsdoc";
6
+ import swaggerUi from "swagger-ui-express";
7
  import { AppDataSource } from "./utils/dataSource";
8
  import authRoute from "./routes/auth";
9
  import uploadRoute from "./routes/upload";
 
16
  app.use(cors());
17
  app.use(express.json({ limit: "10mb" }));
18
 
19
+ // Root endpoint with milestone information
20
+ app.get("/", (req, res) => {
21
+ res.json({
22
+ name: "StyleGPT Milestone 2",
23
+ version: "1.0.0",
24
+ description: "Visual Wardrobe Tagging & AI-Powered Outfit Suggestions",
25
+ milestone: 2,
26
+ features: [
27
+ "User Authentication (JWT-based)",
28
+ "Visual Wardrobe Management",
29
+ "AI-Powered Image Classification (Fashion-CLIP)",
30
+ "Smart Outfit Suggestions",
31
+ "User Profile Management"
32
+ ],
33
+ endpoints: {
34
+ root: "/",
35
+ docs: "/docs",
36
+ health: "/health",
37
+ api: {
38
+ auth: "/api/auth",
39
+ profile: "/api/profile",
40
+ upload: "/api/upload",
41
+ suggest: "/api/suggest"
42
+ }
43
+ },
44
+ technologies: [
45
+ "Node.js",
46
+ "TypeScript",
47
+ "Express.js",
48
+ "PostgreSQL",
49
+ "TypeORM",
50
+ "Cloudinary",
51
+ "Hugging Face Fashion-CLIP",
52
+ "JWT Authentication"
53
+ ]
54
+ });
55
+ });
56
+
57
+ // Swagger/OpenAPI configuration
58
+ const swaggerOptions: swaggerJsdoc.Options = {
59
+ definition: {
60
+ openapi: "3.0.0",
61
+ info: {
62
+ title: "StyleGPT Milestone 2 API",
63
+ version: "1.0.0",
64
+ description: "API documentation for StyleGPT Milestone 2 - Visual Wardrobe Tagging & AI-Powered Outfit Suggestions",
65
+ contact: {
66
+ name: "StyleGPT",
67
+ url: "https://huggingface.co/spaces/nexusbert/StyleGPT-milestone2"
68
+ }
69
+ },
70
+ servers: [
71
+ {
72
+ url: process.env.API_URL || `http://localhost:${process.env.PORT || 7860}`,
73
+ description: "API Server"
74
+ }
75
+ ],
76
+ components: {
77
+ securitySchemes: {
78
+ bearerAuth: {
79
+ type: "http",
80
+ scheme: "bearer",
81
+ bearerFormat: "JWT"
82
+ }
83
+ },
84
+ schemas: {
85
+ User: {
86
+ type: "object",
87
+ properties: {
88
+ id: { type: "integer" },
89
+ name: { type: "string" },
90
+ email: { type: "string", format: "email" },
91
+ createdAt: { type: "string", format: "date-time" }
92
+ }
93
+ },
94
+ WardrobeItem: {
95
+ type: "object",
96
+ properties: {
97
+ id: { type: "integer" },
98
+ imageUrl: { type: "string", format: "uri" },
99
+ category: { type: "string" },
100
+ style: { type: "string", enum: ["formal", "casual", "streetwear"] },
101
+ userId: { type: "integer" },
102
+ createdAt: { type: "string", format: "date-time" }
103
+ }
104
+ },
105
+ RegisterRequest: {
106
+ type: "object",
107
+ required: ["name", "email", "password"],
108
+ properties: {
109
+ name: { type: "string" },
110
+ email: { type: "string", format: "email" },
111
+ password: { type: "string", minLength: 6 }
112
+ }
113
+ },
114
+ LoginRequest: {
115
+ type: "object",
116
+ required: ["email", "password"],
117
+ properties: {
118
+ email: { type: "string", format: "email" },
119
+ password: { type: "string" }
120
+ }
121
+ },
122
+ AuthResponse: {
123
+ type: "object",
124
+ properties: {
125
+ success: { type: "boolean" },
126
+ user: { $ref: "#/components/schemas/User" },
127
+ token: { type: "string" },
128
+ error: { type: "string" }
129
+ }
130
+ },
131
+ UploadRequest: {
132
+ type: "object",
133
+ required: ["imageUrl"],
134
+ properties: {
135
+ imageUrl: { type: "string", format: "uri" }
136
+ }
137
+ },
138
+ SuggestRequest: {
139
+ type: "object",
140
+ required: ["message"],
141
+ properties: {
142
+ message: { type: "string" },
143
+ session_id: { type: "string" }
144
+ }
145
+ }
146
+ }
147
+ },
148
+ tags: [
149
+ { name: "Authentication", description: "User registration and login" },
150
+ { name: "Profile", description: "User profile management" },
151
+ { name: "Upload", description: "Wardrobe item upload and classification" },
152
+ { name: "Suggest", description: "AI-powered outfit suggestions" },
153
+ { name: "Health", description: "Health check endpoints" }
154
+ ]
155
+ },
156
+ apis: ["./src/routes/*.ts", "./src/index.ts"]
157
+ };
158
+
159
+ const swaggerSpec = swaggerJsdoc(swaggerOptions);
160
+
161
+ // Swagger UI endpoint
162
+ app.use("/docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec, {
163
+ customCss: ".swagger-ui .topbar { display: none }",
164
+ customSiteTitle: "StyleGPT Milestone 2 API Docs"
165
+ }));
166
 
167
+ // Swagger JSON endpoint
168
+ app.get("/docs.json", (req, res) => {
169
+ res.setHeader("Content-Type", "application/json");
170
+ res.send(swaggerSpec);
171
+ });
172
+
173
+ // Health check endpoint
174
+ /**
175
+ * @openapi
176
+ * /health:
177
+ * get:
178
+ * summary: Health check endpoint
179
+ * tags: [Health]
180
+ * responses:
181
+ * 200:
182
+ * description: Service is healthy
183
+ * content:
184
+ * application/json:
185
+ * schema:
186
+ * type: object
187
+ * properties:
188
+ * status:
189
+ * type: string
190
+ * example: healthy
191
+ * database:
192
+ * type: boolean
193
+ * example: true
194
+ */
195
  app.get("/health", (req, res) => {
196
  res.json({ status: "healthy", database: AppDataSource.isInitialized });
197
  });
198
 
199
+ app.use("/api/auth", authRoute);
200
+ app.use("/api/profile", profileRoute);
201
+ app.use("/api/upload", uploadRoute);
202
+ app.use("/api/suggest", suggestRoute);
203
+
204
  const PORT = process.env.PORT || 7860;
205
 
206
  AppDataSource.initialize()
src/routes/auth.ts CHANGED
@@ -8,6 +8,30 @@ dotenv.config();
8
 
9
  const router = express.Router();
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  router.post("/register", async (req, res) => {
12
  try {
13
  const { name, email, password } = req.body;
@@ -71,6 +95,30 @@ router.post("/register", async (req, res) => {
71
  }
72
  });
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  router.post("/login", async (req, res) => {
75
  try {
76
  const { email, password } = req.body;
 
8
 
9
  const router = express.Router();
10
 
11
+ /**
12
+ * @openapi
13
+ * /api/auth/register:
14
+ * post:
15
+ * summary: Register a new user
16
+ * tags: [Authentication]
17
+ * requestBody:
18
+ * required: true
19
+ * content:
20
+ * application/json:
21
+ * schema:
22
+ * $ref: "#/components/schemas/RegisterRequest"
23
+ * responses:
24
+ * 201:
25
+ * description: User registered successfully
26
+ * content:
27
+ * application/json:
28
+ * schema:
29
+ * $ref: "#/components/schemas/AuthResponse"
30
+ * 400:
31
+ * description: Bad request (missing fields, email exists, or weak password)
32
+ * 500:
33
+ * description: Server error
34
+ */
35
  router.post("/register", async (req, res) => {
36
  try {
37
  const { name, email, password } = req.body;
 
95
  }
96
  });
97
 
98
+ /**
99
+ * @openapi
100
+ * /api/auth/login:
101
+ * post:
102
+ * summary: Login user
103
+ * tags: [Authentication]
104
+ * requestBody:
105
+ * required: true
106
+ * content:
107
+ * application/json:
108
+ * schema:
109
+ * $ref: "#/components/schemas/LoginRequest"
110
+ * responses:
111
+ * 200:
112
+ * description: Login successful
113
+ * content:
114
+ * application/json:
115
+ * schema:
116
+ * $ref: "#/components/schemas/AuthResponse"
117
+ * 401:
118
+ * description: Invalid credentials
119
+ * 500:
120
+ * description: Server error
121
+ */
122
  router.post("/login", async (req, res) => {
123
  try {
124
  const { email, password } = req.body;
src/routes/profile.ts CHANGED
@@ -5,6 +5,33 @@ import { authenticateToken, AuthRequest } from "../middleware/auth";
5
 
6
  const router = express.Router();
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  router.get("/", authenticateToken, async (req: AuthRequest, res) => {
9
  try {
10
  const userId = req.userId!;
 
5
 
6
  const router = express.Router();
7
 
8
+ /**
9
+ * @openapi
10
+ * /api/profile:
11
+ * get:
12
+ * summary: Get user profile
13
+ * tags: [Profile]
14
+ * security:
15
+ * - bearerAuth: []
16
+ * responses:
17
+ * 200:
18
+ * description: Profile retrieved successfully
19
+ * content:
20
+ * application/json:
21
+ * schema:
22
+ * type: object
23
+ * properties:
24
+ * success:
25
+ * type: boolean
26
+ * user:
27
+ * $ref: "#/components/schemas/User"
28
+ * 401:
29
+ * description: Unauthorized
30
+ * 404:
31
+ * description: User not found
32
+ * 500:
33
+ * description: Server error
34
+ */
35
  router.get("/", authenticateToken, async (req: AuthRequest, res) => {
36
  try {
37
  const userId = req.userId!;
src/routes/suggest.ts CHANGED
@@ -8,6 +8,40 @@ dotenv.config();
8
 
9
  const router = express.Router();
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  router.post("/", authenticateToken, async (req: AuthRequest, res) => {
12
  try {
13
  const { message, session_id } = req.body;
 
8
 
9
  const router = express.Router();
10
 
11
+ /**
12
+ * @openapi
13
+ * /api/suggest:
14
+ * post:
15
+ * summary: Get AI-powered outfit suggestions based on user's wardrobe
16
+ * tags: [Suggest]
17
+ * security:
18
+ * - bearerAuth: []
19
+ * requestBody:
20
+ * required: true
21
+ * content:
22
+ * application/json:
23
+ * schema:
24
+ * $ref: "#/components/schemas/SuggestRequest"
25
+ * responses:
26
+ * 200:
27
+ * description: Suggestions generated successfully
28
+ * content:
29
+ * application/json:
30
+ * schema:
31
+ * type: object
32
+ * properties:
33
+ * success:
34
+ * type: boolean
35
+ * suggestion:
36
+ * type: object
37
+ * description: AI-generated outfit suggestion from Milestone 1
38
+ * 400:
39
+ * description: Bad request (missing message)
40
+ * 401:
41
+ * description: Unauthorized
42
+ * 500:
43
+ * description: Server error
44
+ */
45
  router.post("/", authenticateToken, async (req: AuthRequest, res) => {
46
  try {
47
  const { message, session_id } = req.body;
src/routes/upload.ts CHANGED
@@ -7,6 +7,39 @@ import { authenticateToken, AuthRequest } from "../middleware/auth";
7
 
8
  const router = express.Router();
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  router.post("/", authenticateToken, async (req: AuthRequest, res) => {
11
  try {
12
  const { imageUrl } = req.body;
 
7
 
8
  const router = express.Router();
9
 
10
+ /**
11
+ * @openapi
12
+ * /api/upload:
13
+ * post:
14
+ * summary: Upload and classify a wardrobe item image
15
+ * tags: [Upload]
16
+ * security:
17
+ * - bearerAuth: []
18
+ * requestBody:
19
+ * required: true
20
+ * content:
21
+ * application/json:
22
+ * schema:
23
+ * $ref: "#/components/schemas/UploadRequest"
24
+ * responses:
25
+ * 200:
26
+ * description: Item uploaded and classified successfully
27
+ * content:
28
+ * application/json:
29
+ * schema:
30
+ * type: object
31
+ * properties:
32
+ * success:
33
+ * type: boolean
34
+ * item:
35
+ * $ref: "#/components/schemas/WardrobeItem"
36
+ * 400:
37
+ * description: Bad request (missing imageUrl)
38
+ * 401:
39
+ * description: Unauthorized
40
+ * 500:
41
+ * description: Server error
42
+ */
43
  router.post("/", authenticateToken, async (req: AuthRequest, res) => {
44
  try {
45
  const { imageUrl } = req.body;