@arken/node 1.5.0 → 1.5.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/build/modules/character/character.service.js.map +1 -1
- package/build/modules/chat/chat.service.js.map +1 -1
- package/build/modules/core/core.models.js.map +1 -1
- package/build/modules/core/core.service.js.map +1 -1
- package/build/modules/profile/profile.service.js.map +1 -1
- package/build/package.json +2 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types.d.ts +1 -0
- package/build/types.js +1 -0
- package/build/types.js.map +1 -1
- package/build/util/mongo.js.map +1 -1
- package/db.ts +76 -1
- package/index.ts +351 -18
- package/{util/mongo.ts → mongo.ts} +2 -0
- package/package.json +3 -3
- package/tsconfig.json +33 -2
- package/types.ts +2 -0
- package/util.ts +1 -0
- package/modules/area/area.models.ts +0 -15
- package/modules/area/area.router.ts +0 -74
- package/modules/area/area.schema.ts +0 -22
- package/modules/area/area.service.ts +0 -124
- package/modules/area/area.types.ts +0 -26
- package/modules/area/index.ts +0 -5
- package/modules/asset/asset.models.ts +0 -59
- package/modules/asset/asset.router.ts +0 -55
- package/modules/asset/asset.schema.ts +0 -27
- package/modules/asset/asset.service.ts +0 -85
- package/modules/asset/asset.types.ts +0 -22
- package/modules/asset/index.ts +0 -5
- package/modules/chain/chain.models.ts +0 -50
- package/modules/chain/chain.router.ts +0 -104
- package/modules/chain/chain.schema.ts +0 -52
- package/modules/chain/chain.service.ts +0 -167
- package/modules/chain/chain.types.ts +0 -24
- package/modules/chain/index.ts +0 -5
- package/modules/character/character.models.ts +0 -174
- package/modules/character/character.router.ts +0 -314
- package/modules/character/character.schema.ts +0 -147
- package/modules/character/character.service.ts +0 -875
- package/modules/character/character.types.ts +0 -64
- package/modules/character/index.ts +0 -5
- package/modules/chat/chat.models.ts +0 -43
- package/modules/chat/chat.router.ts +0 -67
- package/modules/chat/chat.schema.ts +0 -36
- package/modules/chat/chat.service.ts +0 -120
- package/modules/chat/chat.types.ts +0 -20
- package/modules/chat/index.ts +0 -5
- package/modules/collection/collection.models.ts +0 -76
- package/modules/collection/collection.router.ts +0 -91
- package/modules/collection/collection.schema.ts +0 -90
- package/modules/collection/collection.service.ts +0 -192
- package/modules/collection/collection.types.ts +0 -36
- package/modules/collection/index.ts +0 -5
- package/modules/core/core.models.ts +0 -1379
- package/modules/core/core.router.ts +0 -1781
- package/modules/core/core.schema.ts +0 -847
- package/modules/core/core.service.ts +0 -2822
- package/modules/core/core.types.ts +0 -340
- package/modules/core/index.ts +0 -5
- package/modules/core/mail/applyPatchesOrMail.ts +0 -568
- package/modules/core/mail/mailClaimablePatchesBatch.ts +0 -381
- package/modules/game/game.models.ts +0 -53
- package/modules/game/game.router.ts +0 -110
- package/modules/game/game.schema.ts +0 -23
- package/modules/game/game.service.ts +0 -143
- package/modules/game/game.types.ts +0 -28
- package/modules/game/index.ts +0 -5
- package/modules/interface/index.ts +0 -5
- package/modules/interface/interface.canonicalize.ts +0 -279
- package/modules/interface/interface.models.ts +0 -40
- package/modules/interface/interface.router.ts +0 -175
- package/modules/interface/interface.schema.ts +0 -59
- package/modules/interface/interface.service.ts +0 -356
- package/modules/interface/interface.types.ts +0 -25
- package/modules/item/index.ts +0 -5
- package/modules/item/item.models.ts +0 -124
- package/modules/item/item.router.ts +0 -103
- package/modules/item/item.schema.ts +0 -120
- package/modules/item/item.service.ts +0 -167
- package/modules/item/item.types.ts +0 -74
- package/modules/job/index.ts +0 -5
- package/modules/job/job.models.ts +0 -14
- package/modules/job/job.router.ts +0 -44
- package/modules/job/job.schema.ts +0 -9
- package/modules/job/job.service.ts +0 -243
- package/modules/job/job.types.ts +0 -23
- package/modules/market/index.ts +0 -5
- package/modules/market/market.models.ts +0 -113
- package/modules/market/market.router.ts +0 -73
- package/modules/market/market.schema.ts +0 -140
- package/modules/market/market.service.ts +0 -122
- package/modules/market/market.types.ts +0 -56
- package/modules/product/index.ts +0 -5
- package/modules/product/product.models.ts +0 -166
- package/modules/product/product.router.ts +0 -93
- package/modules/product/product.schema.ts +0 -149
- package/modules/product/product.service.ts +0 -160
- package/modules/product/product.types.ts +0 -33
- package/modules/profile/index.ts +0 -5
- package/modules/profile/profile.models.ts +0 -214
- package/modules/profile/profile.router.ts +0 -72
- package/modules/profile/profile.schema.ts +0 -156
- package/modules/profile/profile.service.ts +0 -147
- package/modules/profile/profile.types.ts +0 -22
- package/modules/raffle/index.ts +0 -5
- package/modules/raffle/raffle.models.ts +0 -44
- package/modules/raffle/raffle.router.ts +0 -90
- package/modules/raffle/raffle.schema.ts +0 -32
- package/modules/raffle/raffle.service.ts +0 -167
- package/modules/raffle/raffle.types.ts +0 -30
- package/modules/skill/index.ts +0 -5
- package/modules/skill/skill.models.ts +0 -16
- package/modules/skill/skill.router.ts +0 -201
- package/modules/skill/skill.schema.ts +0 -40
- package/modules/skill/skill.service.ts +0 -390
- package/modules/skill/skill.types.ts +0 -33
- package/modules/video/index.ts +0 -5
- package/modules/video/video.models.ts +0 -25
- package/modules/video/video.router.ts +0 -143
- package/modules/video/video.schema.ts +0 -46
- package/modules/video/video.service.ts +0 -274
- package/modules/video/video.types.ts +0 -33
- package/util/db/index.ts +0 -7
- package/util/db/isPostgresError.ts +0 -9
- package/util/db/isUniqueConstraintViolation.ts +0 -3
- package/util/db.ts +0 -62
- package/util/index.ts +0 -351
- /package/{util/api.ts → api.ts} +0 -0
- /package/{util/array.ts → array.ts} +0 -0
- /package/{util/browser.ts → browser.ts} +0 -0
- /package/{util/codebase.ts → codebase.ts} +0 -0
- /package/{util/config.ts → config.ts} +0 -0
- /package/{util/decoder.test.ts → decoder.test.ts} +0 -0
- /package/{util/decoder.ts → decoder.ts} +0 -0
- /package/{util/format.ts → format.ts} +0 -0
- /package/{util/guid.ts → guid.ts} +0 -0
- /package/{util/json.ts → json.ts} +0 -0
- /package/{util/log.ts → log.ts} +0 -0
- /package/{util/math.ts → math.ts} +0 -0
- /package/{util/merkle.ts → merkle.ts} +0 -0
- /package/{util/number.ts → number.ts} +0 -0
- /package/{util/object.ts → object.ts} +0 -0
- /package/{util/otp.ts → otp.ts} +0 -0
- /package/{util/physics.ts → physics.ts} +0 -0
- /package/{util/process.ts → process.ts} +0 -0
- /package/{util/rpc.ts → rpc.ts} +0 -0
- /package/{util/seer.ts → seer.ts} +0 -0
- /package/{util/string.ts → string.ts} +0 -0
- /package/{util/text.ts → text.ts} +0 -0
- /package/{util/time → time}/date.ts +0 -0
- /package/{util/time → time}/fancyTimeFormat.ts +0 -0
- /package/{util/time → time}/index.ts +0 -0
- /package/{util/time → time}/now.ts +0 -0
- /package/{util/types → types}/mongo.d.ts +0 -0
- /package/{util/web3 → web3}/httpProvider.ts +0 -0
- /package/{util/web3.ts → web3.ts} +0 -0
- /package/{util/websocket.ts → websocket.ts} +0 -0
- /package/{util/zk.ts → zk.ts} +0 -0
- /package/{util/zod.ts → zod.ts} +0 -0
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import type { RouterContext, RouterInput, RouterOutput, Era, Game, GameStat } from './game.types';
|
|
2
|
-
import { getFilter } from '../../util/api';
|
|
3
|
-
import { ARXError } from '../../util/rpc';
|
|
4
|
-
|
|
5
|
-
export class Service {
|
|
6
|
-
// Game Methods
|
|
7
|
-
async getGame(input: RouterInput['getGame'], ctx: RouterContext): Promise<RouterOutput['getGame']> {
|
|
8
|
-
if (!input) throw new ARXError('NO_INPUT');
|
|
9
|
-
console.log('Core.Service.getGame', input, getFilter(input));
|
|
10
|
-
|
|
11
|
-
const game = await ctx.app.model.Game.findOne(getFilter(input)).populate('stat').exec();
|
|
12
|
-
|
|
13
|
-
if (!game) throw new Error('Game not found');
|
|
14
|
-
|
|
15
|
-
return game as Game;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async getGames(input: RouterInput['getGames'], ctx: RouterContext): Promise<RouterOutput['getGames']> {
|
|
19
|
-
console.log('Core.Service.getGames', input);
|
|
20
|
-
|
|
21
|
-
const filter = getFilter(input);
|
|
22
|
-
|
|
23
|
-
filter.status = 'Active';
|
|
24
|
-
|
|
25
|
-
const games = await ctx.app.model.Game.find(filter).populate('stat').exec();
|
|
26
|
-
|
|
27
|
-
return games as Game[];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async createGame(input: RouterInput['createGame'], ctx: RouterContext): Promise<RouterOutput['createGame']> {
|
|
31
|
-
if (!input) throw new ARXError('NO_INPUT');
|
|
32
|
-
console.log('Core.Service.createGame', input);
|
|
33
|
-
|
|
34
|
-
const game = await ctx.app.model.Game.create(input);
|
|
35
|
-
return game as Game;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async updateGame(input: RouterInput['updateGame'], ctx: RouterContext): Promise<RouterOutput['updateGame']> {
|
|
39
|
-
if (!input) throw new ARXError('NO_INPUT');
|
|
40
|
-
console.log('Core.Service.updateGame', input);
|
|
41
|
-
|
|
42
|
-
const filter = getFilter(input);
|
|
43
|
-
const updatedGame = await ctx.app.model.Game.findByIdAndUpdate(filter.id, { new: true }).lean().exec();
|
|
44
|
-
if (!updatedGame) throw new Error('Game update failed');
|
|
45
|
-
|
|
46
|
-
return updatedGame as Game;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// GameStat Methods
|
|
50
|
-
async getGameStat(input: RouterInput['getGameStat'], ctx: RouterContext): Promise<RouterOutput['getGameStat']> {
|
|
51
|
-
if (!input) throw new ARXError('NO_INPUT');
|
|
52
|
-
console.log('Core.Service.getGameStat', input);
|
|
53
|
-
|
|
54
|
-
const gameStat = await ctx.app.model.GameStat.findOne(getFilter(input)).exec();
|
|
55
|
-
if (!gameStat) throw new Error('GameStat not found');
|
|
56
|
-
|
|
57
|
-
return gameStat as GameStat;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async getGameStats(input: RouterInput['getGameStats'], ctx: RouterContext): Promise<RouterOutput['getGameStats']> {
|
|
61
|
-
console.log('Core.Service.getGameStats', input);
|
|
62
|
-
|
|
63
|
-
const filter = getFilter(input);
|
|
64
|
-
|
|
65
|
-
filter.status = 'Active';
|
|
66
|
-
|
|
67
|
-
const gameStats = await ctx.app.model.GameStat.find(filter).exec();
|
|
68
|
-
|
|
69
|
-
return gameStats as GameStat[];
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async createGameStat(
|
|
73
|
-
input: RouterInput['createGameStat'],
|
|
74
|
-
ctx: RouterContext
|
|
75
|
-
): Promise<RouterOutput['createGameStat']> {
|
|
76
|
-
if (!input) throw new ARXError('NO_INPUT');
|
|
77
|
-
console.log('Core.Service.createGameStat', input);
|
|
78
|
-
|
|
79
|
-
const gameStat = await ctx.app.model.GameStat.create(input);
|
|
80
|
-
return gameStat as GameStat;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async updateGameStat(
|
|
84
|
-
input: RouterInput['updateGameStat'],
|
|
85
|
-
ctx: RouterContext
|
|
86
|
-
): Promise<RouterOutput['updateGameStat']> {
|
|
87
|
-
if (!input) throw new ARXError('NO_INPUT');
|
|
88
|
-
console.log('Core.Service.updateGameStat', input);
|
|
89
|
-
|
|
90
|
-
const gameStat = await ctx.app.model.GameStat.findByIdAndUpdate(input.where.id.equals, { new: true }).lean().exec();
|
|
91
|
-
if (!gameStat) throw new Error('GameStat update failed');
|
|
92
|
-
|
|
93
|
-
return gameStat as GameStat;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Era Methods
|
|
97
|
-
async getEra(input: RouterInput['getEra'], ctx: RouterContext): Promise<RouterOutput['getEra']> {
|
|
98
|
-
if (!input) throw new ARXError('NO_INPUT');
|
|
99
|
-
console.log('Core.Service.getEra', input);
|
|
100
|
-
|
|
101
|
-
const era = await ctx.app.model.Era.findOne(getFilter(input)).exec();
|
|
102
|
-
if (!era) throw new Error('Era not found');
|
|
103
|
-
|
|
104
|
-
return era as Era;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async getEras(input: RouterInput['getEras'], ctx: RouterContext): Promise<RouterOutput['getEras']> {
|
|
108
|
-
const filter = getFilter(input);
|
|
109
|
-
const eras = await ctx.app.model.Era.find(filter).exec();
|
|
110
|
-
|
|
111
|
-
return eras as Era[];
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async createEra(input: RouterInput['createEra'], ctx: RouterContext): Promise<RouterOutput['createEra']> {
|
|
115
|
-
if (!input) throw new Error('Input should not be void');
|
|
116
|
-
console.log('Game.Service.createEra', input);
|
|
117
|
-
|
|
118
|
-
const era = await ctx.app.model.Era.create(input.data);
|
|
119
|
-
return era as Era;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async updateEra(input: RouterInput['updateEra'], ctx: RouterContext): Promise<RouterOutput['updateEra']> {
|
|
123
|
-
if (!input) throw new Error('Input should not be void');
|
|
124
|
-
console.log('Game.Service.updateEra', input, input.data);
|
|
125
|
-
|
|
126
|
-
const filter = getFilter(input);
|
|
127
|
-
const updatedEra = await ctx.app.model.Era.findOneAndUpdate(filter, input.data, { new: true }).exec();
|
|
128
|
-
if (!updatedEra) throw new Error('Era update failed');
|
|
129
|
-
|
|
130
|
-
return updatedEra as Era;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
async deleteEra(input: RouterInput['deleteEra'], ctx: RouterContext): Promise<RouterOutput['deleteEra']> {
|
|
134
|
-
if (!input) throw new Error('Input should not be void');
|
|
135
|
-
console.log('Game.Service.deleteEra', input);
|
|
136
|
-
|
|
137
|
-
const filter = getFilter(input);
|
|
138
|
-
const deletedEra = await ctx.app.model.Era.findOneAndDelete(filter).exec();
|
|
139
|
-
if (!deletedEra) throw new Error('Era not found');
|
|
140
|
-
|
|
141
|
-
return deletedEra as Era;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { Model, Document } from '../../util/mongo';
|
|
3
|
-
import * as schema from './game.schema';
|
|
4
|
-
|
|
5
|
-
export type * from './game.router';
|
|
6
|
-
export type * from './game.service';
|
|
7
|
-
export type { RouterContext } from '../../types';
|
|
8
|
-
|
|
9
|
-
// Define types based on the schema
|
|
10
|
-
export type Game = z.infer<typeof schema.Game>;
|
|
11
|
-
export type GameDocument = Game & Document;
|
|
12
|
-
|
|
13
|
-
export type GameStat = z.infer<typeof schema.GameStat>;
|
|
14
|
-
export type GameStatDocument = GameStat & Document;
|
|
15
|
-
|
|
16
|
-
export type GameRound = z.infer<typeof schema.GameRound>;
|
|
17
|
-
export type GameRoundDocument = GameRound & Document;
|
|
18
|
-
|
|
19
|
-
export type Era = z.infer<typeof schema.Era>;
|
|
20
|
-
export type EraDocument = Era & Document;
|
|
21
|
-
|
|
22
|
-
// Mappings for MongoDB models
|
|
23
|
-
export type Mappings = {
|
|
24
|
-
Game: Model<GameDocument>;
|
|
25
|
-
GameStat: Model<GameStatDocument>;
|
|
26
|
-
GameRound: Model<GameRoundDocument>;
|
|
27
|
-
Era: Model<EraDocument>;
|
|
28
|
-
};
|
package/modules/game/index.ts
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import get from 'lodash/get';
|
|
2
|
-
|
|
3
|
-
type AnyObj = Record<string, any>;
|
|
4
|
-
|
|
5
|
-
// --- same sugar compilation as web (keep it identical across runtimes) ---
|
|
6
|
-
function isObject(x: any) {
|
|
7
|
-
return !!x && typeof x === 'object' && !Array.isArray(x);
|
|
8
|
-
}
|
|
9
|
-
function isSugarExpr(x: any) {
|
|
10
|
-
return isObject(x) && '$' in x;
|
|
11
|
-
}
|
|
12
|
-
function isJsonLogicExpr(x: any) {
|
|
13
|
-
return isObject(x) && '$expr' in x;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function sugarArgToLogic(arg: any): any {
|
|
17
|
-
if (typeof arg === 'string' && arg.startsWith('$')) return { var: arg.slice(1) };
|
|
18
|
-
return arg;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function compileSugarToJsonLogic(expr: any): any {
|
|
22
|
-
if (!isSugarExpr(expr)) return expr;
|
|
23
|
-
|
|
24
|
-
const raw = expr.$;
|
|
25
|
-
if (!Array.isArray(raw) || raw.length === 0) return { $expr: raw };
|
|
26
|
-
|
|
27
|
-
const [op, ...rest] = raw;
|
|
28
|
-
const args = rest.map(sugarArgToLogic);
|
|
29
|
-
|
|
30
|
-
const map: Record<string, (a: any[]) => any> = {
|
|
31
|
-
var: (a) => ({ var: a[0] }),
|
|
32
|
-
not: (a) => ({ '!': [a[0]] }),
|
|
33
|
-
and: (a) => ({ and: a }),
|
|
34
|
-
or: (a) => ({ or: a }),
|
|
35
|
-
eq: (a) => ({ '==': [a[0], a[1]] }),
|
|
36
|
-
ne: (a) => ({ '!=': [a[0], a[1]] }),
|
|
37
|
-
gt: (a) => ({ '>': [a[0], a[1]] }),
|
|
38
|
-
gte: (a) => ({ '>=': [a[0], a[1]] }),
|
|
39
|
-
lt: (a) => ({ '<': [a[0], a[1]] }),
|
|
40
|
-
lte: (a) => ({ '<=': [a[0], a[1]] }),
|
|
41
|
-
cat: (a) => ({ cat: a }),
|
|
42
|
-
if: (a) => ({ if: a }),
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const fn = map[String(op)];
|
|
46
|
-
const compiled = fn ? fn(args) : { [String(op)]: args };
|
|
47
|
-
return { $expr: compiled };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// --- template-to-jsonlogic compiler (same logic as web) ---
|
|
51
|
-
function isTemplateString(s: any) {
|
|
52
|
-
return typeof s === 'string' && s.includes('{{') && s.includes('}}');
|
|
53
|
-
}
|
|
54
|
-
function isSingleMustacheWholeString(s: string) {
|
|
55
|
-
const t = s.trim();
|
|
56
|
-
return t.startsWith('{{') && t.endsWith('}}') && t.indexOf('{{') === 0 && t.lastIndexOf('}}') === t.length - 2;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function parseInlineArgs(raw: string): string[] {
|
|
60
|
-
const out: string[] = [];
|
|
61
|
-
let buf = '';
|
|
62
|
-
let depth = 0;
|
|
63
|
-
let quote: "'" | '"' | null = null;
|
|
64
|
-
|
|
65
|
-
const push = () => {
|
|
66
|
-
const s = buf.trim();
|
|
67
|
-
if (s) out.push(s);
|
|
68
|
-
buf = '';
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
for (let i = 0; i < raw.length; i++) {
|
|
72
|
-
const ch = raw[i];
|
|
73
|
-
|
|
74
|
-
if (quote) {
|
|
75
|
-
buf += ch;
|
|
76
|
-
if (ch === quote && raw[i - 1] !== '\\') quote = null;
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (ch === '"' || ch === "'") {
|
|
81
|
-
quote = ch as any;
|
|
82
|
-
buf += ch;
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (ch === '(') depth++;
|
|
87
|
-
if (ch === ')') depth = Math.max(0, depth - 1);
|
|
88
|
-
|
|
89
|
-
if (ch === ',' && depth === 0) {
|
|
90
|
-
push();
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
buf += ch;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
push();
|
|
98
|
-
return out;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function parseLiteralOrVar(token: string): any {
|
|
102
|
-
const t = token.trim();
|
|
103
|
-
|
|
104
|
-
if ((t.startsWith('"') && t.endsWith('"')) || (t.startsWith("'") && t.endsWith("'"))) {
|
|
105
|
-
try {
|
|
106
|
-
if (t.startsWith("'")) return JSON.parse('"' + t.slice(1, -1).replace(/"/g, '\\"') + '"');
|
|
107
|
-
return JSON.parse(t);
|
|
108
|
-
} catch {
|
|
109
|
-
return t.slice(1, -1);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (t === 'true') return true;
|
|
114
|
-
if (t === 'false') return false;
|
|
115
|
-
if (t === 'null') return null;
|
|
116
|
-
|
|
117
|
-
if (/^-?\d+(\.\d+)?$/.test(t)) return Number(t);
|
|
118
|
-
|
|
119
|
-
return { var: t };
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function compileInlineMustacheToJsonLogic(expr: string): any {
|
|
123
|
-
const s = expr.trim();
|
|
124
|
-
|
|
125
|
-
if (/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\[[0-9]+\])*$/.test(s)) {
|
|
126
|
-
return { var: s };
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const m = /^([A-Za-z_$][\w$]*)\(([\s\S]*)\)$/.exec(s);
|
|
130
|
-
if (!m) return { var: s };
|
|
131
|
-
|
|
132
|
-
const fn = m[1];
|
|
133
|
-
const argRaw = m[2] ?? '';
|
|
134
|
-
const argTokens = parseInlineArgs(argRaw);
|
|
135
|
-
const args = argTokens.map(parseLiteralOrVar);
|
|
136
|
-
|
|
137
|
-
const map: Record<string, any> = {
|
|
138
|
-
not: (a: any[]) => ({ '!': [a[0]] }),
|
|
139
|
-
and: (a: any[]) => ({ and: a }),
|
|
140
|
-
or: (a: any[]) => ({ or: a }),
|
|
141
|
-
|
|
142
|
-
eq: (a: any[]) => ({ '==': [a[0], a[1]] }),
|
|
143
|
-
ne: (a: any[]) => ({ '!=': [a[0], a[1]] }),
|
|
144
|
-
gt: (a: any[]) => ({ '>': [a[0], a[1]] }),
|
|
145
|
-
gte: (a: any[]) => ({ '>=': [a[0], a[1]] }),
|
|
146
|
-
lt: (a: any[]) => ({ '<': [a[0], a[1]] }),
|
|
147
|
-
lte: (a: any[]) => ({ '<=': [a[0], a[1]] }),
|
|
148
|
-
|
|
149
|
-
cat: (a: any[]) => ({ cat: a }),
|
|
150
|
-
if: (a: any[]) => ({ if: a }),
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const builder = map[fn];
|
|
154
|
-
if (builder) return builder(args);
|
|
155
|
-
|
|
156
|
-
return { [fn]: args };
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function compileInterpolatedStringToCat(s: string): any {
|
|
160
|
-
const parts: any[] = [];
|
|
161
|
-
let i = 0;
|
|
162
|
-
|
|
163
|
-
while (i < s.length) {
|
|
164
|
-
const start = s.indexOf('{{', i);
|
|
165
|
-
if (start === -1) {
|
|
166
|
-
const tail = s.slice(i);
|
|
167
|
-
if (tail) parts.push(tail);
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const head = s.slice(i, start);
|
|
172
|
-
if (head) parts.push(head);
|
|
173
|
-
|
|
174
|
-
const end = s.indexOf('}}', start + 2);
|
|
175
|
-
if (end === -1) {
|
|
176
|
-
parts.push(s.slice(start));
|
|
177
|
-
break;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const inner = s.slice(start + 2, end);
|
|
181
|
-
parts.push(compileInlineMustacheToJsonLogic(inner));
|
|
182
|
-
|
|
183
|
-
i = end + 2;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (parts.length === 1) return parts[0];
|
|
187
|
-
return { cat: parts };
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function compileTemplateStringToJsonLogicValue(input: string): any {
|
|
191
|
-
let out = String(input);
|
|
192
|
-
|
|
193
|
-
const ifRe = /{{#if\s+([^}]+)}}([\s\S]*?)({{else}}([\s\S]*?))?{{\/if}}/g;
|
|
194
|
-
|
|
195
|
-
for (let loop = 0; loop < 10; loop++) {
|
|
196
|
-
const prev = out;
|
|
197
|
-
out = out.replace(ifRe, (_m, condRaw, thenPart, _elseWhole, elsePart) => {
|
|
198
|
-
const cond = String(condRaw ?? '').trim();
|
|
199
|
-
const thenS = String(thenPart ?? '');
|
|
200
|
-
const elseS = String(elsePart ?? '');
|
|
201
|
-
return `__IF__(${cond})__THEN__(${thenS})__ELSE__(${elseS})__END__`;
|
|
202
|
-
});
|
|
203
|
-
if (out === prev) break;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const ifSentinelRe = /^__IF__\(([\s\S]*)\)__THEN__\(([\s\S]*)\)__ELSE__\(([\s\S]*)\)__END__$/;
|
|
207
|
-
const mm = ifSentinelRe.exec(out);
|
|
208
|
-
if (mm) {
|
|
209
|
-
const condExpr = compileInlineMustacheToJsonLogic(mm[1]);
|
|
210
|
-
const thenCompiled = compileTemplateStringToJsonLogicValue(mm[2]);
|
|
211
|
-
const elseCompiled = compileTemplateStringToJsonLogicValue(mm[3]);
|
|
212
|
-
return { if: [condExpr, thenCompiled, elseCompiled] };
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (isSingleMustacheWholeString(out) && !out.includes('{{#if')) {
|
|
216
|
-
const inner = out.trim().slice(2, -2);
|
|
217
|
-
return compileInlineMustacheToJsonLogic(inner);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (out.includes('{{')) {
|
|
221
|
-
return compileInterpolatedStringToCat(out);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
return out;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function compileTemplateStringToExpr(s: string) {
|
|
228
|
-
if (!isTemplateString(s)) return s;
|
|
229
|
-
const compiled = compileTemplateStringToJsonLogicValue(s);
|
|
230
|
-
if (compiled && typeof compiled === 'object') return { $expr: compiled };
|
|
231
|
-
return compiled;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// --- canonicalize: walk any JSON-ish tree and rewrite templates/sugar into $expr ---
|
|
235
|
-
export function canonicalizeInterfaceDoc(input: any): any {
|
|
236
|
-
const seen = new Map<any, any>();
|
|
237
|
-
|
|
238
|
-
const walk = (v: any): any => {
|
|
239
|
-
if (v === null || v === undefined) return v;
|
|
240
|
-
if (typeof v === 'number' || typeof v === 'boolean') return v;
|
|
241
|
-
|
|
242
|
-
// IMPORTANT: Seer canonicalization should NOT preserve functions (DB-safe only)
|
|
243
|
-
if (typeof v === 'function') return undefined;
|
|
244
|
-
|
|
245
|
-
if (typeof v === 'string') {
|
|
246
|
-
// forbid legacy JS formulas at the canonical layer
|
|
247
|
-
if (v.trim().startsWith('=')) {
|
|
248
|
-
// best practice: reject, but you can also keep as-is if you must
|
|
249
|
-
throw new Error('Canonical interface spec cannot contain legacy "=..." formulas.');
|
|
250
|
-
}
|
|
251
|
-
if (isTemplateString(v)) return walk(compileTemplateStringToExpr(v));
|
|
252
|
-
return v;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
if (Array.isArray(v)) return v.map(walk);
|
|
256
|
-
|
|
257
|
-
if (typeof v === 'object') {
|
|
258
|
-
if (seen.has(v)) return seen.get(v);
|
|
259
|
-
|
|
260
|
-
// sugar -> $expr
|
|
261
|
-
if (isSugarExpr(v)) return walk(compileSugarToJsonLogic(v));
|
|
262
|
-
|
|
263
|
-
// already $expr: canonicalize inside it too (deep)
|
|
264
|
-
if (isJsonLogicExpr(v)) {
|
|
265
|
-
const out = { $expr: walk((v as any).$expr) };
|
|
266
|
-
return out;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const out: AnyObj = {};
|
|
270
|
-
seen.set(v, out);
|
|
271
|
-
for (const [k, val] of Object.entries(v)) out[k] = walk(val);
|
|
272
|
-
return out;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
return v;
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
return walk(input);
|
|
279
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// arken/packages/node/modules/interface/interface.models.ts
|
|
2
|
-
//
|
|
3
|
-
import * as mongo from '../../util/mongo';
|
|
4
|
-
import type * as Types from './interface.types';
|
|
5
|
-
|
|
6
|
-
export const Interface = mongo.createModel<Types.InterfaceDocument>('Interface', {
|
|
7
|
-
key: { type: String, required: true },
|
|
8
|
-
submissions: [{ type: mongo.Schema.Types.ObjectId, ref: 'InterfaceSubmission' }],
|
|
9
|
-
groupId: { type: mongo.Schema.Types.ObjectId, ref: 'InterfaceGroup', required: true },
|
|
10
|
-
|
|
11
|
-
status: {
|
|
12
|
-
type: String,
|
|
13
|
-
default: 'Active',
|
|
14
|
-
enum: ['Paused', 'Pending', 'Active', 'Archived', 'Published', 'Draft'],
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
// ✅ NEW (typed-wrapper-safe): store as Mixed, validate via Zod on IO
|
|
18
|
-
inherits: { type: mongo.Schema.Types.Mixed, default: [] }, // string[]
|
|
19
|
-
variables: { type: mongo.Schema.Types.Mixed, default: {} }, // record
|
|
20
|
-
patches: { type: mongo.Schema.Types.Mixed, default: [] }, // patch[]
|
|
21
|
-
|
|
22
|
-
nodes: { type: mongo.Schema.Types.Mixed, default: [] },
|
|
23
|
-
version: { type: Number },
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
export const InterfaceGroup = mongo.createModel<Types.InterfaceGroupDocument>('InterfaceGroup', {});
|
|
27
|
-
|
|
28
|
-
export const InterfaceComponent = mongo.createModel<Types.InterfaceComponentDocument>('InterfaceComponent', {
|
|
29
|
-
value: { type: Object, default: {} },
|
|
30
|
-
type: { type: String },
|
|
31
|
-
hasAttachment: { type: Boolean },
|
|
32
|
-
hasValidation: { type: Boolean },
|
|
33
|
-
isDisabled: { type: Boolean },
|
|
34
|
-
isEditable: { type: Boolean },
|
|
35
|
-
isRequired: { type: Boolean },
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
export const InterfaceSubmission = mongo.createModel<Types.InterfaceSubmissionDocument>('InterfaceSubmission', {
|
|
39
|
-
interfaceId: { type: mongo.Schema.Types.ObjectId, ref: 'Interface' } as any,
|
|
40
|
-
});
|
|
@@ -1,175 +0,0 @@
|
|
|
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 { Interface, InterfaceGroup, InterfaceComponent } from './interface.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
|
-
// Interface Procedures
|
|
16
|
-
getInterface: procedure
|
|
17
|
-
.use(hasRole('guest', t))
|
|
18
|
-
.use(customErrorFormatter(t))
|
|
19
|
-
.input(getQueryInput(Interface))
|
|
20
|
-
.output(Interface)
|
|
21
|
-
.query(({ input, ctx }) => (ctx.app.service.Interface.getInterface as any)(input, ctx)),
|
|
22
|
-
|
|
23
|
-
createInterface: procedure
|
|
24
|
-
.use(hasRole('user', t))
|
|
25
|
-
.use(customErrorFormatter(t))
|
|
26
|
-
.input(getQueryInput(Interface))
|
|
27
|
-
.output(Interface.pick({ id: true, name: true }))
|
|
28
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.createInterface as any)(input, ctx)),
|
|
29
|
-
|
|
30
|
-
updateInterface: procedure
|
|
31
|
-
.use(hasRole('user', t))
|
|
32
|
-
.use(customErrorFormatter(t))
|
|
33
|
-
.input(getQueryInput(Interface))
|
|
34
|
-
.output(Interface.pick({ id: true }))
|
|
35
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.updateInterface as any)(input, ctx)),
|
|
36
|
-
|
|
37
|
-
deleteInterface: procedure
|
|
38
|
-
.use(hasRole('user', t))
|
|
39
|
-
.use(customErrorFormatter(t))
|
|
40
|
-
.input(getQueryInput(Interface))
|
|
41
|
-
// .output(Interface.pick({ id: true }))
|
|
42
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.deleteInterface as any)(input, ctx)),
|
|
43
|
-
|
|
44
|
-
getInterfaces: procedure
|
|
45
|
-
.use(hasRole('user', t))
|
|
46
|
-
.use(customErrorFormatter(t))
|
|
47
|
-
.input(getQueryInput(Interface))
|
|
48
|
-
.output(z.object({ items: z.array(Interface), total: z.number() }))
|
|
49
|
-
.query(({ input, ctx }) => (ctx.app.service.Interface.getInterfaces as any)(input, ctx)),
|
|
50
|
-
|
|
51
|
-
// getInterface: procedure
|
|
52
|
-
// .use(hasRole('guest', t))
|
|
53
|
-
// .use(customErrorFormatter(t))
|
|
54
|
-
// .input(getQueryInput(Interface))
|
|
55
|
-
// .output(Interface)
|
|
56
|
-
// .query(({ input, ctx }) => (ctx.app.service.Interface.getInterface as any)(input, ctx)),
|
|
57
|
-
|
|
58
|
-
// getInterfaces: procedure
|
|
59
|
-
// .use(hasRole('guest', t))
|
|
60
|
-
// .use(customErrorFormatter(t))
|
|
61
|
-
// .input(getQueryInput(Interface))
|
|
62
|
-
// .output(z.array(Interface))
|
|
63
|
-
// .query(({ input, ctx }) => (ctx.app.service.Interface.getInterfaces as any)(input, ctx)),
|
|
64
|
-
|
|
65
|
-
// createInterface: procedure
|
|
66
|
-
// .use(hasRole('admin', t))
|
|
67
|
-
// .use(customErrorFormatter(t))
|
|
68
|
-
// .input(getQueryInput(Interface))
|
|
69
|
-
// .output(Interface.pick({ id: true }))
|
|
70
|
-
// .mutation(({ input, ctx }) => (ctx.app.service.Interface.createInterface as any)(input, ctx)),
|
|
71
|
-
|
|
72
|
-
// updateInterface: procedure
|
|
73
|
-
// .use(hasRole('admin', t))
|
|
74
|
-
// .use(customErrorFormatter(t))
|
|
75
|
-
// .input(getQueryInput(Interface))
|
|
76
|
-
// .output(Interface.pick({ id: true }))
|
|
77
|
-
// .mutation(({ input, ctx }) => (ctx.app.service.Interface.updateInterface as any)(input, ctx)),
|
|
78
|
-
|
|
79
|
-
// deleteInterface: procedure
|
|
80
|
-
// .use(hasRole('admin', t))
|
|
81
|
-
// .use(customErrorFormatter(t))
|
|
82
|
-
// .input(getQueryInput(Interface))
|
|
83
|
-
// .output(Interface.pick({ id: true }))
|
|
84
|
-
// .mutation(({ input, ctx }) => (ctx.app.service.Interface.deleteInterface as any)(input, ctx)),
|
|
85
|
-
|
|
86
|
-
// InterfaceGroup Procedures
|
|
87
|
-
getInterfaceGroup: procedure
|
|
88
|
-
.use(hasRole('guest', t))
|
|
89
|
-
.use(customErrorFormatter(t))
|
|
90
|
-
.input(getQueryInput(InterfaceGroup))
|
|
91
|
-
.output(InterfaceGroup)
|
|
92
|
-
.query(({ input, ctx }) => (ctx.app.service.Interface.getInterfaceGroup as any)(input, ctx)),
|
|
93
|
-
|
|
94
|
-
getInterfaceGroups: procedure
|
|
95
|
-
.use(hasRole('guest', t))
|
|
96
|
-
.use(customErrorFormatter(t))
|
|
97
|
-
.input(getQueryInput(InterfaceGroup))
|
|
98
|
-
.output(z.array(InterfaceGroup))
|
|
99
|
-
.query(({ input, ctx }) => (ctx.app.service.Interface.getInterfaceGroups as any)(input, ctx)),
|
|
100
|
-
|
|
101
|
-
createInterfaceGroup: procedure
|
|
102
|
-
.use(hasRole('admin', t))
|
|
103
|
-
.use(customErrorFormatter(t))
|
|
104
|
-
.input(getQueryInput(InterfaceGroup))
|
|
105
|
-
.output(InterfaceGroup.pick({ id: true }))
|
|
106
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.createInterfaceGroup as any)(input, ctx)),
|
|
107
|
-
|
|
108
|
-
updateInterfaceGroup: procedure
|
|
109
|
-
.use(hasRole('admin', t))
|
|
110
|
-
.use(customErrorFormatter(t))
|
|
111
|
-
.input(getQueryInput(InterfaceGroup))
|
|
112
|
-
.output(InterfaceGroup.pick({ id: true }))
|
|
113
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.updateInterfaceGroup as any)(input, ctx)),
|
|
114
|
-
|
|
115
|
-
// InterfaceComponent Procedures
|
|
116
|
-
getInterfaceComponent: procedure
|
|
117
|
-
.use(hasRole('guest', t))
|
|
118
|
-
.use(customErrorFormatter(t))
|
|
119
|
-
.input(getQueryInput(InterfaceComponent))
|
|
120
|
-
.output(InterfaceComponent)
|
|
121
|
-
.query(({ input, ctx }) => (ctx.app.service.Interface.getInterfaceComponent as any)(input, ctx)),
|
|
122
|
-
|
|
123
|
-
createInterfaceComponent: procedure
|
|
124
|
-
.use(hasRole('admin', t))
|
|
125
|
-
.use(customErrorFormatter(t))
|
|
126
|
-
.input(getQueryInput(InterfaceComponent))
|
|
127
|
-
.output(InterfaceComponent.pick({ id: true }))
|
|
128
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.createInterfaceComponent as any)(input, ctx)),
|
|
129
|
-
|
|
130
|
-
updateInterfaceComponent: procedure
|
|
131
|
-
.use(hasRole('admin', t))
|
|
132
|
-
.use(customErrorFormatter(t))
|
|
133
|
-
.input(getQueryInput(InterfaceComponent))
|
|
134
|
-
.output(InterfaceComponent.pick({ id: true }))
|
|
135
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.updateInterfaceComponent as any)(input, ctx)),
|
|
136
|
-
|
|
137
|
-
publishInterface: procedure
|
|
138
|
-
.use(hasRole('admin', t))
|
|
139
|
-
.use(customErrorFormatter(t))
|
|
140
|
-
.input(getQueryInput(Interface))
|
|
141
|
-
.output(Interface.pick({ id: true }))
|
|
142
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.updateInterfaceComponent as any)(input, ctx)),
|
|
143
|
-
|
|
144
|
-
deactivateInterface: procedure
|
|
145
|
-
.use(hasRole('admin', t))
|
|
146
|
-
.use(customErrorFormatter(t))
|
|
147
|
-
.input(getQueryInput(Interface))
|
|
148
|
-
.output(Interface.pick({ id: true }))
|
|
149
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.updateInterfaceComponent as any)(input, ctx)),
|
|
150
|
-
|
|
151
|
-
resetInterface: procedure
|
|
152
|
-
.use(hasRole('admin', t))
|
|
153
|
-
.use(customErrorFormatter(t))
|
|
154
|
-
.input(getQueryInput(Interface))
|
|
155
|
-
.output(Interface.pick({ id: true }))
|
|
156
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.updateInterfaceComponent as any)(input, ctx)),
|
|
157
|
-
|
|
158
|
-
acceptInterfaceSubmission: procedure
|
|
159
|
-
.use(hasRole('admin', t))
|
|
160
|
-
.use(customErrorFormatter(t))
|
|
161
|
-
.input(getQueryInput(Interface))
|
|
162
|
-
.output(Interface.pick({ id: true }))
|
|
163
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.updateInterfaceComponent as any)(input, ctx)),
|
|
164
|
-
|
|
165
|
-
createInterfaceDraft: procedure
|
|
166
|
-
.use(hasRole('admin', t))
|
|
167
|
-
.use(customErrorFormatter(t))
|
|
168
|
-
.input(getQueryInput(Interface))
|
|
169
|
-
.output(Interface.pick({ id: true }))
|
|
170
|
-
.mutation(({ input, ctx }) => (ctx.app.service.Interface.createInterfaceDraft as any)(input, ctx)),
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
export type Router = ReturnType<typeof createRouter>;
|
|
174
|
-
export type RouterInput = inferRouterInputs<Router>;
|
|
175
|
-
export type RouterOutput = inferRouterOutputs<Router>;
|