@arken/seer-protocol 0.1.0 → 0.1.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.
- package/.rush/temp/shrinkwrap-deps.json +537 -56
- package/area/area.models.ts +15 -0
- package/area/area.router.ts +74 -0
- package/area/area.schema.ts +22 -0
- package/area/area.types.ts +26 -0
- package/area/index.ts +5 -0
- package/asset/asset.models.ts +59 -0
- package/asset/asset.router.ts +55 -0
- package/asset/asset.schema.ts +27 -0
- package/asset/asset.types.ts +22 -0
- package/asset/index.ts +5 -0
- package/chain/chain.models.ts +50 -0
- package/chain/chain.router.ts +104 -0
- package/chain/chain.schema.ts +52 -0
- package/chain/chain.types.ts +24 -0
- package/chain/index.ts +5 -0
- package/character/character.models.ts +174 -0
- package/character/character.router.ts +314 -0
- package/character/character.schema.ts +147 -0
- package/character/character.types.ts +64 -0
- package/character/index.ts +5 -0
- package/chat/chat.models.ts +43 -0
- package/chat/chat.router.ts +67 -0
- package/chat/chat.schema.ts +36 -0
- package/chat/chat.types.ts +20 -0
- package/chat/index.ts +5 -0
- package/collection/collection.models.ts +76 -0
- package/collection/collection.router.ts +91 -0
- package/collection/collection.schema.ts +90 -0
- package/collection/collection.types.ts +36 -0
- package/collection/index.ts +5 -0
- package/core/core.models.ts +1380 -0
- package/core/core.router.ts +1781 -0
- package/core/core.schema.ts +847 -0
- package/core/core.types.ts +340 -0
- package/core/index.ts +5 -0
- package/{src/modules/evolution → evolution}/evolution.models.ts +1 -1
- package/{src/modules/evolution → evolution}/evolution.router.ts +5 -5
- package/{src/modules/evolution → evolution}/evolution.types.ts +1 -1
- package/game/game.models.ts +53 -0
- package/game/game.router.ts +110 -0
- package/game/game.schema.ts +23 -0
- package/game/game.types.ts +28 -0
- package/game/index.ts +5 -0
- package/index.ts +59 -0
- package/{src/modules/infinite → infinite}/infinite.models.ts +1 -1
- package/{src/modules/infinite → infinite}/infinite.router.ts +5 -5
- package/{src/modules/infinite → infinite}/infinite.types.ts +1 -1
- package/interface/index.ts +5 -0
- package/interface/interface.canonicalize.ts +279 -0
- package/interface/interface.models.ts +40 -0
- package/interface/interface.router.ts +175 -0
- package/interface/interface.schema.ts +59 -0
- package/interface/interface.types.ts +25 -0
- package/{src/modules/isles → isles}/isles.models.ts +1 -1
- package/{src/modules/isles → isles}/isles.router.ts +5 -5
- package/{src/modules/isles → isles}/isles.types.ts +1 -1
- package/item/index.ts +5 -0
- package/item/item.models.ts +124 -0
- package/item/item.router.ts +103 -0
- package/item/item.schema.ts +120 -0
- package/item/item.types.ts +74 -0
- package/job/index.ts +5 -0
- package/job/job.models.ts +14 -0
- package/job/job.router.ts +44 -0
- package/job/job.schema.ts +9 -0
- package/job/job.types.ts +23 -0
- package/market/index.ts +5 -0
- package/market/market.models.ts +113 -0
- package/market/market.router.ts +73 -0
- package/market/market.schema.ts +140 -0
- package/market/market.types.ts +56 -0
- package/{src/modules/oasis → oasis}/oasis.models.ts +1 -1
- package/{src/modules/oasis → oasis}/oasis.router.ts +1 -1
- package/{src/modules/oasis → oasis}/oasis.types.ts +1 -1
- package/package.json +12 -14
- package/product/index.ts +5 -0
- package/product/product.models.ts +166 -0
- package/product/product.router.ts +93 -0
- package/product/product.schema.ts +149 -0
- package/product/product.types.ts +33 -0
- package/profile/index.ts +5 -0
- package/profile/profile.models.ts +214 -0
- package/profile/profile.router.ts +72 -0
- package/profile/profile.schema.ts +156 -0
- package/profile/profile.types.ts +22 -0
- package/raffle/index.ts +5 -0
- package/raffle/raffle.models.ts +44 -0
- package/raffle/raffle.router.ts +90 -0
- package/raffle/raffle.schema.ts +32 -0
- package/raffle/raffle.types.ts +30 -0
- package/{src/router.ts → router.ts} +22 -28
- package/schema.ts +321 -0
- package/skill/index.ts +5 -0
- package/skill/skill.models.ts +16 -0
- package/skill/skill.router.ts +201 -0
- package/skill/skill.schema.ts +40 -0
- package/skill/skill.types.ts +33 -0
- package/{src/modules/trek → trek}/trek.router.ts +1 -1
- package/types.ts +273 -0
- package/video/index.ts +5 -0
- package/video/video.models.ts +25 -0
- package/video/video.router.ts +143 -0
- package/video/video.schema.ts +46 -0
- package/video/video.types.ts +33 -0
- package/src/index.ts +0 -22
- package/src/modules/evolution/evolution.service.ts +0 -2000
- package/src/modules/infinite/infinite.service.ts +0 -40
- package/src/modules/isles/isles.service.ts +0 -40
- package/src/modules/oasis/oasis.service.ts +0 -38
- package/src/modules/trek/trek.service.ts +0 -1031
- package/src/types.ts +0 -106
- /package/{src/modules/evolution → evolution}/evolution.schema.ts +0 -0
- /package/{src/modules/evolution → evolution}/index.ts +0 -0
- /package/{src/modules/infinite → infinite}/index.ts +0 -0
- /package/{src/modules/infinite → infinite}/infinite.schema.ts +0 -0
- /package/{src/modules/isles → isles}/index.ts +0 -0
- /package/{src/modules/isles → isles}/isles.schema.ts +0 -0
- /package/{src/modules/oasis → oasis}/index.ts +0 -0
- /package/{src/modules/oasis → oasis}/oasis.schema.ts +0 -0
- /package/{src/modules/trek → trek}/index.ts +0 -0
- /package/{src/modules/trek → trek}/trek.models.ts +0 -0
- /package/{src/modules/trek → trek}/trek.schema.ts +0 -0
- /package/{src/modules/trek → trek}/trek.types.ts +0 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { z, ObjectId, Entity } from '../../schema';
|
|
2
|
+
|
|
3
|
+
// Extend the ProductMeta schema
|
|
4
|
+
const ProductMeta = z.object({
|
|
5
|
+
name: z.string(),
|
|
6
|
+
members: z.array(ObjectId), // Array of Profile references
|
|
7
|
+
isProposal: z.boolean(),
|
|
8
|
+
price: z.number().nonnegative(),
|
|
9
|
+
oldPrice: z.number().nonnegative().optional(),
|
|
10
|
+
images: z.record(z.string(), z.any()),
|
|
11
|
+
video: z.string().url(),
|
|
12
|
+
genre: z.string(),
|
|
13
|
+
releaseDate: z.string(),
|
|
14
|
+
developer: z.string(),
|
|
15
|
+
publisher: z.string(),
|
|
16
|
+
developerTags: z.array(z.string()),
|
|
17
|
+
languageSupport: z.array(z.any()), // Replace with actual Language schema if available
|
|
18
|
+
systemRequirements: z.array(z.any()), // Replace with actual SystemRequirement schema if available
|
|
19
|
+
tags: z.array(ObjectId), // Array of Tag references
|
|
20
|
+
type: z.string(),
|
|
21
|
+
downloads: z.number().int().nonnegative(),
|
|
22
|
+
plans: z.array(z.any()), // Replace with actual ProductPlan schema if available
|
|
23
|
+
frequentlyTradedAssets: z.array(ObjectId), // Array of Asset references
|
|
24
|
+
saleBox: z.record(z.string(), z.any()),
|
|
25
|
+
assets: z.array(ObjectId), // Array of Asset references
|
|
26
|
+
community: z.record(z.string(), z.any()),
|
|
27
|
+
nameUrl: z.string(),
|
|
28
|
+
steamId: z.number().int(),
|
|
29
|
+
author: z.string(),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Updated Product schema
|
|
33
|
+
export const Product = Entity.merge(
|
|
34
|
+
z.object({
|
|
35
|
+
shortDescription: z.string().max(300).min(1),
|
|
36
|
+
content: z.string().min(1),
|
|
37
|
+
communityId: ObjectId,
|
|
38
|
+
type: z.string().max(100).default('game'),
|
|
39
|
+
releaseDate: z.date().optional(),
|
|
40
|
+
sku: z.string().min(1),
|
|
41
|
+
categoryId: ObjectId.optional(),
|
|
42
|
+
price: z.number().nonnegative(),
|
|
43
|
+
discountPrice: z.number().nonnegative().optional(),
|
|
44
|
+
currency: z.string().length(3),
|
|
45
|
+
images: z.array(z.string().url()).optional(),
|
|
46
|
+
videos: z.array(z.string().url()).optional(),
|
|
47
|
+
digitalContent: z
|
|
48
|
+
.array(
|
|
49
|
+
z.object({
|
|
50
|
+
url: z.string().url(),
|
|
51
|
+
size: z.number().nonnegative(),
|
|
52
|
+
drm: z.enum(['None', 'Steam', 'Epic', 'Uplay', 'Origin']).optional(),
|
|
53
|
+
})
|
|
54
|
+
)
|
|
55
|
+
.optional(),
|
|
56
|
+
dlcs: z.array(ObjectId).optional(),
|
|
57
|
+
bundles: z.array(ObjectId).optional(),
|
|
58
|
+
achievements: z
|
|
59
|
+
.array(
|
|
60
|
+
z.object({
|
|
61
|
+
name: z.string(),
|
|
62
|
+
description: z.string().optional(),
|
|
63
|
+
icon: z.string().url().optional(),
|
|
64
|
+
})
|
|
65
|
+
)
|
|
66
|
+
.optional(),
|
|
67
|
+
reviews: z
|
|
68
|
+
.array(
|
|
69
|
+
z.object({
|
|
70
|
+
userId: ObjectId,
|
|
71
|
+
rating: z.number().min(1).max(5),
|
|
72
|
+
comment: z.string().optional(),
|
|
73
|
+
createdDate: z.date().default(() => new Date()),
|
|
74
|
+
})
|
|
75
|
+
)
|
|
76
|
+
.optional(),
|
|
77
|
+
cloudSave: z.boolean().default(false),
|
|
78
|
+
ugcSupport: z.boolean().default(false),
|
|
79
|
+
wishlistCount: z.number().int().nonnegative().default(0),
|
|
80
|
+
|
|
81
|
+
// Additional fields from Objection.js model
|
|
82
|
+
parentId: ObjectId.optional(),
|
|
83
|
+
score: z.number().optional(),
|
|
84
|
+
ownerId: ObjectId.optional(),
|
|
85
|
+
ratingId: ObjectId.optional(),
|
|
86
|
+
ideaId: ObjectId.optional(),
|
|
87
|
+
meta: ProductMeta.optional(),
|
|
88
|
+
})
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// ProductDLC schema
|
|
92
|
+
export const ProductDLC = Entity.merge(
|
|
93
|
+
z.object({
|
|
94
|
+
name: z.string().min(1),
|
|
95
|
+
description: z.string().optional(),
|
|
96
|
+
gameId: ObjectId,
|
|
97
|
+
price: z.number().nonnegative(),
|
|
98
|
+
discountPrice: z.number().nonnegative().optional(),
|
|
99
|
+
currency: z.string().length(3),
|
|
100
|
+
digitalContent: z
|
|
101
|
+
.array(
|
|
102
|
+
z.object({
|
|
103
|
+
url: z.string().url(),
|
|
104
|
+
size: z.number().nonnegative(),
|
|
105
|
+
drm: z.enum(['None', 'Steam', 'Epic', 'Uplay', 'Origin']).optional(),
|
|
106
|
+
})
|
|
107
|
+
)
|
|
108
|
+
.optional(),
|
|
109
|
+
achievements: z
|
|
110
|
+
.array(
|
|
111
|
+
z.object({
|
|
112
|
+
name: z.string(),
|
|
113
|
+
description: z.string().optional(),
|
|
114
|
+
icon: z.string().url().optional(),
|
|
115
|
+
})
|
|
116
|
+
)
|
|
117
|
+
.optional(),
|
|
118
|
+
})
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
// ProductBundle schema
|
|
122
|
+
export const ProductBundle = Entity.merge(
|
|
123
|
+
z.object({
|
|
124
|
+
name: z.string().min(1),
|
|
125
|
+
description: z.string().optional(),
|
|
126
|
+
products: z.array(ObjectId),
|
|
127
|
+
price: z.number().nonnegative(),
|
|
128
|
+
discountPrice: z.number().nonnegative().optional(),
|
|
129
|
+
currency: z.string().length(3),
|
|
130
|
+
})
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
// ProductReview schema
|
|
134
|
+
export const ProductReview = Entity.merge(
|
|
135
|
+
z.object({
|
|
136
|
+
userId: ObjectId,
|
|
137
|
+
productId: ObjectId,
|
|
138
|
+
rating: z.number().min(1).max(5),
|
|
139
|
+
comment: z.string().optional(),
|
|
140
|
+
})
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
export const ProductUpdate = Entity.merge(
|
|
144
|
+
z.object({
|
|
145
|
+
productId: ObjectId,
|
|
146
|
+
updateContent: z.string().min(1),
|
|
147
|
+
updateDate: z.date(),
|
|
148
|
+
})
|
|
149
|
+
);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import * as schema from './product.schema';
|
|
3
|
+
import { Document, Model } from '../../util/mongo';
|
|
4
|
+
import type { RouterContext } from '../../types';
|
|
5
|
+
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
|
|
6
|
+
import type { Router } from './product.router';
|
|
7
|
+
|
|
8
|
+
export type * from './product.router';
|
|
9
|
+
export type * from './product.service';
|
|
10
|
+
export type { RouterContext };
|
|
11
|
+
|
|
12
|
+
export type Product = z.infer<typeof schema.Product>;
|
|
13
|
+
export type ProductUpdate = z.infer<typeof schema.ProductUpdate>;
|
|
14
|
+
export type ProductDLC = z.infer<typeof schema.ProductDLC>;
|
|
15
|
+
export type ProductBundle = z.infer<typeof schema.ProductBundle>;
|
|
16
|
+
export type ProductReview = z.infer<typeof schema.ProductReview>;
|
|
17
|
+
|
|
18
|
+
export type ProductDocument = Product & Document;
|
|
19
|
+
export type ProductUpdateDocument = ProductUpdate & Document;
|
|
20
|
+
export type ProductDLCDocument = ProductDLC & Document;
|
|
21
|
+
export type ProductBundleDocument = ProductBundle & Document;
|
|
22
|
+
export type ProductReviewDocument = ProductReview & Document;
|
|
23
|
+
|
|
24
|
+
export type Mappings = {
|
|
25
|
+
Product: Model<ProductDocument>;
|
|
26
|
+
ProductUpdate: Model<ProductUpdateDocument>;
|
|
27
|
+
ProductDLC: Model<ProductDLCDocument>;
|
|
28
|
+
ProductBundle: Model<ProductBundleDocument>;
|
|
29
|
+
ProductReview: Model<ProductReviewDocument>;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type RouterInput = inferRouterInputs<Router>;
|
|
33
|
+
export type RouterOutput = inferRouterOutputs<Router>;
|
package/profile/index.ts
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// profile.models.ts
|
|
2
|
+
//
|
|
3
|
+
import * as mongo from '../../util/mongo';
|
|
4
|
+
import type * as Types from './profile.types';
|
|
5
|
+
|
|
6
|
+
const { addTagVirtuals, addApplicationVirtual } = mongo;
|
|
7
|
+
|
|
8
|
+
const RankingStatSchema = new mongo.Schema(
|
|
9
|
+
{
|
|
10
|
+
total: { type: Number, required: true },
|
|
11
|
+
position: { type: Number, required: true },
|
|
12
|
+
},
|
|
13
|
+
{ _id: false }
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const RankingSchema = new mongo.Schema(
|
|
17
|
+
{
|
|
18
|
+
orbs: { type: RankingStatSchema, required: true },
|
|
19
|
+
wins: { type: RankingStatSchema, required: true },
|
|
20
|
+
kills: { type: RankingStatSchema, required: true },
|
|
21
|
+
deaths: { type: RankingStatSchema, required: true },
|
|
22
|
+
points: { type: RankingStatSchema, required: true },
|
|
23
|
+
rounds: { type: RankingStatSchema, required: true },
|
|
24
|
+
evolves: { type: RankingStatSchema, required: true },
|
|
25
|
+
rewards: { type: RankingStatSchema, required: true },
|
|
26
|
+
powerups: { type: RankingStatSchema, required: true },
|
|
27
|
+
revenges: { type: RankingStatSchema, required: true },
|
|
28
|
+
winRatio: { type: RankingStatSchema, required: true },
|
|
29
|
+
timeSpent: { type: RankingStatSchema, required: true },
|
|
30
|
+
averageLatency: { type: RankingStatSchema, required: true },
|
|
31
|
+
killDeathRatio: { type: RankingStatSchema, required: true },
|
|
32
|
+
roundPointRatio: { type: RankingStatSchema, required: true },
|
|
33
|
+
},
|
|
34
|
+
{ _id: false }
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const ServerDataSchema = new mongo.Schema(
|
|
38
|
+
{
|
|
39
|
+
orbs: { type: Number },
|
|
40
|
+
wins: { type: Number },
|
|
41
|
+
kills: { type: Number },
|
|
42
|
+
deaths: { type: Number },
|
|
43
|
+
points: { type: Number },
|
|
44
|
+
rounds: { type: Number },
|
|
45
|
+
evolves: { type: Number },
|
|
46
|
+
ranking: { type: RankingSchema },
|
|
47
|
+
rewards: { type: Number },
|
|
48
|
+
earnings: { type: Number },
|
|
49
|
+
powerups: { type: Number },
|
|
50
|
+
revenges: { type: Number },
|
|
51
|
+
winRatio: { type: Number },
|
|
52
|
+
timeSpent: { type: Number },
|
|
53
|
+
winStreak: { type: Number },
|
|
54
|
+
averageLatency: { type: Number, default: null },
|
|
55
|
+
killDeathRatio: { type: Number },
|
|
56
|
+
roundPointRatio: { type: Number },
|
|
57
|
+
},
|
|
58
|
+
{ _id: false }
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const EvolutionSchema = new mongo.Schema(
|
|
62
|
+
{
|
|
63
|
+
hashes: [{ type: String }],
|
|
64
|
+
overall: {
|
|
65
|
+
orbs: { type: Number },
|
|
66
|
+
wins: { type: Number },
|
|
67
|
+
kills: { type: Number },
|
|
68
|
+
deaths: { type: Number },
|
|
69
|
+
points: { type: Number },
|
|
70
|
+
rounds: { type: Number },
|
|
71
|
+
evolves: { type: Number },
|
|
72
|
+
ranking: { type: RankingSchema },
|
|
73
|
+
rewards: { type: Number },
|
|
74
|
+
earnings: { type: Number },
|
|
75
|
+
powerups: { type: Number },
|
|
76
|
+
revenges: { type: Number },
|
|
77
|
+
winRatio: { type: Number },
|
|
78
|
+
timeSpent: { type: Number },
|
|
79
|
+
winStreak: { type: Number },
|
|
80
|
+
averageLatency: { type: Number },
|
|
81
|
+
killDeathRatio: { type: Number },
|
|
82
|
+
roundPointRatio: { type: Number },
|
|
83
|
+
},
|
|
84
|
+
servers: { type: Map, of: ServerDataSchema },
|
|
85
|
+
lastUpdated: { type: Number },
|
|
86
|
+
},
|
|
87
|
+
{ _id: false }
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// StatsSchema
|
|
91
|
+
const StatsSchema = new mongo.Schema(
|
|
92
|
+
{
|
|
93
|
+
gamesOwned: { type: Number, default: 0 },
|
|
94
|
+
playedMinutes: { type: Number, default: 0 },
|
|
95
|
+
leveledUpCount: { type: Number, default: 0 },
|
|
96
|
+
xpEarnedCount: { type: Number, default: 0 },
|
|
97
|
+
craftedItemCount: { type: Number, default: 0 },
|
|
98
|
+
equippedItemCount: { type: Number, default: 0 },
|
|
99
|
+
transferredInCount: { type: Number, default: 0 },
|
|
100
|
+
transferredOutCount: { type: Number, default: 0 },
|
|
101
|
+
marketTradeSoldCount: { type: Number, default: 0 },
|
|
102
|
+
marketTradeListedCount: { type: Number, default: 0 },
|
|
103
|
+
evolution: { type: EvolutionSchema },
|
|
104
|
+
},
|
|
105
|
+
{ _id: false }
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
const SettingsSchema = new mongo.Schema(
|
|
109
|
+
{
|
|
110
|
+
warp: { type: mongo.Schema.Types.Mixed, default: {} },
|
|
111
|
+
designer: { type: mongo.Schema.Types.Mixed, default: {} },
|
|
112
|
+
privacy: {
|
|
113
|
+
type: String,
|
|
114
|
+
enum: ['public', 'private', 'friends-only'],
|
|
115
|
+
default: 'public',
|
|
116
|
+
},
|
|
117
|
+
notifications: { type: Boolean, default: true },
|
|
118
|
+
},
|
|
119
|
+
{ _id: false }
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// const CharacterSubSchema = new mongo.Schema(
|
|
123
|
+
// {
|
|
124
|
+
// characterId: { type: mongo.Schema.Types.ObjectId, ref: 'Character', required: true, autopopulate: true },
|
|
125
|
+
// meta: { type: mongo.Schema.Types.Mixed, default: {} },
|
|
126
|
+
// },
|
|
127
|
+
// { _id: false }
|
|
128
|
+
// );
|
|
129
|
+
|
|
130
|
+
// CharacterSubSchema.virtual('character', {
|
|
131
|
+
// ref: 'Character', // The model to use
|
|
132
|
+
// localField: 'characterId', // Find in `Character` where `_id` matches `characterId`
|
|
133
|
+
// foreignField: '_id',
|
|
134
|
+
// justOne: true, // Since `characterId` is a single reference
|
|
135
|
+
// });
|
|
136
|
+
|
|
137
|
+
export const Profile = mongo.createModel<Types.ProfileDocument>(
|
|
138
|
+
'Profile',
|
|
139
|
+
{
|
|
140
|
+
accountId: { type: mongo.Schema.Types.ObjectId, ref: 'Account', required: true },
|
|
141
|
+
points: { type: Number, default: 0 },
|
|
142
|
+
// coins: { type: Number, default: 0 },
|
|
143
|
+
telegramUserId: { type: Number },
|
|
144
|
+
interactions: { type: Number, default: 0 },
|
|
145
|
+
activityRating: { type: Number, default: 0 },
|
|
146
|
+
address: { type: String, maxlength: 100 },
|
|
147
|
+
avatar: { type: String, maxlength: 100 },
|
|
148
|
+
roleId: { type: mongo.Schema.Types.ObjectId, ref: 'Role' },
|
|
149
|
+
privateKey: { type: String, maxlength: 300 },
|
|
150
|
+
signature: { type: String, maxlength: 200 },
|
|
151
|
+
chainId: { type: mongo.Schema.Types.ObjectId, ref: 'Chain' },
|
|
152
|
+
teamId: { type: mongo.Schema.Types.ObjectId, ref: 'Team' },
|
|
153
|
+
characterId: { type: mongo.Schema.Types.ObjectId, ref: 'Character' },
|
|
154
|
+
partyId: { type: mongo.Schema.Types.ObjectId, ref: 'Party' },
|
|
155
|
+
isBanned: { type: Boolean },
|
|
156
|
+
banExpireDate: { type: Date },
|
|
157
|
+
banReason: { type: String },
|
|
158
|
+
bio: { type: String },
|
|
159
|
+
banner: { type: String },
|
|
160
|
+
mode: { type: String, default: 'gamer' },
|
|
161
|
+
friends: [
|
|
162
|
+
{
|
|
163
|
+
profileId: { type: mongo.Schema.Types.ObjectId, ref: 'Profile', required: true },
|
|
164
|
+
meta: { type: mongo.Schema.Types.Mixed, default: {} },
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
badges: [
|
|
168
|
+
{
|
|
169
|
+
badgeId: { type: mongo.Schema.Types.ObjectId, ref: 'Badge', required: true },
|
|
170
|
+
meta: { type: mongo.Schema.Types.Mixed, default: {} },
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
settings: SettingsSchema,
|
|
174
|
+
stats: StatsSchema,
|
|
175
|
+
achievements: [
|
|
176
|
+
{
|
|
177
|
+
achievementId: { type: mongo.Schema.Types.ObjectId, ref: 'Achievement', required: true },
|
|
178
|
+
meta: { type: mongo.Schema.Types.Mixed, default: {} },
|
|
179
|
+
current: { type: Number, default: 0 },
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
virtuals: [
|
|
185
|
+
...addTagVirtuals('Profile'),
|
|
186
|
+
...addApplicationVirtual(),
|
|
187
|
+
{
|
|
188
|
+
name: 'character',
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: 'characters',
|
|
192
|
+
ref: 'Character',
|
|
193
|
+
localField: '_id',
|
|
194
|
+
foreignField: 'ownerId',
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: 'chain',
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
name: 'role',
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: 'account',
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
name: 'team',
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
indexes: [
|
|
210
|
+
{ applicationId: 1, telegramUserId: 1, unique: true },
|
|
211
|
+
{ applicationId: 1, accountId: 1, name: 1, unique: true },
|
|
212
|
+
],
|
|
213
|
+
}
|
|
214
|
+
);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z as zod } from 'zod';
|
|
2
|
+
import { initTRPC, inferRouterInputs } from '@trpc/server';
|
|
3
|
+
import { customErrorFormatter, hasRole } from '../../util/rpc';
|
|
4
|
+
import type { RouterContext } from '../../types';
|
|
5
|
+
import { Profile } from './profile.schema';
|
|
6
|
+
import { Query, getQueryInput, getQueryOutput, inferRouterOutputs } from '../../schema';
|
|
7
|
+
|
|
8
|
+
export const z = zod;
|
|
9
|
+
export const t = initTRPC.context<RouterContext>().create();
|
|
10
|
+
export const router = t.router;
|
|
11
|
+
export const procedure = t.procedure;
|
|
12
|
+
|
|
13
|
+
export const createRouter = () =>
|
|
14
|
+
router({
|
|
15
|
+
setProfileMode: procedure
|
|
16
|
+
.use(hasRole('user', t))
|
|
17
|
+
.use(customErrorFormatter(t))
|
|
18
|
+
.input(z.string())
|
|
19
|
+
.mutation(({ input, ctx }) => (ctx.app.service.Profile.setProfileMode as any)(input, ctx)),
|
|
20
|
+
|
|
21
|
+
// Profile endpoints
|
|
22
|
+
me: procedure
|
|
23
|
+
.use(hasRole('user', t))
|
|
24
|
+
.use(customErrorFormatter(t))
|
|
25
|
+
// .output(Profile.partial())
|
|
26
|
+
.query(({ input, ctx }) => (ctx.app.service.Profile.me as any)(input, ctx)),
|
|
27
|
+
|
|
28
|
+
// Profile endpoints
|
|
29
|
+
getProfile: procedure
|
|
30
|
+
.use(hasRole('guest', t))
|
|
31
|
+
.use(customErrorFormatter(t))
|
|
32
|
+
.input(getQueryInput(Profile))
|
|
33
|
+
// .output(Profile.partial())
|
|
34
|
+
.query(({ input, ctx }) => (ctx.app.service.Profile.getProfile as any)(input, ctx)),
|
|
35
|
+
|
|
36
|
+
getProfiles: procedure
|
|
37
|
+
.use(hasRole('guest', t))
|
|
38
|
+
.use(customErrorFormatter(t))
|
|
39
|
+
.input(getQueryInput(Profile))
|
|
40
|
+
.output(z.array(Profile))
|
|
41
|
+
.query(({ input, ctx }) => (ctx.app.service.Profile.getProfiles as any)(input, ctx)),
|
|
42
|
+
|
|
43
|
+
createProfile: procedure
|
|
44
|
+
.use(hasRole('user', t))
|
|
45
|
+
.use(customErrorFormatter(t))
|
|
46
|
+
.input(getQueryInput(Profile))
|
|
47
|
+
.output(Profile.partial())
|
|
48
|
+
.mutation(({ input, ctx }) => (ctx.app.service.Profile.createProfile as any)(input, ctx)),
|
|
49
|
+
|
|
50
|
+
updateProfile: procedure
|
|
51
|
+
.use(hasRole('user', t))
|
|
52
|
+
.use(customErrorFormatter(t))
|
|
53
|
+
.input(getQueryInput(Profile))
|
|
54
|
+
.output(Profile.partial())
|
|
55
|
+
.mutation(({ input, ctx }) => (ctx.app.service.Profile.updateProfile as any)(input, ctx)),
|
|
56
|
+
|
|
57
|
+
getProfileStats: procedure
|
|
58
|
+
.use(hasRole('guest', t))
|
|
59
|
+
.use(customErrorFormatter(t))
|
|
60
|
+
.input(z.object({ query: Query }))
|
|
61
|
+
.query(({ input, ctx }) => (ctx.app.service.Profile.getProfileStats as any)(input, ctx)),
|
|
62
|
+
|
|
63
|
+
updateProfileSettings: procedure
|
|
64
|
+
.use(hasRole('user', t))
|
|
65
|
+
.use(customErrorFormatter(t))
|
|
66
|
+
.input(z.object({ query: Query, settings: Profile.shape.settings }))
|
|
67
|
+
.mutation(({ input, ctx }) => (ctx.app.service.Profile.updateProfileSettings as any)(input, ctx)),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
export type Router = ReturnType<typeof createRouter>;
|
|
71
|
+
export type RouterInput = inferRouterInputs<Router>;
|
|
72
|
+
export type RouterOutput = inferRouterOutputs<Router>;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// profile.schema.ts
|
|
2
|
+
//
|
|
3
|
+
import { z, ObjectId, Entity } from '../../schema';
|
|
4
|
+
import { Character } from '../character/character.schema';
|
|
5
|
+
import { Achievement, Badge } from '../core/core.schema';
|
|
6
|
+
|
|
7
|
+
const RankingStatSchema = z.object({
|
|
8
|
+
total: z.number(),
|
|
9
|
+
position: z.number(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
// Define the Ranking schema
|
|
13
|
+
const RankingSchema = z.object({
|
|
14
|
+
orbs: RankingStatSchema,
|
|
15
|
+
wins: RankingStatSchema,
|
|
16
|
+
kills: RankingStatSchema,
|
|
17
|
+
deaths: RankingStatSchema,
|
|
18
|
+
points: RankingStatSchema,
|
|
19
|
+
rounds: RankingStatSchema,
|
|
20
|
+
evolves: RankingStatSchema,
|
|
21
|
+
rewards: RankingStatSchema,
|
|
22
|
+
powerups: RankingStatSchema,
|
|
23
|
+
revenges: RankingStatSchema,
|
|
24
|
+
winRatio: RankingStatSchema,
|
|
25
|
+
timeSpent: RankingStatSchema,
|
|
26
|
+
averageLatency: RankingStatSchema,
|
|
27
|
+
killDeathRatio: RankingStatSchema,
|
|
28
|
+
roundPointRatio: RankingStatSchema,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const ServerDataSchema = z.object({
|
|
32
|
+
orbs: z.number().optional(),
|
|
33
|
+
wins: z.number().optional(),
|
|
34
|
+
kills: z.number().optional(),
|
|
35
|
+
deaths: z.number().optional(),
|
|
36
|
+
points: z.number().optional(),
|
|
37
|
+
rounds: z.number().optional(),
|
|
38
|
+
evolves: z.number().optional(),
|
|
39
|
+
ranking: RankingSchema.optional(),
|
|
40
|
+
rewards: z.number().optional(),
|
|
41
|
+
earnings: z.number().optional(),
|
|
42
|
+
powerups: z.number().optional(),
|
|
43
|
+
revenges: z.number().optional(),
|
|
44
|
+
winRatio: z.number().optional(),
|
|
45
|
+
timeSpent: z.number().optional(),
|
|
46
|
+
winStreak: z.number().optional(),
|
|
47
|
+
averageLatency: z.number().nullable().optional(),
|
|
48
|
+
killDeathRatio: z.number().optional(),
|
|
49
|
+
roundPointRatio: z.number().optional(),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Profile schema for a user on a digital game platform
|
|
53
|
+
export const Profile = Entity.merge(
|
|
54
|
+
z.object({
|
|
55
|
+
accountId: ObjectId.optional(), // TODO; fix?
|
|
56
|
+
partyId: ObjectId.optional(),
|
|
57
|
+
points: z.number().optional(),
|
|
58
|
+
// currency: z.number().optional(),
|
|
59
|
+
telegramUserId: z.number().optional(),
|
|
60
|
+
interactions: z.number().default(0),
|
|
61
|
+
activityRating: z.number().default(0),
|
|
62
|
+
address: z.string().max(100).optional(),
|
|
63
|
+
avatar: z.string().max(100).optional(),
|
|
64
|
+
roleId: ObjectId.optional(),
|
|
65
|
+
privateKey: z.string().max(300).optional(),
|
|
66
|
+
signature: z.string().max(200).optional(),
|
|
67
|
+
chainId: ObjectId.optional(),
|
|
68
|
+
teamId: ObjectId.optional(),
|
|
69
|
+
characterId: ObjectId.optional(),
|
|
70
|
+
isBanned: z.boolean().optional(),
|
|
71
|
+
banExpireDate: z.date().optional(),
|
|
72
|
+
banReason: z.string().optional(),
|
|
73
|
+
mode: z.string().default('gamer').optional(),
|
|
74
|
+
|
|
75
|
+
bio: z.string().optional(),
|
|
76
|
+
banner: z.string().url().optional(), // URL to the user's banner image
|
|
77
|
+
friends: z
|
|
78
|
+
.array(
|
|
79
|
+
z.object({
|
|
80
|
+
friend: z.lazy(() => Profile),
|
|
81
|
+
meta: z.any().optional(),
|
|
82
|
+
})
|
|
83
|
+
)
|
|
84
|
+
.optional(),
|
|
85
|
+
achievements: z
|
|
86
|
+
.array(
|
|
87
|
+
z.object({
|
|
88
|
+
achievementId: ObjectId,
|
|
89
|
+
meta: z.any().optional(),
|
|
90
|
+
current: z.number().default(0),
|
|
91
|
+
})
|
|
92
|
+
)
|
|
93
|
+
.optional(),
|
|
94
|
+
badges: z
|
|
95
|
+
.array(
|
|
96
|
+
z.object({
|
|
97
|
+
badgeId: ObjectId,
|
|
98
|
+
meta: z.any().optional(),
|
|
99
|
+
})
|
|
100
|
+
)
|
|
101
|
+
.optional(),
|
|
102
|
+
character: Character.optional(),
|
|
103
|
+
characters: z.array(ObjectId.optional()).optional(),
|
|
104
|
+
settings: z
|
|
105
|
+
.object({
|
|
106
|
+
warp: z.any().default({}),
|
|
107
|
+
designer: z.any().default({}),
|
|
108
|
+
privacy: z.enum(['public', 'private', 'friends-only']).default('public'),
|
|
109
|
+
notifications: z.boolean().default(true),
|
|
110
|
+
})
|
|
111
|
+
.optional(),
|
|
112
|
+
stats: z
|
|
113
|
+
.object({
|
|
114
|
+
gamesOwned: z.number().int().nonnegative().default(0),
|
|
115
|
+
playedMinutes: z.number().nonnegative().default(0), // Total playtime in hours
|
|
116
|
+
leveledUpCount: z.number().int().nonnegative().default(0),
|
|
117
|
+
xpEarnedCount: z.number().int().nonnegative().default(0),
|
|
118
|
+
craftedItemCount: z.number().int().nonnegative().default(0),
|
|
119
|
+
equippedItemCount: z.number().int().nonnegative().default(0),
|
|
120
|
+
transferredInCount: z.number().int().nonnegative().default(0),
|
|
121
|
+
transferredOutCount: z.number().int().nonnegative().default(0),
|
|
122
|
+
marketTradeSoldCount: z.number().int().nonnegative().default(0),
|
|
123
|
+
marketTradeListedCount: z.number().int().nonnegative().default(0),
|
|
124
|
+
evolution: z
|
|
125
|
+
.object({
|
|
126
|
+
hashes: z.array(z.string()).default([]),
|
|
127
|
+
overall: z
|
|
128
|
+
.object({
|
|
129
|
+
orbs: z.number().optional(),
|
|
130
|
+
wins: z.number().optional(),
|
|
131
|
+
kills: z.number().optional(),
|
|
132
|
+
deaths: z.number().optional(),
|
|
133
|
+
points: z.number().optional(),
|
|
134
|
+
rounds: z.number().optional(),
|
|
135
|
+
evolves: z.number().optional(),
|
|
136
|
+
ranking: RankingSchema.optional(),
|
|
137
|
+
rewards: z.number().optional(),
|
|
138
|
+
earnings: z.number().optional(),
|
|
139
|
+
powerups: z.number().optional(),
|
|
140
|
+
revenges: z.number().optional(),
|
|
141
|
+
winRatio: z.number().optional(),
|
|
142
|
+
timeSpent: z.number().optional(),
|
|
143
|
+
winStreak: z.number().optional(),
|
|
144
|
+
averageLatency: z.number().optional().nullable(),
|
|
145
|
+
killDeathRatio: z.number().optional(),
|
|
146
|
+
roundPointRatio: z.number().optional(),
|
|
147
|
+
})
|
|
148
|
+
.default({}),
|
|
149
|
+
servers: z.record(ServerDataSchema).optional(),
|
|
150
|
+
lastUpdated: z.number().optional(),
|
|
151
|
+
})
|
|
152
|
+
.optional(),
|
|
153
|
+
})
|
|
154
|
+
.optional(),
|
|
155
|
+
})
|
|
156
|
+
);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// profile.types.ts
|
|
2
|
+
//
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import * as schema from './profile.schema';
|
|
5
|
+
import { Document, Model } from '../../util/mongo';
|
|
6
|
+
import type { RouterContext } from '../../types';
|
|
7
|
+
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
|
|
8
|
+
import type { Router } from './profile.router';
|
|
9
|
+
|
|
10
|
+
export type * from './profile.router';
|
|
11
|
+
export type * from './profile.service';
|
|
12
|
+
export type { RouterContext };
|
|
13
|
+
|
|
14
|
+
export type Profile = z.infer<typeof schema.Profile>;
|
|
15
|
+
export type ProfileDocument = Profile & Document;
|
|
16
|
+
|
|
17
|
+
export type Mappings = {
|
|
18
|
+
Profile: Model<ProfileDocument>;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type RouterInput = inferRouterInputs<Router>;
|
|
22
|
+
export type RouterOutput = inferRouterOutputs<Router>;
|