@m5kdev/backend 0.4.0 → 0.6.0
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/dist/src/modules/ai/ai.prompts.d.ts +5 -0
- package/dist/src/modules/ai/ai.prompts.js +16 -0
- package/dist/src/modules/ai/ai.service.d.ts +26 -12
- package/dist/src/modules/ai/ai.service.js +105 -15
- package/dist/src/modules/auth/auth.dto.d.ts +2 -2
- package/dist/src/modules/auth/auth.lib.d.ts +3 -3
- package/dist/src/modules/auth/auth.repository.d.ts +2 -2
- package/dist/src/modules/auth/auth.repository.js +1 -1
- package/dist/src/modules/auth/auth.service.d.ts +3 -3
- package/dist/src/modules/auth/auth.service.js +1 -1
- package/dist/src/modules/auth/auth.trpc.d.ts +6 -6
- package/dist/src/modules/auth/auth.trpc.js +1 -1
- package/dist/src/modules/base/base.abstract.d.ts +3 -2
- package/dist/src/modules/base/base.abstract.js +10 -1
- package/dist/src/modules/base/base.procedure.d.ts +112 -0
- package/dist/src/modules/base/base.procedure.js +289 -0
- package/dist/src/modules/base/base.repository.d.ts +1 -0
- package/dist/src/modules/base/base.repository.js +12 -2
- package/dist/src/modules/base/base.service.d.ts +17 -5
- package/dist/src/modules/base/base.service.js +7 -0
- package/dist/src/modules/base/base.service.test.d.ts +1 -0
- package/dist/src/modules/base/base.service.test.js +415 -0
- package/dist/src/modules/connect/connect.repository.d.ts +3 -3
- package/dist/src/modules/connect/connect.service.d.ts +4 -4
- package/dist/src/modules/connect/connect.trpc.d.ts +2 -2
- package/dist/src/modules/recurrence/recurrence.service.d.ts +29 -8
- package/dist/src/modules/recurrence/recurrence.service.js +3 -4
- package/dist/src/modules/recurrence/recurrence.trpc.d.ts +3 -3
- package/dist/src/modules/recurrence/recurrence.trpc.js +1 -1
- package/dist/src/modules/tag/tag.db.js +1 -1
- package/dist/src/modules/tag/tag.repository.js +27 -26
- package/dist/src/modules/tag/tag.service.d.ts +86 -15
- package/dist/src/modules/tag/tag.service.js +20 -12
- package/dist/src/modules/tag/tag.trpc.d.ts +3 -3
- package/dist/src/types.d.ts +5 -5
- package/dist/src/utils/trpc.d.ts +6 -6
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.repairJsonPrompt = void 0;
|
|
4
|
+
const ai_prompt_1 = require("./ai.prompt");
|
|
5
|
+
exports.repairJsonPrompt = new ai_prompt_1.Prompt(`
|
|
6
|
+
You are a JSON repair expert. You are given a JSON string that is invalid, error message and a schema that is used to parse the JSON string. You need to repair the JSON string and return the repaired JSON adher to the schema.
|
|
7
|
+
|
|
8
|
+
## Text
|
|
9
|
+
|
|
10
|
+
{{text}}
|
|
11
|
+
|
|
12
|
+
## Error
|
|
13
|
+
|
|
14
|
+
{{error}}
|
|
15
|
+
|
|
16
|
+
`);
|
|
@@ -3,10 +3,10 @@ import type { Mastra } from "@mastra/core";
|
|
|
3
3
|
import type { FullOutput, MastraModelOutput } from "@mastra/core/stream";
|
|
4
4
|
import { MDocument } from "@mastra/rag";
|
|
5
5
|
import type { OpenRouterProvider } from "@openrouter/ai-sdk-provider";
|
|
6
|
-
import {
|
|
6
|
+
import { generateText, type ModelMessage } from "ai";
|
|
7
7
|
import type Replicate from "replicate";
|
|
8
8
|
import type { ZodType, z } from "zod";
|
|
9
|
-
import type { User } from "../auth/auth.lib";
|
|
9
|
+
import type { Context, User } from "../auth/auth.lib";
|
|
10
10
|
import type { ServerResultAsync } from "../base/base.dto";
|
|
11
11
|
import { BaseService } from "../base/base.service";
|
|
12
12
|
import type { AiUsageRepository, AiUsageRow } from "./ai.repository";
|
|
@@ -18,6 +18,26 @@ type MessageListInput = {
|
|
|
18
18
|
role: "user" | "assistant" | "system";
|
|
19
19
|
content: string;
|
|
20
20
|
}[];
|
|
21
|
+
type GenerateTextParams = Parameters<typeof generateText>[0];
|
|
22
|
+
type GenerateTextInput = {
|
|
23
|
+
prompt: string | ModelMessage[];
|
|
24
|
+
messages?: never;
|
|
25
|
+
} | {
|
|
26
|
+
messages: ModelMessage[];
|
|
27
|
+
prompt?: never;
|
|
28
|
+
};
|
|
29
|
+
type AIServiceGenerateTextParams = Omit<GenerateTextParams, "model" | "prompt" | "messages"> & GenerateTextInput & {
|
|
30
|
+
model: string;
|
|
31
|
+
removeMDash?: boolean;
|
|
32
|
+
ctx?: Context;
|
|
33
|
+
};
|
|
34
|
+
type AIServiceGenerateObjectParams<T extends ZodType> = Omit<GenerateTextParams, "model" | "prompt" | "messages" | "output"> & GenerateTextInput & {
|
|
35
|
+
model: string;
|
|
36
|
+
schema: T;
|
|
37
|
+
repairAttempts?: number;
|
|
38
|
+
repairModel?: string;
|
|
39
|
+
ctx?: Context;
|
|
40
|
+
};
|
|
21
41
|
export declare class AIService<MastraInstance extends Mastra> extends BaseService<{
|
|
22
42
|
aiUsage?: AiUsageRepository;
|
|
23
43
|
}, {
|
|
@@ -39,8 +59,8 @@ export declare class AIService<MastraInstance extends Mastra> extends BaseServic
|
|
|
39
59
|
replicate?: Replicate;
|
|
40
60
|
});
|
|
41
61
|
getMastra(): MastraInstance;
|
|
42
|
-
prepareModel(model: string):
|
|
43
|
-
prepareEmbeddingModel(model: string):
|
|
62
|
+
prepareModel(model: string): ReturnType<OpenRouterProvider["chat"]>;
|
|
63
|
+
prepareEmbeddingModel(model: string): ReturnType<OpenRouterProvider["textEmbeddingModel"]>;
|
|
44
64
|
agentUse(agent: string, options: MastraAgentGenerateOptions & {
|
|
45
65
|
prompt?: string;
|
|
46
66
|
messages?: MessageListInput;
|
|
@@ -94,14 +114,8 @@ export declare class AIService<MastraInstance extends Mastra> extends BaseServic
|
|
|
94
114
|
}[], model?: string): ServerResultAsync<{
|
|
95
115
|
embeddings: number[][];
|
|
96
116
|
}>;
|
|
97
|
-
generateText(params:
|
|
98
|
-
|
|
99
|
-
removeMDash?: boolean;
|
|
100
|
-
}): ServerResultAsync<string>;
|
|
101
|
-
generateObject<T extends ZodType>(params: Omit<Parameters<typeof generateObject<T>>[0], "model" | "schema"> & {
|
|
102
|
-
model: string;
|
|
103
|
-
schema: T;
|
|
104
|
-
}): ServerResultAsync<z.infer<T>>;
|
|
117
|
+
generateText(params: AIServiceGenerateTextParams): ServerResultAsync<string>;
|
|
118
|
+
generateObject<T extends ZodType>(params: AIServiceGenerateObjectParams<T>): ServerResultAsync<z.infer<T>>;
|
|
105
119
|
generateReplicate(model: Parameters<Replicate["run"]>[0], options: Parameters<Replicate["run"]>[1]): ServerResultAsync<object>;
|
|
106
120
|
generateTranscript(file_url: string): ServerResultAsync<{
|
|
107
121
|
text: string;
|
|
@@ -6,8 +6,10 @@ const ai_utils_1 = require("@m5kdev/commons/modules/ai/ai.utils");
|
|
|
6
6
|
const request_context_1 = require("@mastra/core/request-context");
|
|
7
7
|
const rag_1 = require("@mastra/rag");
|
|
8
8
|
const ai_1 = require("ai");
|
|
9
|
+
const jsonrepair_1 = require("jsonrepair");
|
|
9
10
|
const neverthrow_1 = require("neverthrow");
|
|
10
11
|
const base_service_1 = require("../base/base.service");
|
|
12
|
+
const ai_prompts_1 = require("./ai.prompts");
|
|
11
13
|
class AIService extends base_service_1.BaseService {
|
|
12
14
|
helpers = {
|
|
13
15
|
arrayToPseudoXML: ai_utils_1.arrayToPseudoXML,
|
|
@@ -31,15 +33,19 @@ class AIService extends base_service_1.BaseService {
|
|
|
31
33
|
if (!this.openrouter) {
|
|
32
34
|
throw new Error("OpenRouter is not configured");
|
|
33
35
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
return this.openrouter.chat(model, {
|
|
37
|
+
usage: {
|
|
38
|
+
include: true,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
36
41
|
}
|
|
37
42
|
prepareEmbeddingModel(model) {
|
|
38
43
|
if (!this.openrouter) {
|
|
39
44
|
throw new Error("OpenRouter is not configured");
|
|
40
45
|
}
|
|
41
|
-
const
|
|
42
|
-
return
|
|
46
|
+
const openrouter = this.openrouter;
|
|
47
|
+
return (openrouter.embeddingModel?.(model) ??
|
|
48
|
+
openrouter.textEmbeddingModel(model));
|
|
43
49
|
}
|
|
44
50
|
async agentUse(agent, options, ctx) {
|
|
45
51
|
return this.throwableAsync(async () => {
|
|
@@ -146,21 +152,105 @@ class AIService extends base_service_1.BaseService {
|
|
|
146
152
|
}
|
|
147
153
|
async generateText(params) {
|
|
148
154
|
return this.throwableAsync(async () => {
|
|
149
|
-
const { removeMDash = true, model, ...rest } = params;
|
|
150
|
-
const
|
|
155
|
+
const { removeMDash = true, model, prompt, messages, ctx, ...rest } = params;
|
|
156
|
+
const request = messages
|
|
157
|
+
? { ...rest, model: this.prepareModel(model), messages }
|
|
158
|
+
: { ...rest, model: this.prepareModel(model), prompt };
|
|
159
|
+
const result = await (0, ai_1.generateText)(request);
|
|
160
|
+
if (this.repository.aiUsage) {
|
|
161
|
+
const createUsageResult = await this.repository.aiUsage.create({
|
|
162
|
+
userId: ctx?.user?.id,
|
|
163
|
+
model,
|
|
164
|
+
provider: "openrouter",
|
|
165
|
+
feature: "generateText",
|
|
166
|
+
traceId: result.providerMetadata?.openrouter?.traceId?.toString(),
|
|
167
|
+
inputTokens: result.usage.inputTokens,
|
|
168
|
+
outputTokens: result.usage.outputTokens,
|
|
169
|
+
totalTokens: result.usage.totalTokens,
|
|
170
|
+
cost: result?.providerMetadata?.openrouter?.usage?.cost ?? 0,
|
|
171
|
+
});
|
|
172
|
+
if (createUsageResult.isErr())
|
|
173
|
+
return (0, neverthrow_1.err)(createUsageResult.error);
|
|
174
|
+
}
|
|
151
175
|
return (0, neverthrow_1.ok)(removeMDash ? result.text.replace(/\u2013|\u2014/g, "-") : result.text);
|
|
152
176
|
});
|
|
153
177
|
}
|
|
154
178
|
async generateObject(params) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
...
|
|
159
|
-
model,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
179
|
+
const { model, schema, prompt, messages, repairAttempts = 0, repairModel, ctx, ...rest } = params;
|
|
180
|
+
const request = messages
|
|
181
|
+
? {
|
|
182
|
+
...rest,
|
|
183
|
+
model: this.prepareModel(model),
|
|
184
|
+
messages,
|
|
185
|
+
output: ai_1.Output.object({ schema }),
|
|
186
|
+
}
|
|
187
|
+
: {
|
|
188
|
+
...rest,
|
|
189
|
+
model: this.prepareModel(model),
|
|
190
|
+
prompt,
|
|
191
|
+
output: ai_1.Output.object({ schema }),
|
|
192
|
+
};
|
|
193
|
+
try {
|
|
194
|
+
const result = await (0, ai_1.generateText)(request);
|
|
195
|
+
if (this.repository.aiUsage) {
|
|
196
|
+
const createUsageResult = await this.repository.aiUsage.create({
|
|
197
|
+
userId: ctx?.user?.id,
|
|
198
|
+
model,
|
|
199
|
+
provider: "openrouter",
|
|
200
|
+
feature: "generateObject",
|
|
201
|
+
traceId: result.providerMetadata?.openrouter?.traceId?.toString(),
|
|
202
|
+
inputTokens: result.usage.inputTokens,
|
|
203
|
+
outputTokens: result.usage.outputTokens,
|
|
204
|
+
totalTokens: result.usage.totalTokens,
|
|
205
|
+
cost: result?.providerMetadata?.openrouter?.usage?.cost ?? 0,
|
|
206
|
+
});
|
|
207
|
+
if (createUsageResult.isErr())
|
|
208
|
+
return (0, neverthrow_1.err)(createUsageResult.error);
|
|
209
|
+
}
|
|
210
|
+
return (0, neverthrow_1.ok)(result.output);
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
if (ai_1.NoObjectGeneratedError.isInstance(error)) {
|
|
214
|
+
if (this.repository.aiUsage) {
|
|
215
|
+
const createUsageResult = await this.repository.aiUsage.create({
|
|
216
|
+
userId: ctx?.user?.id,
|
|
217
|
+
model,
|
|
218
|
+
provider: "openrouter",
|
|
219
|
+
feature: "generateObject",
|
|
220
|
+
traceId: null,
|
|
221
|
+
inputTokens: error?.usage?.inputTokens,
|
|
222
|
+
outputTokens: error?.usage?.outputTokens,
|
|
223
|
+
totalTokens: error?.usage?.totalTokens,
|
|
224
|
+
cost: 0,
|
|
225
|
+
});
|
|
226
|
+
if (createUsageResult.isErr())
|
|
227
|
+
return (0, neverthrow_1.err)(createUsageResult.error);
|
|
228
|
+
}
|
|
229
|
+
if (error.text) {
|
|
230
|
+
const repairedText = (0, jsonrepair_1.jsonrepair)(error.text);
|
|
231
|
+
const parsed = schema.safeParse(repairedText);
|
|
232
|
+
if (parsed.success)
|
|
233
|
+
return (0, neverthrow_1.ok)(parsed.data);
|
|
234
|
+
if (repairAttempts === 0)
|
|
235
|
+
return this.error("PARSE_ERROR", "AI: Agent object failed", { cause: error });
|
|
236
|
+
return this.generateObject({
|
|
237
|
+
...rest,
|
|
238
|
+
prompt: ai_prompts_1.repairJsonPrompt.compile({
|
|
239
|
+
text: error.text,
|
|
240
|
+
error: JSON.stringify(error.cause ?? "Unknown error"),
|
|
241
|
+
}),
|
|
242
|
+
repairAttempts: repairAttempts - 1,
|
|
243
|
+
model: repairModel ?? model,
|
|
244
|
+
schema,
|
|
245
|
+
ctx,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
return this.error("PARSE_ERROR", "AI: Agent object failed without text", {
|
|
249
|
+
cause: error,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
return this.error("BAD_REQUEST", "AI: Provided failed to generate object", { cause: error });
|
|
253
|
+
}
|
|
164
254
|
}
|
|
165
255
|
async generateReplicate(model, options) {
|
|
166
256
|
return this.throwableAsync(async () => {
|
|
@@ -10,9 +10,9 @@ export declare const waitlistSchema: z.ZodObject<{
|
|
|
10
10
|
expiresAt: z.ZodNullable<z.ZodDate>;
|
|
11
11
|
}, z.core.$strip>;
|
|
12
12
|
export declare const waitlistOutputSchema: z.ZodObject<{
|
|
13
|
-
name: z.ZodNullable<z.ZodString>;
|
|
14
13
|
id: z.ZodString;
|
|
15
14
|
email: z.ZodNullable<z.ZodString>;
|
|
15
|
+
name: z.ZodNullable<z.ZodString>;
|
|
16
16
|
status: z.ZodString;
|
|
17
17
|
createdAt: z.ZodDate;
|
|
18
18
|
updatedAt: z.ZodNullable<z.ZodDate>;
|
|
@@ -53,9 +53,9 @@ export declare const accountClaimMagicLinkSchema: z.ZodObject<{
|
|
|
53
53
|
createdAt: z.ZodDate;
|
|
54
54
|
}, z.core.$strip>;
|
|
55
55
|
export declare const accountClaimMagicLinkOutputSchema: z.ZodObject<{
|
|
56
|
-
url: z.ZodString;
|
|
57
56
|
id: z.ZodString;
|
|
58
57
|
email: z.ZodString;
|
|
58
|
+
url: z.ZodString;
|
|
59
59
|
createdAt: z.ZodDate;
|
|
60
60
|
userId: z.ZodString;
|
|
61
61
|
expiresAt: z.ZodNullable<z.ZodDate>;
|
|
@@ -3260,13 +3260,13 @@ export declare function createBetterAuth<O extends Orm, S extends Schema, E exte
|
|
|
3260
3260
|
$Infer: {
|
|
3261
3261
|
body: ({
|
|
3262
3262
|
permission: {
|
|
3263
|
-
readonly user?: ("get" | "
|
|
3263
|
+
readonly user?: ("get" | "set-role" | "create" | "update" | "delete" | "list" | "ban" | "impersonate" | "set-password")[] | undefined;
|
|
3264
3264
|
readonly session?: ("delete" | "list" | "revoke")[] | undefined;
|
|
3265
3265
|
};
|
|
3266
3266
|
permissions?: never | undefined;
|
|
3267
3267
|
} | {
|
|
3268
3268
|
permissions: {
|
|
3269
|
-
readonly user?: ("get" | "
|
|
3269
|
+
readonly user?: ("get" | "set-role" | "create" | "update" | "delete" | "list" | "ban" | "impersonate" | "set-password")[] | undefined;
|
|
3270
3270
|
readonly session?: ("delete" | "list" | "revoke")[] | undefined;
|
|
3271
3271
|
};
|
|
3272
3272
|
permission?: never | undefined;
|
|
@@ -4811,7 +4811,7 @@ export declare function createBetterAuth<O extends Orm, S extends Schema, E exte
|
|
|
4811
4811
|
} | undefined;
|
|
4812
4812
|
verification?: {
|
|
4813
4813
|
modelName?: string;
|
|
4814
|
-
fields?: Partial<Record<"
|
|
4814
|
+
fields?: Partial<Record<"createdAt" | "updatedAt" | "expiresAt" | "value" | "identifier", string>>;
|
|
4815
4815
|
additionalFields?: {
|
|
4816
4816
|
[key: string]: import("better-auth", { with: { "resolution-mode": "import" } }).DBFieldAttribute;
|
|
4817
4817
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { LibSQLDatabase } from "drizzle-orm/libsql";
|
|
2
|
-
import * as auth from "./auth.db";
|
|
3
|
-
import type { AccountClaim, AccountClaimMagicLink, AccountClaimMagicLinkOutput, AccountClaimOutput, Waitlist, WaitlistOutput } from "./auth.dto";
|
|
4
2
|
import type { ServerResultAsync } from "../base/base.dto";
|
|
5
3
|
import { BaseRepository } from "../base/base.repository";
|
|
4
|
+
import * as auth from "./auth.db";
|
|
5
|
+
import type { AccountClaim, AccountClaimMagicLink, AccountClaimMagicLinkOutput, AccountClaimOutput, Waitlist, WaitlistOutput } from "./auth.dto";
|
|
6
6
|
declare const schema: {
|
|
7
7
|
users: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
8
8
|
name: "users";
|
|
@@ -5,8 +5,8 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const drizzle_orm_1 = require("drizzle-orm");
|
|
6
6
|
const neverthrow_1 = require("neverthrow");
|
|
7
7
|
const uuid_1 = require("uuid");
|
|
8
|
-
const auth = tslib_1.__importStar(require("./auth.db"));
|
|
9
8
|
const base_repository_1 = require("../base/base.repository");
|
|
9
|
+
const auth = tslib_1.__importStar(require("./auth.db"));
|
|
10
10
|
const schema = { ...auth };
|
|
11
11
|
function parseOrganizationMetadata(metadata) {
|
|
12
12
|
if (!metadata)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { AccountClaim, AccountClaimMagicLinkOutput, AccountClaimOutput, Waitlist, WaitlistOutput } from "./auth.dto";
|
|
2
|
-
import type { Context, User } from "./auth.lib";
|
|
3
|
-
import type { AuthRepository } from "./auth.repository";
|
|
4
1
|
import type { ServerResultAsync } from "../base/base.dto";
|
|
5
2
|
import { BaseService } from "../base/base.service";
|
|
6
3
|
import type { BillingService } from "../billing/billing.service";
|
|
7
4
|
import type { EmailService } from "../email/email.service";
|
|
5
|
+
import type { AccountClaim, AccountClaimMagicLinkOutput, AccountClaimOutput, Waitlist, WaitlistOutput } from "./auth.dto";
|
|
6
|
+
import type { Context, User } from "./auth.lib";
|
|
7
|
+
import type { AuthRepository } from "./auth.repository";
|
|
8
8
|
type AuthServiceDependencies = {
|
|
9
9
|
email: EmailService;
|
|
10
10
|
} | {
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AuthService = void 0;
|
|
4
4
|
const neverthrow_1 = require("neverthrow");
|
|
5
|
-
const base_service_1 = require("../base/base.service");
|
|
6
5
|
const posthog_1 = require("../../utils/posthog");
|
|
6
|
+
const base_service_1 = require("../base/base.service");
|
|
7
7
|
class AuthService extends base_service_1.BaseService {
|
|
8
8
|
getBillingService() {
|
|
9
9
|
if (!("billing" in this.service))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AuthService } from "./auth.service";
|
|
2
1
|
import { type TRPCMethods } from "../../utils/trpc";
|
|
2
|
+
import type { AuthService } from "./auth.service";
|
|
3
3
|
export declare function createAuthTRPC({ router, publicProcedure, privateProcedure: procedure, adminProcedure }: TRPCMethods, authService: AuthService): import("@trpc/server").TRPCBuiltRouter<{
|
|
4
4
|
ctx: import("./auth.lib").Context;
|
|
5
5
|
meta: any;
|
|
@@ -138,8 +138,8 @@ export declare function createAuthTRPC({ router, publicProcedure, privateProcedu
|
|
|
138
138
|
listAdminWaitlist: import("@trpc/server").TRPCQueryProcedure<{
|
|
139
139
|
input: void;
|
|
140
140
|
output: {
|
|
141
|
-
name: string | null;
|
|
142
141
|
id: string;
|
|
142
|
+
name: string | null;
|
|
143
143
|
email: string | null;
|
|
144
144
|
createdAt: Date;
|
|
145
145
|
updatedAt: Date | null;
|
|
@@ -152,8 +152,8 @@ export declare function createAuthTRPC({ router, publicProcedure, privateProcedu
|
|
|
152
152
|
email: string;
|
|
153
153
|
};
|
|
154
154
|
output: {
|
|
155
|
-
name: string | null;
|
|
156
155
|
id: string;
|
|
156
|
+
name: string | null;
|
|
157
157
|
email: string | null;
|
|
158
158
|
createdAt: Date;
|
|
159
159
|
updatedAt: Date | null;
|
|
@@ -183,8 +183,8 @@ export declare function createAuthTRPC({ router, publicProcedure, privateProcedu
|
|
|
183
183
|
id: string;
|
|
184
184
|
};
|
|
185
185
|
output: {
|
|
186
|
-
name: string | null;
|
|
187
186
|
id: string;
|
|
187
|
+
name: string | null;
|
|
188
188
|
email: string | null;
|
|
189
189
|
createdAt: Date;
|
|
190
190
|
updatedAt: Date | null;
|
|
@@ -197,8 +197,8 @@ export declare function createAuthTRPC({ router, publicProcedure, privateProcedu
|
|
|
197
197
|
id: string;
|
|
198
198
|
};
|
|
199
199
|
output: {
|
|
200
|
-
name: string | null;
|
|
201
200
|
id: string;
|
|
201
|
+
name: string | null;
|
|
202
202
|
email: string | null;
|
|
203
203
|
createdAt: Date;
|
|
204
204
|
updatedAt: Date | null;
|
|
@@ -211,8 +211,8 @@ export declare function createAuthTRPC({ router, publicProcedure, privateProcedu
|
|
|
211
211
|
email: string;
|
|
212
212
|
};
|
|
213
213
|
output: {
|
|
214
|
-
name: string | null;
|
|
215
214
|
id: string;
|
|
215
|
+
name: string | null;
|
|
216
216
|
email: string | null;
|
|
217
217
|
createdAt: Date;
|
|
218
218
|
updatedAt: Date | null;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createAuthTRPC = createAuthTRPC;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const auth_dto_1 = require("./auth.dto");
|
|
6
5
|
const trpc_1 = require("../../utils/trpc");
|
|
6
|
+
const auth_dto_1 = require("./auth.dto");
|
|
7
7
|
function createAuthTRPC({ router, publicProcedure, privateProcedure: procedure, adminProcedure }, authService) {
|
|
8
8
|
return router({
|
|
9
9
|
getUserWaitlistCount: procedure.output(zod_1.z.number()).query(async ({ ctx }) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { TRPC_ERROR_CODE_KEY } from "@trpc/server";
|
|
2
|
-
import type { ServerResult, ServerResultAsync } from "./base.dto";
|
|
3
|
-
import type { ServerErrorLayer } from "./base.types";
|
|
4
2
|
import { ServerError } from "../../utils/errors";
|
|
5
3
|
import { logger } from "../../utils/logger";
|
|
4
|
+
import type { ServerResult, ServerResultAsync } from "./base.dto";
|
|
5
|
+
import type { ServerErrorLayer } from "./base.types";
|
|
6
6
|
export declare abstract class Base {
|
|
7
7
|
layer: ServerErrorLayer;
|
|
8
8
|
logger: ReturnType<typeof logger.child>;
|
|
@@ -15,4 +15,5 @@ export declare abstract class Base {
|
|
|
15
15
|
handleUnknownError(error: unknown): ServerError;
|
|
16
16
|
throwable<T>(fn: () => ServerResult<T>): ServerResult<T>;
|
|
17
17
|
throwableAsync<T>(fn: () => ServerResultAsync<T>): ServerResultAsync<T>;
|
|
18
|
+
throwablePromise<T>(fn: () => Promise<T>, errorHandler?: (error: unknown) => ServerError): ServerResultAsync<T>;
|
|
18
19
|
}
|
|
@@ -43,11 +43,20 @@ class Base {
|
|
|
43
43
|
}
|
|
44
44
|
async throwableAsync(fn) {
|
|
45
45
|
try {
|
|
46
|
-
return fn();
|
|
46
|
+
return await fn();
|
|
47
47
|
}
|
|
48
48
|
catch (error) {
|
|
49
49
|
return (0, neverthrow_1.err)(this.handleUnknownError(error));
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
+
async throwablePromise(fn, errorHandler) {
|
|
53
|
+
try {
|
|
54
|
+
const result = await fn();
|
|
55
|
+
return (0, neverthrow_1.ok)(result);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
return (0, neverthrow_1.err)(errorHandler ? errorHandler(error) : this.handleUnknownError(error));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
52
61
|
}
|
|
53
62
|
exports.Base = Base;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { QueryInput } from "@m5kdev/commons/modules/schemas/query.schema";
|
|
2
|
+
import type { TRPC_ERROR_CODE_KEY } from "@trpc/server";
|
|
3
|
+
import type { ServerError } from "../../utils/errors";
|
|
4
|
+
import type { logger } from "../../utils/logger";
|
|
5
|
+
import type { Context, Session, User } from "../auth/auth.lib";
|
|
6
|
+
import type { Base } from "./base.abstract";
|
|
7
|
+
import type { ServerResult, ServerResultAsync } from "./base.dto";
|
|
8
|
+
import type { Entity, ResourceActionGrant } from "./base.grants";
|
|
9
|
+
type ServiceLogger = ReturnType<typeof logger.child>;
|
|
10
|
+
type RepositoryMap = Record<string, Base>;
|
|
11
|
+
type ServiceMap = Record<string, Base>;
|
|
12
|
+
export type ServiceProcedureContext = {
|
|
13
|
+
user?: User | null;
|
|
14
|
+
session?: Session | null;
|
|
15
|
+
} & Record<string, unknown>;
|
|
16
|
+
export type ServiceProcedureState = Record<string, unknown>;
|
|
17
|
+
export type ServiceProcedureStoredValue<T> = [T] extends [undefined] ? undefined : Awaited<T>;
|
|
18
|
+
export type ServiceProcedureResultLike<T> = T | ServerResult<T> | Promise<T | ServerResult<T>>;
|
|
19
|
+
export type ServiceProcedureContextFilterScope = "user" | "organization" | "team";
|
|
20
|
+
export type ServiceProcedureContextFilteredInput<TInput> = Extract<NonNullable<TInput>, QueryInput>;
|
|
21
|
+
export type ServiceProcedure<TInput, TCtx extends ServiceProcedureContext, TOutput> = (input: TInput, ctx: TCtx) => ServerResultAsync<TOutput>;
|
|
22
|
+
export type ServiceProcedureArgs<TInput, TCtx extends ServiceProcedureContext, Repositories extends RepositoryMap, Services extends ServiceMap, State extends ServiceProcedureState> = {
|
|
23
|
+
input: TInput;
|
|
24
|
+
ctx: TCtx;
|
|
25
|
+
state: State;
|
|
26
|
+
repository: Repositories;
|
|
27
|
+
service: Services;
|
|
28
|
+
logger: ServiceLogger;
|
|
29
|
+
};
|
|
30
|
+
export type ServiceProcedureStep<TInput, TCtx extends ServiceProcedureContext, Repositories extends RepositoryMap, Services extends ServiceMap, State extends ServiceProcedureState, TOutput = undefined> = (args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>) => ServiceProcedureResultLike<ServiceProcedureStoredValue<TOutput>>;
|
|
31
|
+
export type ServiceProcedureInputMapper<TInput, TCtx extends ServiceProcedureContext, Repositories extends RepositoryMap, Services extends ServiceMap, State extends ServiceProcedureState, TNextInput> = (args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>) => ServiceProcedureResultLike<ServiceProcedureStoredValue<TNextInput>>;
|
|
32
|
+
export type ServiceProcedureHandler<TInput, TCtx extends ServiceProcedureContext, Repositories extends RepositoryMap, Services extends ServiceMap, State extends ServiceProcedureState, TOutput> = (args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>) => ServiceProcedureResultLike<TOutput>;
|
|
33
|
+
export type ServiceProcedureEntityResolver<TInput, TCtx extends ServiceProcedureContext, Repositories extends RepositoryMap, Services extends ServiceMap, State extends ServiceProcedureState, TEntities extends Entity | Entity[] | undefined> = TEntities | ((args: ServiceProcedureArgs<TInput, TCtx, Repositories, Services, State>) => ServiceProcedureResultLike<TEntities>);
|
|
34
|
+
type ServiceProcedureAccessBaseConfig = {
|
|
35
|
+
action: string;
|
|
36
|
+
grants?: ResourceActionGrant[];
|
|
37
|
+
};
|
|
38
|
+
export type ServiceProcedureEntityStepName<State extends ServiceProcedureState> = Extract<{
|
|
39
|
+
[Key in keyof State]: State[Key] extends Entity | Entity[] | undefined ? Key : never;
|
|
40
|
+
}[keyof State], string>;
|
|
41
|
+
export type ServiceProcedureAccessEntitiesConfig<TInput, TCtx extends ServiceProcedureContext, Repositories extends RepositoryMap, Services extends ServiceMap, State extends ServiceProcedureState, TEntities extends Entity | Entity[] | undefined = undefined> = ServiceProcedureAccessBaseConfig & {
|
|
42
|
+
entities?: ServiceProcedureEntityResolver<TInput, TCtx, Repositories, Services, State, TEntities>;
|
|
43
|
+
entityStep?: never;
|
|
44
|
+
};
|
|
45
|
+
export type ServiceProcedureAccessStateConfig<State extends ServiceProcedureState, StepName extends ServiceProcedureEntityStepName<State>> = ServiceProcedureAccessBaseConfig & {
|
|
46
|
+
entityStep: StepName;
|
|
47
|
+
entities?: never;
|
|
48
|
+
};
|
|
49
|
+
export type ServiceProcedureAccessConfig<TInput, TCtx extends ServiceProcedureContext, Repositories extends RepositoryMap, Services extends ServiceMap, State extends ServiceProcedureState, TEntities extends Entity | Entity[] | undefined = undefined> = ServiceProcedureAccessEntitiesConfig<TInput, TCtx, Repositories, Services, State, TEntities> | ServiceProcedureAccessStateConfig<State, ServiceProcedureEntityStepName<State>>;
|
|
50
|
+
export interface ServiceProcedureBuilder<TInput, TCtx extends ServiceProcedureContext, Repositories extends RepositoryMap, Services extends ServiceMap, State extends ServiceProcedureState = Record<string, never>> {
|
|
51
|
+
use<StepName extends string, TOutput = void>(stepName: StepName, step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>): ServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State & Record<StepName, ServiceProcedureStoredValue<TOutput>>>;
|
|
52
|
+
mapInput<StepName extends string, TNextInput>(stepName: StepName, step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>): ServiceProcedureBuilder<ServiceProcedureStoredValue<TNextInput>, TCtx, Repositories, Services, State & Record<StepName, ServiceProcedureStoredValue<TNextInput>>>;
|
|
53
|
+
addContextFilter(include?: readonly ServiceProcedureContextFilterScope[]): ServiceProcedureBuilder<ServiceProcedureContextFilteredInput<TInput>, TCtx & Context, Repositories, Services, State & {
|
|
54
|
+
contextFilter: ServiceProcedureContextFilteredInput<TInput>;
|
|
55
|
+
}>;
|
|
56
|
+
requireAuth(): ServiceProcedureBuilder<TInput, TCtx & Context, Repositories, Services, State>;
|
|
57
|
+
handle<TOutput>(handler: ServiceProcedureHandler<TInput, TCtx, Repositories, Services, State, TOutput>): ServiceProcedure<TInput, TCtx, TOutput>;
|
|
58
|
+
}
|
|
59
|
+
export interface PermissionServiceProcedureBuilder<TInput, TCtx extends ServiceProcedureContext, Repositories extends RepositoryMap, Services extends ServiceMap, State extends ServiceProcedureState = Record<string, never>> extends ServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State> {
|
|
60
|
+
use<StepName extends string, TOutput = void>(stepName: StepName, step: ServiceProcedureStep<TInput, TCtx, Repositories, Services, State, TOutput>): PermissionServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State & Record<StepName, ServiceProcedureStoredValue<TOutput>>>;
|
|
61
|
+
mapInput<StepName extends string, TNextInput>(stepName: StepName, step: ServiceProcedureInputMapper<TInput, TCtx, Repositories, Services, State, TNextInput>): PermissionServiceProcedureBuilder<ServiceProcedureStoredValue<TNextInput>, TCtx, Repositories, Services, State & Record<StepName, ServiceProcedureStoredValue<TNextInput>>>;
|
|
62
|
+
addContextFilter(include?: readonly ServiceProcedureContextFilterScope[]): PermissionServiceProcedureBuilder<ServiceProcedureContextFilteredInput<TInput>, TCtx & Context, Repositories, Services, State & {
|
|
63
|
+
contextFilter: ServiceProcedureContextFilteredInput<TInput>;
|
|
64
|
+
}>;
|
|
65
|
+
requireAuth(): PermissionServiceProcedureBuilder<TInput, TCtx & Context, Repositories, Services, State>;
|
|
66
|
+
access(config: ServiceProcedureAccessEntitiesConfig<TInput, TCtx, Repositories, Services, State>): PermissionServiceProcedureBuilder<TInput, TCtx & Context, Repositories, Services, State>;
|
|
67
|
+
access<TEntities extends Entity | Entity[] | undefined>(config: ServiceProcedureAccessEntitiesConfig<TInput, TCtx, Repositories, Services, State, TEntities>): PermissionServiceProcedureBuilder<TInput, TCtx & Context, Repositories, Services, State & {
|
|
68
|
+
access: TEntities;
|
|
69
|
+
}>;
|
|
70
|
+
access<StepName extends ServiceProcedureEntityStepName<State>>(config: ServiceProcedureAccessStateConfig<State, StepName>): PermissionServiceProcedureBuilder<TInput, TCtx & Context, Repositories, Services, State & {
|
|
71
|
+
access: State[StepName];
|
|
72
|
+
}>;
|
|
73
|
+
}
|
|
74
|
+
type BaseServiceProcedureHost<Repositories extends RepositoryMap, Services extends ServiceMap> = {
|
|
75
|
+
repository: Repositories;
|
|
76
|
+
service: Services;
|
|
77
|
+
logger: ServiceLogger;
|
|
78
|
+
addContextFilter(ctx: Context, include?: {
|
|
79
|
+
user?: boolean;
|
|
80
|
+
organization?: boolean;
|
|
81
|
+
team?: boolean;
|
|
82
|
+
}, query?: QueryInput): QueryInput;
|
|
83
|
+
error(code: TRPC_ERROR_CODE_KEY, message?: string, options?: {
|
|
84
|
+
cause?: unknown;
|
|
85
|
+
clientMessage?: string;
|
|
86
|
+
log?: boolean;
|
|
87
|
+
}): ServerResult<never>;
|
|
88
|
+
throwableAsync<T>(fn: () => ServerResultAsync<T>): ServerResultAsync<T>;
|
|
89
|
+
handleUnknownError(error: unknown): ServerError;
|
|
90
|
+
};
|
|
91
|
+
type PermissionServiceProcedureHost<Repositories extends RepositoryMap, Services extends ServiceMap> = BaseServiceProcedureHost<Repositories, Services> & {
|
|
92
|
+
checkPermission<T extends Entity>(ctx: {
|
|
93
|
+
session: Session;
|
|
94
|
+
user: User;
|
|
95
|
+
}, action: string, entities?: T | T[], grants?: ResourceActionGrant[]): boolean;
|
|
96
|
+
checkPermissionAsync<T extends Entity>(ctx: {
|
|
97
|
+
session: Session;
|
|
98
|
+
user: User;
|
|
99
|
+
}, action: string, getEntities: () => ServerResultAsync<T | T[] | undefined>, grants?: ResourceActionGrant[]): ServerResultAsync<boolean>;
|
|
100
|
+
};
|
|
101
|
+
type ProcedureRuntimeStep<Repositories extends RepositoryMap, Services extends ServiceMap> = {
|
|
102
|
+
stage: "use" | "input" | "auth" | "access";
|
|
103
|
+
stepName: string;
|
|
104
|
+
run: (args: ServiceProcedureArgs<unknown, ServiceProcedureContext, Repositories, Services, ServiceProcedureState>) => Promise<ServerResult<unknown>>;
|
|
105
|
+
};
|
|
106
|
+
type ProcedureBuilderConfig<Repositories extends RepositoryMap, Services extends ServiceMap> = {
|
|
107
|
+
name: string;
|
|
108
|
+
steps: ProcedureRuntimeStep<Repositories, Services>[];
|
|
109
|
+
};
|
|
110
|
+
export declare function createServiceProcedureBuilder<TInput, TCtx extends ServiceProcedureContext, Repositories extends RepositoryMap, Services extends ServiceMap, State extends ServiceProcedureState = Record<string, never>>(host: BaseServiceProcedureHost<Repositories, Services>, config: ProcedureBuilderConfig<Repositories, Services>): ServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State>;
|
|
111
|
+
export declare function createPermissionServiceProcedureBuilder<TInput, TCtx extends ServiceProcedureContext, Repositories extends RepositoryMap, Services extends ServiceMap, State extends ServiceProcedureState = Record<string, never>>(host: PermissionServiceProcedureHost<Repositories, Services>, config: ProcedureBuilderConfig<Repositories, Services>): PermissionServiceProcedureBuilder<TInput, TCtx, Repositories, Services, State>;
|
|
112
|
+
export {};
|