cyberia 3.0.1 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/.github/workflows/engine-cyberia.cd.yml +1 -0
  2. package/CHANGELOG.md +56 -1
  3. package/CLI-HELP.md +2 -4
  4. package/README.md +139 -0
  5. package/bin/build.js +5 -0
  6. package/bin/cyberia.js +385 -71
  7. package/bin/deploy.js +18 -26
  8. package/bin/file.js +3 -0
  9. package/bin/index.js +385 -71
  10. package/conf.js +32 -3
  11. package/deployment.yaml +2 -2
  12. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  13. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  14. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  15. package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
  16. package/manifests/ipfs/configmap.yaml +7 -0
  17. package/package.json +8 -8
  18. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +2 -0
  19. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +7 -0
  20. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +93 -2
  21. package/src/api/file/file.controller.js +3 -13
  22. package/src/api/file/file.ref.json +0 -21
  23. package/src/api/ipfs/ipfs.controller.js +104 -0
  24. package/src/api/ipfs/ipfs.model.js +71 -0
  25. package/src/api/ipfs/ipfs.router.js +31 -0
  26. package/src/api/ipfs/ipfs.service.js +193 -0
  27. package/src/api/object-layer/README.md +139 -0
  28. package/src/api/object-layer/object-layer.controller.js +3 -0
  29. package/src/api/object-layer/object-layer.model.js +15 -1
  30. package/src/api/object-layer/object-layer.router.js +6 -10
  31. package/src/api/object-layer/object-layer.service.js +311 -182
  32. package/src/cli/cluster.js +30 -38
  33. package/src/cli/index.js +0 -1
  34. package/src/cli/run.js +14 -0
  35. package/src/client/components/core/LoadingAnimation.js +2 -3
  36. package/src/client/components/core/Modal.js +1 -1
  37. package/src/client/components/cyberia/ObjectLayerEngineModal.js +4 -5
  38. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +280 -29
  39. package/src/client/services/ipfs/ipfs.service.js +144 -0
  40. package/src/client/services/object-layer/object-layer.management.js +161 -8
  41. package/src/index.js +1 -1
  42. package/src/runtime/express/Express.js +1 -1
  43. package/src/server/auth.js +18 -18
  44. package/src/server/ipfs-client.js +433 -0
  45. package/src/server/object-layer.js +649 -18
  46. package/src/server/semantic-layer-generator.js +1083 -0
  47. package/src/server/shape-generator.js +952 -0
  48. package/test/shape-generator.test.js +457 -0
  49. package/bin/ssl.js +0 -63
@@ -23,7 +23,7 @@ spec:
23
23
  spec:
24
24
  containers:
25
25
  - name: dd-cron-backup
26
- image: underpost/underpost-engine:v3.0.1
26
+ image: underpost/underpost-engine:v3.0.2
27
27
  command:
28
28
  - /bin/sh
29
29
  - -c
@@ -23,7 +23,7 @@ spec:
23
23
  spec:
24
24
  containers:
25
25
  - name: dd-cron-dns
26
- image: underpost/underpost-engine:v3.0.1
26
+ image: underpost/underpost-engine:v3.0.2
27
27
  command:
28
28
  - /bin/sh
29
29
  - -c
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-default-development-blue
20
- image: localhost/rockylinux9-underpost:v3.0.1
20
+ image: localhost/rockylinux9-underpost:v3.0.2
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "124Ki"
@@ -100,7 +100,7 @@ spec:
100
100
  spec:
101
101
  containers:
102
102
  - name: dd-default-development-green
103
- image: localhost/rockylinux9-underpost:v3.0.1
103
+ image: localhost/rockylinux9-underpost:v3.0.2
104
104
  # resources:
105
105
  # requests:
106
106
  # memory: "124Ki"
@@ -18,7 +18,7 @@ spec:
18
18
  spec:
19
19
  containers:
20
20
  - name: dd-test-development-blue
21
- image: localhost/rockylinux9-underpost:v3.0.1
21
+ image: localhost/rockylinux9-underpost:v3.0.2
22
22
 
23
23
  command:
24
24
  - /bin/sh
@@ -103,7 +103,7 @@ spec:
103
103
  spec:
104
104
  containers:
105
105
  - name: dd-test-development-green
106
- image: localhost/rockylinux9-underpost:v3.0.1
106
+ image: localhost/rockylinux9-underpost:v3.0.2
107
107
 
108
108
  command:
109
109
  - /bin/sh
@@ -16,6 +16,13 @@ data:
16
16
  ipfs-cluster-service init
17
17
  fi
18
18
 
19
+ # Bind cluster APIs to 0.0.0.0 so they are reachable from other pods.
20
+ # By default ipfs-cluster listens on 127.0.0.1 for REST (9094),
21
+ # Proxy (9095) and Pinning Service (9097).
22
+ sed -i 's|/ip4/127\.0\.0\.1/tcp/9094|/ip4/0.0.0.0/tcp/9094|g' /data/ipfs-cluster/service.json
23
+ sed -i 's|/ip4/127\.0\.0\.1/tcp/9095|/ip4/0.0.0.0/tcp/9095|g' /data/ipfs-cluster/service.json
24
+ sed -i 's|/ip4/127\.0\.0\.1/tcp/9097|/ip4/0.0.0.0/tcp/9097|g' /data/ipfs-cluster/service.json
25
+
19
26
  PEER_HOSTNAME=$(cat /proc/sys/kernel/hostname)
20
27
 
21
28
  if echo "${PEER_HOSTNAME}" | grep -q "^ipfs-cluster-0"; then
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "cyberia",
5
- "version": "3.0.1",
5
+ "version": "3.0.2",
6
6
  "description": "Cyberia Engine - Object Layer and Assets Management Microservice",
7
7
  "scripts": {
8
8
  "start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
@@ -76,20 +76,24 @@
76
76
  "http-proxy-middleware": "^2.0.6",
77
77
  "ignore-walk": "^8.0.0",
78
78
  "iovalkey": "^0.2.1",
79
+ "jimp": "^1.6.0",
79
80
  "json-colorizer": "^2.2.2",
80
81
  "jsonwebtoken": "^9.0.2",
81
82
  "mariadb": "^3.2.2",
82
83
  "marked": "^12.0.2",
83
- "mocha": "^11.3.0",
84
+ "maxrects-packer": "^2.7.3",
85
+ "mocha": "^7.2.0",
84
86
  "mongoose": "^8.9.5",
85
87
  "morgan": "^1.10.0",
86
88
  "nodemailer": "^7.0.9",
87
89
  "nodemon": "^3.0.1",
88
90
  "peer": "^1.0.2",
89
91
  "peerjs": "^1.5.2",
92
+ "pngjs": "^7.0.0",
90
93
  "prom-client": "^15.1.2",
91
94
  "read": "^2.1.0",
92
95
  "rrule": "^2.8.1",
96
+ "sharp": "^0.32.5",
93
97
  "shelljs": "^0.10.0",
94
98
  "sitemap": "^7.1.1",
95
99
  "socket.io": "^4.8.0",
@@ -100,11 +104,7 @@
100
104
  "uglify-js": "^3.17.4",
101
105
  "validator": "^13.11.0",
102
106
  "vanilla-jsoneditor": "^2.3.2",
103
- "winston": "^3.11.0",
104
- "maxrects-packer": "^2.7.3",
105
- "pngjs": "^7.0.0",
106
- "jimp": "^1.6.0",
107
- "sharp": "^0.32.5"
107
+ "winston": "^3.11.0"
108
108
  },
109
109
  "publishConfig": {
110
110
  "provenance": true,
@@ -115,4 +115,4 @@
115
115
  "minimatch": "^10.2.2",
116
116
  "glob": "^11.0.0"
117
117
  }
118
- }
118
+ }
@@ -51,6 +51,8 @@ const AtlasSpriteSheetController = {
51
51
  },
