@appconda/nextjs 1.1.2 → 1.1.4

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.
@@ -0,0 +1,2 @@
1
+ export * from './lib/handler';
2
+ import './lib/jobs';
@@ -0,0 +1,3 @@
1
+ export * from './lib/handler';
2
+ import './lib/jobs';
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbW9kdWxlcy9ob29rcy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxjQUFjLGVBQWUsQ0FBQztBQUU5QixPQUFPLFlBQVksQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIlxuZXhwb3J0ICogZnJvbSAnLi9saWIvaGFuZGxlcic7XG5cbmltcG9ydCAnLi9saWIvam9icyc7XG4iXX0=
@@ -0,0 +1,32 @@
1
+ type TaskPayload = {
2
+ timestamp: Date;
3
+ lastTimestamp?: Date;
4
+ timezone: string;
5
+ };
6
+ type TaskContext = {
7
+ retriesLeft: number;
8
+ };
9
+ type TriggerArgs = {
10
+ id: string;
11
+ events: string[];
12
+ maxDuration?: number;
13
+ retries?: number;
14
+ run: (payload: TaskPayload, tools: {
15
+ ctx: TaskContext;
16
+ }) => Promise<void> | void;
17
+ };
18
+ export declare class Hooks {
19
+ private lastRunTimestamps;
20
+ private triggers;
21
+ trigger(args: TriggerArgs): void;
22
+ run(hookId: string): Promise<void>;
23
+ private runWithRetry;
24
+ toJSON(): {
25
+ id: string;
26
+ event: string[];
27
+ maxDuration: number | undefined;
28
+ retries: number | undefined;
29
+ }[];
30
+ }
31
+ export declare const hooks: Hooks;
32
+ export {};
@@ -0,0 +1,64 @@
1
+ export class Hooks {
2
+ constructor() {
3
+ this.lastRunTimestamps = {};
4
+ this.triggers = [];
5
+ }
6
+ trigger(args) {
7
+ this.triggers.push(args);
8
+ }
9
+ async run(hookId) {
10
+ const now = new Date();
11
+ const lastTimestamp = this.lastRunTimestamps[hookId];
12
+ const payload = {
13
+ timestamp: now,
14
+ lastTimestamp,
15
+ timezone: "UTC",
16
+ };
17
+ this.lastRunTimestamps[hookId] = now;
18
+ const context = {
19
+ retriesLeft: this.triggers.find(hook => hook.id === hookId)?.retries ?? 0,
20
+ };
21
+ await this.runWithRetry(this.triggers.find(hook => hook.id === hookId), payload, context);
22
+ }
23
+ async runWithRetry(trigger, payload, ctx) {
24
+ const start = Date.now();
25
+ try {
26
+ await Promise.race([
27
+ trigger.run(payload, { ctx }),
28
+ timeout(trigger.maxDuration ?? 60),
29
+ ]);
30
+ log("success", { taskId: trigger.id, time: new Date().toISOString() });
31
+ }
32
+ catch (err) {
33
+ //@ts-ignore
34
+ log("error", { taskId: trigger.id, error: err });
35
+ if (ctx.retriesLeft > 0) {
36
+ ctx.retriesLeft -= 1;
37
+ //@ts-ignore
38
+ log("warn", { taskId: trigger.id, msg: "Retrying..." });
39
+ await this.runWithRetry(trigger, payload, ctx);
40
+ }
41
+ }
42
+ finally {
43
+ const duration = Date.now() - start;
44
+ //@ts-ignore
45
+ log("info", { taskId: trigger.id, durationMs: duration });
46
+ }
47
+ }
48
+ toJSON() {
49
+ return this.triggers.map(trigger => ({
50
+ id: trigger.id,
51
+ event: trigger.events,
52
+ maxDuration: trigger.maxDuration,
53
+ retries: trigger.retries,
54
+ }));
55
+ }
56
+ }
57
+ function log(arg0, arg1) {
58
+ // console.log(arg0, arg1);
59
+ }
60
+ function timeout(seconds) {
61
+ return new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout reached")), seconds * 1000));
62
+ }
63
+ export const hooks = new Hooks();
64
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSG9va3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9ob29rcy9saWIvSG9va3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBc0JBLE1BQU0sT0FBTyxLQUFLO0lBQWxCO1FBQ1ksc0JBQWlCLEdBQXlCLEVBQUUsQ0FBQztRQUM3QyxhQUFRLEdBQWtCLEVBQUUsQ0FBQztJQWlFekMsQ0FBQztJQS9EVSxPQUFPLENBQUMsSUFBaUI7UUFDNUIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVNLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBYztRQUMzQixNQUFNLEdBQUcsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3ZCLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVyRCxNQUFNLE9BQU8sR0FBZ0I7WUFDekIsU0FBUyxFQUFFLEdBQUc7WUFDZCxhQUFhO1lBQ2IsUUFBUSxFQUFFLEtBQUs7U0FDbEIsQ0FBQztRQUVGLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsR0FBRyxHQUFHLENBQUM7UUFFckMsTUFBTSxPQUFPLEdBQWdCO1lBQ3pCLFdBQVcsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssTUFBTSxDQUFDLEVBQUUsT0FBTyxJQUFJLENBQUM7U0FDNUUsQ0FBQztRQUVGLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssTUFBTSxDQUFFLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRy9GLENBQUM7SUFFTyxLQUFLLENBQUMsWUFBWSxDQUN0QixPQUFvQixFQUNwQixPQUFvQixFQUNwQixHQUFnQjtRQUVoQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFekIsSUFBSSxDQUFDO1lBQ0QsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDO2dCQUNmLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLEVBQUUsR0FBRyxFQUFFLENBQUM7Z0JBQzdCLE9BQU8sQ0FBQyxPQUFPLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQzthQUNyQyxDQUFDLENBQUM7WUFDSCxHQUFHLENBQUMsU0FBUyxFQUFFLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzNFLENBQUM7UUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ1gsWUFBWTtZQUNaLEdBQUcsQ0FBQyxPQUFPLEVBQUUsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUVqRCxJQUFJLEdBQUcsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3RCLEdBQUcsQ0FBQyxXQUFXLElBQUksQ0FBQyxDQUFDO2dCQUNyQixZQUFZO2dCQUNaLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxHQUFHLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBQztnQkFDeEQsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDbkQsQ0FBQztRQUNMLENBQUM7Z0JBQVMsQ0FBQztZQUNQLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLENBQUM7WUFDcEMsWUFBWTtZQUNaLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUM5RCxDQUFDO0lBQ0wsQ0FBQztJQUVNLE1BQU07UUFDVCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNqQyxFQUFFLEVBQUUsT0FBTyxDQUFDLEVBQUU7WUFDZCxLQUFLLEVBQUUsT0FBTyxDQUFDLE1BQU07WUFDckIsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXO1lBQ2hDLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztTQUMzQixDQUFDLENBQUMsQ0FBQztJQUNSLENBQUM7Q0FDSjtBQUVELFNBQVMsR0FBRyxDQUFDLElBQVksRUFBRSxJQUF1QztJQUM5RCwyQkFBMkI7QUFDL0IsQ0FBQztBQUVELFNBQVMsT0FBTyxDQUFDLE9BQWU7SUFDNUIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUM3QixVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLGlCQUFpQixDQUFDLENBQUMsRUFBRSxPQUFPLEdBQUcsSUFBSSxDQUFDLENBQ3pFLENBQUM7QUFDTixDQUFDO0FBR0QsTUFBTSxDQUFDLE1BQU0sS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJcbnR5cGUgVGFza1BheWxvYWQgPSB7XG4gICAgdGltZXN0YW1wOiBEYXRlO1xuICAgIGxhc3RUaW1lc3RhbXA/OiBEYXRlO1xuICAgIHRpbWV6b25lOiBzdHJpbmc7XG59O1xuXG50eXBlIFRhc2tDb250ZXh0ID0ge1xuICAgIHJldHJpZXNMZWZ0OiBudW1iZXI7XG59O1xuXG50eXBlIFRyaWdnZXJBcmdzID0ge1xuICAgIGlkOiBzdHJpbmc7XG4gICAgZXZlbnRzOiBzdHJpbmdbXTtcbiAgICBtYXhEdXJhdGlvbj86IG51bWJlcjsgLy8gc2FuaXllXG4gICAgcmV0cmllcz86IG51bWJlcjtcbiAgICBydW46IChcbiAgICAgICAgcGF5bG9hZDogVGFza1BheWxvYWQsXG4gICAgICAgIHRvb2xzOiB7IGN0eDogVGFza0NvbnRleHQgfVxuICAgICkgPT4gUHJvbWlzZTx2b2lkPiB8IHZvaWQ7XG59O1xuXG5leHBvcnQgY2xhc3MgSG9va3Mge1xuICAgIHByaXZhdGUgbGFzdFJ1blRpbWVzdGFtcHM6IFJlY29yZDxzdHJpbmcsIERhdGU+ID0ge307XG4gICAgcHJpdmF0ZSB0cmlnZ2VyczogVHJpZ2dlckFyZ3NbXSA9IFtdO1xuXG4gICAgcHVibGljIHRyaWdnZXIoYXJnczogVHJpZ2dlckFyZ3MpIHtcbiAgICAgICAgdGhpcy50cmlnZ2Vycy5wdXNoKGFyZ3MpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBydW4oaG9va0lkOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICAgICAgY29uc3QgbGFzdFRpbWVzdGFtcCA9IHRoaXMubGFzdFJ1blRpbWVzdGFtcHNbaG9va0lkXTtcblxuICAgICAgICBjb25zdCBwYXlsb2FkOiBUYXNrUGF5bG9hZCA9IHtcbiAgICAgICAgICAgIHRpbWVzdGFtcDogbm93LFxuICAgICAgICAgICAgbGFzdFRpbWVzdGFtcCxcbiAgICAgICAgICAgIHRpbWV6b25lOiBcIlVUQ1wiLFxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMubGFzdFJ1blRpbWVzdGFtcHNbaG9va0lkXSA9IG5vdztcblxuICAgICAgICBjb25zdCBjb250ZXh0OiBUYXNrQ29udGV4dCA9IHtcbiAgICAgICAgICAgIHJldHJpZXNMZWZ0OiB0aGlzLnRyaWdnZXJzLmZpbmQoaG9vayA9PiBob29rLmlkID09PSBob29rSWQpPy5yZXRyaWVzID8/IDAsXG4gICAgICAgIH07XG5cbiAgICAgICAgYXdhaXQgdGhpcy5ydW5XaXRoUmV0cnkodGhpcy50cmlnZ2Vycy5maW5kKGhvb2sgPT4gaG9vay5pZCA9PT0gaG9va0lkKSEsIHBheWxvYWQsIGNvbnRleHQpO1xuXG5cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJ1bldpdGhSZXRyeShcbiAgICAgICAgdHJpZ2dlcjogVHJpZ2dlckFyZ3MsXG4gICAgICAgIHBheWxvYWQ6IFRhc2tQYXlsb2FkLFxuICAgICAgICBjdHg6IFRhc2tDb250ZXh0XG4gICAgKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICAgICAgICAgICAgICB0cmlnZ2VyLnJ1bihwYXlsb2FkLCB7IGN0eCB9KSxcbiAgICAgICAgICAgICAgICB0aW1lb3V0KHRyaWdnZXIubWF4RHVyYXRpb24gPz8gNjApLFxuICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICBsb2coXCJzdWNjZXNzXCIsIHsgdGFza0lkOiB0cmlnZ2VyLmlkLCB0aW1lOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgLy9AdHMtaWdub3JlXG4gICAgICAgICAgICBsb2coXCJlcnJvclwiLCB7IHRhc2tJZDogdHJpZ2dlci5pZCwgZXJyb3I6IGVyciB9KTtcblxuICAgICAgICAgICAgaWYgKGN0eC5yZXRyaWVzTGVmdCA+IDApIHtcbiAgICAgICAgICAgICAgICBjdHgucmV0cmllc0xlZnQgLT0gMTtcbiAgICAgICAgICAgICAgICAvL0B0cy1pZ25vcmVcbiAgICAgICAgICAgICAgICBsb2coXCJ3YXJuXCIsIHsgdGFza0lkOiB0cmlnZ2VyLmlkLCBtc2c6IFwiUmV0cnlpbmcuLi5cIiB9KTtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJ1bldpdGhSZXRyeSh0cmlnZ2VyLCBwYXlsb2FkLCBjdHgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgY29uc3QgZHVyYXRpb24gPSBEYXRlLm5vdygpIC0gc3RhcnQ7XG4gICAgICAgICAgICAvL0B0cy1pZ25vcmVcbiAgICAgICAgICAgIGxvZyhcImluZm9cIiwgeyB0YXNrSWQ6IHRyaWdnZXIuaWQsIGR1cmF0aW9uTXM6IGR1cmF0aW9uIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHRvSlNPTigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudHJpZ2dlcnMubWFwKHRyaWdnZXIgPT4gKHtcbiAgICAgICAgICAgIGlkOiB0cmlnZ2VyLmlkLFxuICAgICAgICAgICAgZXZlbnQ6IHRyaWdnZXIuZXZlbnRzLFxuICAgICAgICAgICAgbWF4RHVyYXRpb246IHRyaWdnZXIubWF4RHVyYXRpb24sXG4gICAgICAgICAgICByZXRyaWVzOiB0cmlnZ2VyLnJldHJpZXMsXG4gICAgICAgIH0pKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGxvZyhhcmcwOiBzdHJpbmcsIGFyZzE6IHsgdGFza0lkOiBzdHJpbmc7IHRpbWU6IHN0cmluZzsgfSkge1xuICAgIC8vIGNvbnNvbGUubG9nKGFyZzAsIGFyZzEpO1xufVxuXG5mdW5jdGlvbiB0aW1lb3V0KHNlY29uZHM6IG51bWJlcikge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgoXywgcmVqZWN0KSA9PlxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHJlamVjdChuZXcgRXJyb3IoXCJUaW1lb3V0IHJlYWNoZWRcIikpLCBzZWNvbmRzICogMTAwMClcbiAgICApO1xufVxuXG5cbmV4cG9ydCBjb25zdCBob29rcyA9IG5ldyBIb29rcygpOyJdfQ==
@@ -0,0 +1,12 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import './jobs';
3
+ export declare function hookHandler(request: NextRequest, res: NextResponse): Promise<NextResponse<{
4
+ message: string;
5
+ }> | NextResponse<{
6
+ hooks: {
7
+ id: string;
8
+ event: string[];
9
+ maxDuration: number | undefined;
10
+ retries: number | undefined;
11
+ }[];
12
+ }>>;
@@ -0,0 +1,23 @@
1
+ import { NextResponse } from 'next/server';
2
+ import './jobs';
3
+ import { hooks } from './Hooks';
4
+ /* export async function GET() {
5
+ return NextResponse.json({ schedules: schedules.toJSON() },
6
+ { status: 200 });
7
+ }
8
+
9
+ export async function POST(request: Request) {
10
+
11
+ } */
12
+ export async function hookHandler(request, res) {
13
+ if (request.method === 'POST') {
14
+ const body = await request.json();
15
+ const hookId = body.hookId;
16
+ hooks.run(hookId);
17
+ return NextResponse.json({ message: 'Callback triggered' }, { status: 200 });
18
+ }
19
+ else {
20
+ return NextResponse.json({ hooks: hooks.toJSON() }, { status: 200 });
21
+ }
22
+ }
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2hvb2tzL2xpYi9oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBZSxZQUFZLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFeEQsT0FBTyxRQUFRLENBQUM7QUFDaEIsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUVoQzs7Ozs7OztJQU9JO0FBRUosTUFBTSxDQUFDLEtBQUssVUFBVSxXQUFXLENBQUMsT0FBb0IsRUFBRSxHQUFpQjtJQUN2RSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssTUFBTSxFQUFFLENBQUM7UUFDOUIsTUFBTSxJQUFJLEdBQUcsTUFBTSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDbEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUMzQixLQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2xCLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxFQUN4RCxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ3JCLENBQUM7U0FBTSxDQUFDO1FBQ04sT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUNoRCxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ3JCLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTmV4dFJlcXVlc3QsIE5leHRSZXNwb25zZSB9IGZyb20gJ25leHQvc2VydmVyJztcblxuaW1wb3J0ICcuL2pvYnMnO1xuaW1wb3J0IHsgaG9va3MgfSBmcm9tICcuL0hvb2tzJztcblxuLyogZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIEdFVCgpIHtcbiAgcmV0dXJuIE5leHRSZXNwb25zZS5qc29uKHsgc2NoZWR1bGVzOiBzY2hlZHVsZXMudG9KU09OKCkgfSxcbiAgICB7IHN0YXR1czogMjAwIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gUE9TVChyZXF1ZXN0OiBSZXF1ZXN0KSB7XG5cbn0gKi9cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhvb2tIYW5kbGVyKHJlcXVlc3Q6IE5leHRSZXF1ZXN0LCByZXM6IE5leHRSZXNwb25zZSkge1xuICBpZiAocmVxdWVzdC5tZXRob2QgPT09ICdQT1NUJykge1xuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZXF1ZXN0Lmpzb24oKTtcbiAgICBjb25zdCBob29rSWQgPSBib2R5Lmhvb2tJZDtcbiAgICBob29rcy5ydW4oaG9va0lkKTtcbiAgICByZXR1cm4gTmV4dFJlc3BvbnNlLmpzb24oeyBtZXNzYWdlOiAnQ2FsbGJhY2sgdHJpZ2dlcmVkJyB9LFxuICAgICAgeyBzdGF0dXM6IDIwMCB9KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gTmV4dFJlc3BvbnNlLmpzb24oeyBob29rczogaG9va3MudG9KU09OKCkgfSxcbiAgICAgIHsgc3RhdHVzOiAyMDAgfSk7XG4gIH1cbn0gXG5cbiJdfQ==
@@ -0,0 +1,2 @@
1
+ import './log-job';
2
+ import './job1';
@@ -0,0 +1,3 @@
1
+ import './log-job';
2
+ import './job1';
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9ob29rcy9saWIvam9icy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLFdBQVcsQ0FBQztBQUNuQixPQUFPLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAnLi9sb2ctam9iJztcbmltcG9ydCAnLi9qb2IxJzsiXX0=
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import { hooks } from "../Hooks";
2
+ hooks.trigger({
3
+ id: "job1",
4
+ events: ["event1"],
5
+ run: async () => {
6
+ console.log("hello from job 1");
7
+ },
8
+ });
9
+ hooks.trigger({
10
+ id: "job2",
11
+ events: ["event2"],
12
+ run: async () => {
13
+ console.log("hello from job 2");
14
+ },
15
+ });
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iMS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2hvb2tzL2xpYi9qb2JzL2pvYjEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUVqQyxLQUFLLENBQUMsT0FBTyxDQUFDO0lBQ1YsRUFBRSxFQUFFLE1BQU07SUFDVixNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUM7SUFDbEIsR0FBRyxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ1osT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7Q0FDSixDQUFDLENBQUM7QUFHSCxLQUFLLENBQUMsT0FBTyxDQUFDO0lBQ1YsRUFBRSxFQUFFLE1BQU07SUFDVixNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUM7SUFDbEIsR0FBRyxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ1osT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7Q0FDSixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCB7IGhvb2tzIH0gZnJvbSBcIi4uL0hvb2tzXCI7XG5cbmhvb2tzLnRyaWdnZXIoe1xuICAgIGlkOiBcImpvYjFcIixcbiAgICBldmVudHM6IFtcImV2ZW50MVwiXSxcbiAgICBydW46IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coXCJoZWxsbyBmcm9tIGpvYiAxXCIpO1xuICAgIH0sXG59KTtcblxuXG5ob29rcy50cmlnZ2VyKHtcbiAgICBpZDogXCJqb2IyXCIsXG4gICAgZXZlbnRzOiBbXCJldmVudDJcIl0sXG4gICAgcnVuOiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiaGVsbG8gZnJvbSBqb2IgMlwiKTtcbiAgICB9LFxufSk7XG5cbiJdfQ==
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import { schedules } from "../Hooks";
2
+ schedules.task({
3
+ id: "test",
4
+ cron: "*/50 * * * * *",
5
+ run: async () => {
6
+ console.log("test");
7
+ },
8
+ });
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nLWpvYi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2hvb2tzL2xpYi9qb2JzL2xvZy1qb2IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUVyQyxTQUFTLENBQUMsSUFBSSxDQUFDO0lBQ1gsRUFBRSxFQUFFLE1BQU07SUFDVixJQUFJLEVBQUUsZ0JBQWdCO0lBQ3RCLEdBQUcsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNaLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDeEIsQ0FBQztDQUNKLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNjaGVkdWxlcyB9IGZyb20gXCIuLi9Ib29rc1wiO1xuXG5zY2hlZHVsZXMudGFzayh7XG4gICAgaWQ6IFwidGVzdFwiLFxuICAgIGNyb246IFwiKi81MCAqICogKiAqICpcIixcbiAgICBydW46IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coXCJ0ZXN0XCIpO1xuICAgIH0sXG59KTsiXX0=
@@ -0,0 +1,8 @@
1
+ export declare const wait: {
2
+ for: ({ seconds }: {
3
+ seconds: number;
4
+ }) => Promise<unknown>;
5
+ until: ({ date }: {
6
+ date: Date;
7
+ }) => Promise<unknown>;
8
+ };
@@ -0,0 +1,13 @@
1
+ export const wait = {
2
+ for: ({ seconds }) => new Promise((resolve) => setTimeout(resolve, seconds * 1000)),
3
+ until: ({ date }) => {
4
+ const now = new Date();
5
+ const diff = date.getTime() - now.getTime();
6
+ if (diff <= 0) {
7
+ // Hedef tarih zaten geçmişse hiç bekleme
8
+ return Promise.resolve();
9
+ }
10
+ return new Promise((resolve) => setTimeout(resolve, diff));
11
+ },
12
+ };
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FpdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2hvb2tzL2xpYi93YWl0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sQ0FBQyxNQUFNLElBQUksR0FBRztJQUNoQixHQUFHLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBdUIsRUFBRSxFQUFFLENBQ3hDLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLE9BQU8sR0FBRyxJQUFJLENBQUMsQ0FBQztJQUUvRCxLQUFLLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBa0IsRUFBRSxFQUFFO1FBQ2xDLE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDdkIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxHQUFHLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUU1QyxJQUFJLElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUNkLHlDQUF5QztZQUN6QyxPQUFPLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUMzQixDQUFDO1FBRUQsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzdELENBQUM7Q0FDRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNvbnN0IHdhaXQgPSB7XG4gICAgZm9yOiAoeyBzZWNvbmRzIH06IHsgc2Vjb25kczogbnVtYmVyIH0pID0+XG4gICAgICBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCBzZWNvbmRzICogMTAwMCkpLFxuICBcbiAgICB1bnRpbDogKHsgZGF0ZSB9OiB7IGRhdGU6IERhdGUgfSkgPT4ge1xuICAgICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICAgIGNvbnN0IGRpZmYgPSBkYXRlLmdldFRpbWUoKSAtIG5vdy5nZXRUaW1lKCk7XG4gIFxuICAgICAgaWYgKGRpZmYgPD0gMCkge1xuICAgICAgICAvLyBIZWRlZiB0YXJpaCB6YXRlbiBnZcOnbWnFn3NlIGhpw6cgYmVrbGVtZVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gIFxuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGRpZmYpKTtcbiAgICB9LFxuICB9O1xuICAiXX0=
@@ -5,3 +5,4 @@ export * from './agent';
5
5
  export * from './tenant';