52
52
  get: async (req, res, options) => {
53
53
  try {
54
+ res.setHeader('Access-Control-Allow-Origin', '*');
55
+ res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
54
56
  const { page, limit } = req.query;
55
57
  const result = await AtlasSpriteSheetService.get(
56
58
  { ...req, query: { ...req.query, page: parseInt(page), limit: parseInt(limit) } },
@@ -75,6 +75,7 @@ const DirectionFramesSchema = new Schema(
75
75
  /**
76
76
  * @typedef {Object} AtlasSpriteSheet
77
77
  * @property {Types.ObjectId} fileId - Reference to File document (consolidated PNG)
78
+ * @property {string} [cid] - IPFS Content Identifier for the atlas PNG
78
79
  * @property {Object} metadata - Atlas sprite sheet metadata
79
80
  * @property {string} metadata.itemKey - Item identifier key for texture reference
80
81
  * @property {number} metadata.atlasWidth - Total atlas width in pixels
@@ -92,6 +93,11 @@ const AtlasSpriteSheetSchema = new Schema(
92
93
  ref: 'File',
93
94
  required: true,
94
95
  },
96
+ cid: {
97
+ type: String,
98
+ default: '',
99
+ trim: true,
100
+ },
95
101
  metadata: {
96
102
  itemKey: { type: String, required: true, trim: true },
97
103
  atlasWidth: { type: Number, required: true, min: 1 },
@@ -129,6 +135,7 @@ const AtlasSpriteSheetDto = {
129
135
  return {
130
136
  _id: 1,
131
137
  fileId: 1,
138
+ cid: 1,
132
139
  metadata: 1,
133
140
  createdAt: 1,
134
141
  updatedAt: 1,
@@ -4,6 +4,8 @@ import { DataQuery } from '../../server/data-query.js';
4
4
  import { AtlasSpriteSheetGenerator } from '../../server/atlas-sprite-sheet-generator.js';
5
5
  import { FileFactory } from '../file/file.service.js';
6
6
  import { AtlasSpriteSheetDto } from './atlas-sprite-sheet.model.js';
7
+ import { IpfsClient } from '../../server/ipfs-client.js';
8
+ import { createPinRecord, removePinRecordsAndUnpin } from '../ipfs/ipfs.service.js';
7
9
 
8
10
  const logger = loggerFactory(import.meta);
9
11
 
@@ -39,6 +41,27 @@ const AtlasSpriteSheetService = {
39
41
 
40
42
  const fileDoc = await new File(FileFactory.create(buffer, `${itemKey}.png`)).save();
41
43
 
44
+ // Add atlas PNG to IPFS and obtain its CID
45
+ let atlasCid = '';
46
+ try {
47
+ const ipfsResult = await IpfsClient.addBufferToIpfs(
48
+ buffer,
49
+ `${itemKey}_atlas_sprite_sheet.png`,
50
+ `/object-layer/${itemKey}/${itemKey}_atlas_sprite_sheet.png`,
51
+ );
52
+ if (ipfsResult) {
53
+ atlasCid = ipfsResult.cid;
54
+ // Create pin record for the authenticated user (when available)
55
+ const userId = req.auth && req.auth.user ? req.auth.user._id : undefined;
56
+ if (userId) {
57
+ await createPinRecord({ cid: atlasCid, userId, options });
58
+ }
59
+ logger.info(`Atlas sprite sheet pinned to IPFS – CID: ${atlasCid}`);
60
+ }
61
+ } catch (ipfsError) {
62
+ logger.warn('Failed to add atlas sprite sheet to IPFS:', ipfsError.message);
63
+ }
64
+
42
65
  let atlasDoc = await AtlasSpriteSheet.findOne({ 'metadata.itemKey': itemKey });
43
66
 
44
67
  if (atlasDoc) {
@@ -47,16 +70,20 @@ const AtlasSpriteSheetService = {
47
70
  await File.findByIdAndDelete(atlasDoc.fileId);
48
71
  }
49
72
  atlasDoc.fileId = fileDoc._id;
73
+ atlasDoc.cid = atlasCid;
50
74
  atlasDoc.metadata = metadata;
51
75
  await atlasDoc.save();
52
76
  } else {
53
77
  atlasDoc = await new AtlasSpriteSheet({
54
78
  fileId: fileDoc._id,
79
+ cid: atlasCid,
55
80
  metadata,
56
81
  }).save();
57
82
  }
58
83
 
59
84
  objectLayer.atlasSpriteSheetId = atlasDoc._id;
85
+ objectLayer.data.atlasSpriteSheetCid = atlasCid;
86
+ objectLayer.markModified('data.atlasSpriteSheetCid');
60
87
  await objectLayer.save();
61
88
 
62
89
  return atlasDoc;
@@ -78,12 +105,30 @@ const AtlasSpriteSheetService = {
78
105
  if (objectLayer.atlasSpriteSheetId) {
79
106
  const atlasDoc = await AtlasSpriteSheet.findById(objectLayer.atlasSpriteSheetId);
80
107
  if (atlasDoc) {
108
+ // Remove pin records and unpin atlas CID from IPFS
109
+ const atlasCid = atlasDoc.cid || objectLayer.data.atlasSpriteSheetCid;
110
+ if (atlasCid) {
111
+ try {
112
+ await removePinRecordsAndUnpin(atlasCid, options);
113
+ // Remove the MFS entry for the atlas sprite sheet PNG
114
+ const itemId = objectLayer.data.item.id;
115
+ await IpfsClient.removeMfsPath(`/object-layer/${itemId}/${itemId}_atlas_sprite_sheet.png`);
116
+ logger.info(`Cleaned up IPFS atlas CID ${atlasCid} for ObjectLayer ${objectLayer._id}`);
117
+ } catch (ipfsErr) {
118
+ logger.warn(`Failed to clean up IPFS atlas CID ${atlasCid}: ${ipfsErr.message}`);
119
+ }
120
+ }
121
+
122
+ // Delete the atlas File document from MongoDB
81
123
  if (atlasDoc.fileId) {
82
124
  await File.findByIdAndDelete(atlasDoc.fileId);
83
125
  }
126
+ // Delete the AtlasSpriteSheet document itself
84
127
  await AtlasSpriteSheet.findByIdAndDelete(atlasDoc._id);
85
128
  }
86
129
  objectLayer.atlasSpriteSheetId = undefined;
130
+ objectLayer.data.atlasSpriteSheetCid = '';
131
+ objectLayer.markModified('data.atlasSpriteSheetCid');
87
132
  await objectLayer.save();
88
133
  }
89
134
 
@@ -130,8 +175,54 @@ const AtlasSpriteSheetService = {
130
175
  /** @type {import('./atlas-sprite-sheet.model.js').AtlasSpriteSheetModel} */
131
176
  const AtlasSpriteSheet =
132
177
  DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.AtlasSpriteSheet;
133
- if (req.params.id) return await AtlasSpriteSheet.findByIdAndDelete(req.params.id);
134
- else return await AtlasSpriteSheet.deleteMany();
178
+ /** @type {import('../file/file.model.js').FileModel} */
179
+ const File = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.File;
180
+
181
+ if (req.params.id) {
182
+ const atlasDoc = await AtlasSpriteSheet.findById(req.params.id);
183
+ if (!atlasDoc) return null;
184
+
185
+ // Remove pin records and unpin atlas CID from IPFS
186
+ if (atlasDoc.cid) {
187
+ try {
188
+ await removePinRecordsAndUnpin(atlasDoc.cid, options);
189
+ if (atlasDoc.metadata?.itemKey) {
190
+ const itemKey = atlasDoc.metadata.itemKey;
191
+ await IpfsClient.removeMfsPath(`/object-layer/${itemKey}/${itemKey}_atlas_sprite_sheet.png`);
192
+ }
193
+ logger.info(`Cleaned up IPFS atlas CID ${atlasDoc.cid} for AtlasSpriteSheet ${atlasDoc._id}`);
194
+ } catch (ipfsErr) {
195
+ logger.warn(`Failed to clean up IPFS atlas CID ${atlasDoc.cid}: ${ipfsErr.message}`);
196
+ }
197
+ }
198
+
199
+ // Delete the referenced File document (the atlas PNG blob)
200
+ if (atlasDoc.fileId) {
201
+ await File.findByIdAndDelete(atlasDoc.fileId);
202
+ }
203
+
204
+ return await AtlasSpriteSheet.findByIdAndDelete(req.params.id);
205
+ } else {
206
+ // Bulk delete: iterate each atlas to clean up File, IPFS pins, and pin records
207
+ const allAtlases = await AtlasSpriteSheet.find({});
208
+ for (const atlasDoc of allAtlases) {
209
+ try {
210
+ if (atlasDoc.cid) {
211
+ await removePinRecordsAndUnpin(atlasDoc.cid, options);
212
+ if (atlasDoc.metadata?.itemKey) {
213
+ const itemKey = atlasDoc.metadata.itemKey;
214
+ await IpfsClient.removeMfsPath(`/object-layer/${itemKey}/${itemKey}_atlas_sprite_sheet.png`);
215
+ }
216
+ }
217
+ if (atlasDoc.fileId) {
218
+ await File.findByIdAndDelete(atlasDoc.fileId);
219
+ }
220
+ } catch (err) {
221
+ logger.error(`Failed to clean up AtlasSpriteSheet ${atlasDoc._id} during bulk delete: ${err.message}`);
222
+ }
223
+ }
224
+ return await AtlasSpriteSheet.deleteMany();
225
+ }
135
226
  },
136
227
  };
137
228
 
@@ -19,22 +19,12 @@ const FileController = {
19
19
  },
20
20
  get: async (req, res, options) => {
21
21
  try {
22
+ res.setHeader('Access-Control-Allow-Origin', '*');
23
+ res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
22
24
  const result = await FileService.get(req, res, options);
23
25
  if (result instanceof Buffer) {
24
- if (
25
- process.env.NODE_ENV === 'development' ||
26
- req.hostname === options.host ||
27
- (options.origins && options.origins.find((o) => o.match(req.hostname)))
28
- ) {
29
- res.set('Cross-Origin-Resource-Policy', 'cross-origin');
30
- return res.status(200).end(result);
31
- }
32
- return res.status(403).json({
33
- status: 'error',
34
- message: 'Forbidden',
35
- });
26
+ return res.status(200).end(result);
36
27
  }
37
-
38
28
  return res.status(200).json({
39
29
  status: 'success',
40
30
  data: result,
@@ -5,27 +5,6 @@
5
5
  "logo": true
6
6
  }
7
7
  },
8
- {
9
- "api": "cyberia-biome",
10
- "model": {
11
- "fileId": true,
12
- "topLevelColorFileId": true
13
- }
14
- },
15
- {
16
- "api": "cyberia-tile",
17
- "model": {
18
- "fileId": true
19
- }
20
- },
21
- {
22
- "api": "cyberia-world",
23
- "model": {
24
- "adjacentFace": {
25
- "fileId": true
26
- }
27
- }
28
- },
29
8
  {
30
9
  "api": "document",
31
10
  "model": {
@@ -0,0 +1,104 @@
1
+ import { loggerFactory } from '../../server/logger.js';
2
+ import { IpfsService } from './ipfs.service.js';
3
+
4
+ const logger = loggerFactory(import.meta);
5
+
6
+ const IpfsController = {
7
+ post: async (req, res, options) => {
8
+ try {
9
+ const result = await IpfsService.post(req, res, options);
10
+ return res.status(200).json({
11
+ status: 'success',
12
+ data: result,
13
+ });
14
+ } catch (error) {
15
+ logger.error(error, error.stack);
16
+ return res.status(400).json({
17
+ status: 'error',
18
+ message: error.message,
19
+ });
20
+ }
21
+ },
22
+ get: async (req, res, options) => {
23
+ try {
24
+ const { page, limit } = req.query;
25
+ const result = await IpfsService.get(
26
+ { ...req, query: { ...req.query, page: parseInt(page), limit: parseInt(limit) } },
27
+ res,
28
+ options,
29
+ );
30
+ return res.status(200).json({
31
+ status: 'success',
32
+ data: result,
33
+ });
34
+ } catch (error) {
35
+ logger.error(error, error.stack);
36
+ return res.status(400).json({
37
+ status: 'error',
38
+ message: error.message,
39
+ });
40
+ }
41
+ },
42
+ put: async (req, res, options) => {
43
+ try {
44
+ const result = await IpfsService.put(req, res, options);
45
+ return res.status(200).json({
46
+ status: 'success',
47
+ data: result,
48
+ });
49
+ } catch (error) {
50
+ logger.error(error, error.stack);
51
+ return res.status(400).json({
52
+ status: 'error',
53
+ message: error.message,
54
+ });
55
+ }
56
+ },
57
+ delete: async (req, res, options) => {
58
+ try {
59
+ const result = await IpfsService.delete(req, res, options);
60
+ return res.status(200).json({
61
+ status: 'success',
62
+ data: result,
63
+ });
64
+ } catch (error) {
65
+ logger.error(error, error.stack);
66
+ return res.status(400).json({
67
+ status: 'error',
68
+ message: error.message,
69
+ });
70
+ }
71
+ },
72
+ pin: async (req, res, options) => {
73
+ try {
74
+ const result = await IpfsService.pin(req, res, options);
75
+ return res.status(200).json({
76
+ status: 'success',
77
+ data: result,
78
+ });
79
+ } catch (error) {
80
+ logger.error(error, error.stack);
81
+ return res.status(400).json({
82
+ status: 'error',
83
+ message: error.message,
84
+ });
85
+ }
86
+ },
87
+ unpin: async (req, res, options) => {
88
+ try {
89
+ const result = await IpfsService.unpin(req, res, options);
90
+ return res.status(200).json({
91
+ status: 'success',
92
+ data: result,
93
+ });
94
+ } catch (error) {
95
+ logger.error(error, error.stack);
96
+ return res.status(400).json({
97
+ status: 'error',
98
+ message: error.message,
99
+ });
100
+ }
101
+ },
102
+ };
103
+
104
+ export { IpfsController };
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Mongoose model for IPFS API – a general-purpose pin record that relates
3
+ * a user to a CID.
4
+ *
5
+ * @module src/api/ipfs/ipfs.model.js
6
+ * @namespace IpfsModel
7
+ */
8
+
9
+ import { Schema, model } from 'mongoose';
10
+
11
+ /**
12
+ * @typedef {Object} Ipfs
13
+ * @property {string} cid – IPFS Content Identifier (CIDv0 or CIDv1).
14
+ * @property {Types.ObjectId} userId – Reference to the User who owns / requested the pin.
15
+ * @property {Date} createdAt – Auto-managed by Mongoose.
16
+ * @property {Date} updatedAt – Auto-managed by Mongoose.
17
+ * @memberof IpfsModel
18
+ */
19
+ const IpfsSchema = new Schema(
20
+ {
21
+ cid: {
22
+ type: String,
23
+ required: true,
24
+ trim: true,
25
+ },
26
+ userId: {
27
+ type: Schema.Types.ObjectId,
28
+ ref: 'User',
29
+ required: true,
30
+ },
31
+ },
32
+ {
33
+ timestamps: true,
34
+ },
35
+ );
36
+
37
+ // Compound index: one pin record per user + CID pair.
38
+ IpfsSchema.index({ cid: 1, userId: 1 }, { unique: true });
39
+
40
+ // Fast look-ups by user.
41
+ IpfsSchema.index({ userId: 1 });
42
+
43
+ // Fast look-ups by CID.
44
+ IpfsSchema.index({ cid: 1 });
45
+
46
+ const IpfsModel = model('Ipfs', IpfsSchema);
47
+
48
+ const ProviderSchema = IpfsSchema;
49
+
50
+ const IpfsDto = {
51
+ select: {
52
+ get: () => {
53
+ return {
54
+ _id: 1,
55
+ cid: 1,
56
+ userId: 1,
57
+ createdAt: 1,
58
+ updatedAt: 1,
59
+ };
60
+ },
61
+ },
62
+ populate: {
63
+ user: () => ({
64
+ path: 'userId',
65
+ model: 'User',
66
+ select: '_id username email role',
67
+ }),
68
+ },
69
+ };
70
+
71
+ export { IpfsSchema, IpfsModel, ProviderSchema, IpfsDto };
@@ -0,0 +1,31 @@
1
+ import { adminGuard } from '../../server/auth.js';
2
+ import { loggerFactory } from '../../server/logger.js';
3
+ import { IpfsController } from './ipfs.controller.js';
4
+ import express from 'express';
5
+
6
+ const logger = loggerFactory(import.meta);
7
+
8
+ const IpfsRouter = (options) => {
9
+ const router = express.Router();
10
+ const authMiddleware = options.authMiddleware;
11
+ router.post(`/pin`, authMiddleware, adminGuard, async (req, res) => await IpfsController.pin(req, res, options));
12
+ router.delete(
13
+ `/pin/:cid`,
14
+ authMiddleware,
15
+ adminGuard,
16
+ async (req, res) => await IpfsController.unpin(req, res, options),
17
+ );
18
+ router.post(`/:id`, authMiddleware, async (req, res) => await IpfsController.post(req, res, options));
19
+ router.post(`/`, authMiddleware, async (req, res) => await IpfsController.post(req, res, options));
20
+ router.get(`/:id`, authMiddleware, async (req, res) => await IpfsController.get(req, res, options));
21
+ router.get(`/`, authMiddleware, async (req, res) => await IpfsController.get(req, res, options));
22
+ router.put(`/:id`, authMiddleware, async (req, res) => await IpfsController.put(req, res, options));
23
+ router.put(`/`, authMiddleware, async (req, res) => await IpfsController.put(req, res, options));
24
+ router.delete(`/:id`, authMiddleware, adminGuard, async (req, res) => await IpfsController.delete(req, res, options));
25
+ router.delete(`/`, authMiddleware, adminGuard, async (req, res) => await IpfsController.delete(req, res, options));
26
+ return router;
27
+ };
28
+
29
+ const ApiRouter = IpfsRouter;
30
+
31
+ export { ApiRouter, IpfsRouter };