6
6
  export * from './task';
7
7
  export * from './scheduled-job';
8
+ export * from './hooks';
@@ -5,4 +5,5 @@ export * from './agent';
5
5
  export * from './tenant';
6
6
  export * from './task';
7
7
  export * from './scheduled-job';
8
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbW9kdWxlcy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLFdBQVcsQ0FBQztBQUMxQixjQUFjLE1BQU0sQ0FBQztBQUNyQixjQUFjLFNBQVMsQ0FBQztBQUN4QixjQUFjLFVBQVUsQ0FBQztBQUN6QixjQUFjLFFBQVEsQ0FBQztBQUN2QixjQUFjLGlCQUFpQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi93YWl0bGlzdCc7XG5leHBvcnQgKiBmcm9tICcuL2FjY291bnQnO1xuZXhwb3J0ICogZnJvbSAnLi9haSc7XG5leHBvcnQgKiBmcm9tICcuL2FnZW50JztcbmV4cG9ydCAqIGZyb20gJy4vdGVuYW50JztcbmV4cG9ydCAqIGZyb20gJy4vdGFzayc7XG5leHBvcnQgKiBmcm9tICcuL3NjaGVkdWxlZC1qb2InOyJdfQ==
8
+ export * from './hooks';
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbW9kdWxlcy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLFdBQVcsQ0FBQztBQUMxQixjQUFjLE1BQU0sQ0FBQztBQUNyQixjQUFjLFNBQVMsQ0FBQztBQUN4QixjQUFjLFVBQVUsQ0FBQztBQUN6QixjQUFjLFFBQVEsQ0FBQztBQUN2QixjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMsU0FBUyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi93YWl0bGlzdCc7XG5leHBvcnQgKiBmcm9tICcuL2FjY291bnQnO1xuZXhwb3J0ICogZnJvbSAnLi9haSc7XG5leHBvcnQgKiBmcm9tICcuL2FnZW50JztcbmV4cG9ydCAqIGZyb20gJy4vdGVuYW50JztcbmV4cG9ydCAqIGZyb20gJy4vdGFzayc7XG5leHBvcnQgKiBmcm9tICcuL3NjaGVkdWxlZC1qb2InO1xuZXhwb3J0ICogZnJvbSAnLi9ob29rcyc7Il19
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@appconda/nextjs",
3
3
  "homepage": "https://appconda.io/support",
4
4
  "description": "Appconda is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API",
5
- "version": "1.1.2",
5
+ "version": "1.1.4",
6
6
  "license": "BSD-3-Clause",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
@@ -0,0 +1,4 @@
1
+
2
+ export * from './lib/handler';
3
+
4
+ import './lib/jobs';
@@ -0,0 +1,103 @@
1
+
2
+ type TaskPayload = {
3
+ timestamp: Date;
4
+ lastTimestamp?: Date;
5
+ timezone: string;
6
+ };
7
+
8
+ type TaskContext = {
9
+ retriesLeft: number;
10
+ };
11
+
12
+ type TriggerArgs = {
13
+ id: string;
14
+ events: string[];
15
+ maxDuration?: number; // saniye
16
+ retries?: number;
17
+ run: (
18
+ payload: TaskPayload,
19
+ tools: { ctx: TaskContext }
20
+ ) => Promise<void> | void;
21
+ };
22
+
23
+ export class Hooks {
24
+ private lastRunTimestamps: Record<string, Date> = {};
25
+ private triggers: TriggerArgs[] = [];
26
+
27
+ public trigger(args: TriggerArgs) {
28
+ this.triggers.push(args);
29
+ }
30
+
31
+ public async run(hookId: string) {
32
+ const now = new Date();
33
+ const lastTimestamp = this.lastRunTimestamps[hookId];
34
+
35
+ const payload: TaskPayload = {
36
+ timestamp: now,
37
+ lastTimestamp,
38
+ timezone: "UTC",
39
+ };
40
+
41
+ this.lastRunTimestamps[hookId] = now;
42
+
43
+ const context: TaskContext = {
44
+ retriesLeft: this.triggers.find(hook => hook.id === hookId)?.retries ?? 0,
45
+ };
46
+
47
+ await this.runWithRetry(this.triggers.find(hook => hook.id === hookId)!, payload, context);
48
+
49
+
50
+ }
51
+
52
+ private async runWithRetry(
53
+ trigger: TriggerArgs,
54
+ payload: TaskPayload,
55
+ ctx: TaskContext
56
+ ) {
57
+ const start = Date.now();
58
+
59
+ try {
60
+ await Promise.race([
61
+ trigger.run(payload, { ctx }),
62
+ timeout(trigger.maxDuration ?? 60),
63
+ ]);
64
+ log("success", { taskId: trigger.id, time: new Date().toISOString() });
65
+ } catch (err) {
66
+ //@ts-ignore
67
+ log("error", { taskId: trigger.id, error: err });
68
+
69
+ if (ctx.retriesLeft > 0) {
70
+ ctx.retriesLeft -= 1;
71
+ //@ts-ignore
72
+ log("warn", { taskId: trigger.id, msg: "Retrying..." });
73
+ await this.runWithRetry(trigger, payload, ctx);
74
+ }
75
+ } finally {
76
+ const duration = Date.now() - start;
77
+ //@ts-ignore
78
+ log("info", { taskId: trigger.id, durationMs: duration });
79
+ }
80
+ }
81
+
82
+ public toJSON() {
83
+ return this.triggers.map(trigger => ({
84
+ id: trigger.id,
85
+ event: trigger.events,
86
+ maxDuration: trigger.maxDuration,
87
+ retries: trigger.retries,
88
+ }));
89
+ }
90
+ }
91
+
92
+ function log(arg0: string, arg1: { taskId: string; time: string; }) {
93
+ // console.log(arg0, arg1);
94
+ }
95
+
96
+ function timeout(seconds: number) {
97
+ return new Promise((_, reject) =>
98
+ setTimeout(() => reject(new Error("Timeout reached")), seconds * 1000)
99
+ );
100
+ }
101
+
102
+
103
+ export const hooks = new Hooks();
@@ -0,0 +1,27 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ import './jobs';
4
+ import { hooks } from './Hooks';
5
+
6
+ /* export async function GET() {
7
+ return NextResponse.json({ schedules: schedules.toJSON() },
8
+ { status: 200 });
9
+ }
10
+
11
+ export async function POST(request: Request) {
12
+
13
+ } */
14
+
15
+ export async function hookHandler(request: NextRequest, res: NextResponse) {
16
+ if (request.method === 'POST') {
17
+ const body = await request.json();
18
+ const hookId = body.hookId;
19
+ hooks.run(hookId);
20
+ return NextResponse.json({ message: 'Callback triggered' },
21
+ { status: 200 });
22
+ } else {
23
+ return NextResponse.json({ hooks: hooks.toJSON() },
24
+ { status: 200 });
25
+ }
26
+ }
27
+
@@ -0,0 +1,2 @@
1
+ import './log-job';
2
+ import './job1';
@@ -0,0 +1,20 @@
1
+
2
+ import { hooks } from "../Hooks";
3
+
4
+ hooks.trigger({
5
+ id: "job1",
6
+ events: ["event1"],
7
+ run: async () => {
8
+ console.log("hello from job 1");
9
+ },
10
+ });
11
+
12
+
13
+ hooks.trigger({
14
+ id: "job2",
15
+ events: ["event2"],
16
+ run: async () => {
17
+ console.log("hello from job 2");
18
+ },
19
+ });
20
+
@@ -0,0 +1,9 @@
1
+ import { schedules } from "../Hooks";
2
+
3
+ schedules.task({
4
+ id: "test",
5
+ cron: "*/50 * * * * *",
6
+ run: async () => {
7
+ console.log("test");
8
+ },
9
+ });
@@ -0,0 +1,17 @@
1
+ export const wait = {
2
+ for: ({ seconds }: { seconds: number }) =>
3
+ new Promise((resolve) => setTimeout(resolve, seconds * 1000)),
4
+
5
+ until: ({ date }: { date: Date }) => {
6
+ const now = new Date();
7
+ const diff = date.getTime() - now.getTime();
8
+
9
+ if (diff <= 0) {
10
+ // Hedef tarih zaten geçmişse hiç bekleme
11
+ return Promise.resolve();
12
+ }
13
+
14
+ return new Promise((resolve) => setTimeout(resolve, diff));
15
+ },
16
+ };
17
+
@@ -4,4 +4,5 @@ export * from './ai';
4
4
  export * from './agent';
5
5
  export * from './tenant';
6
6
  export * from './task';
7
- export * from './scheduled-job';
7
+ export * from './scheduled-job';
8
+ export * from './hooks';