skedyul 1.5.13 → 1.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/cli/index.js +178 -148
- package/dist/config/app-config.d.ts +6 -0
- package/dist/config/index.d.ts +1 -1
- package/dist/config/sequencer-config.d.ts +20 -0
- package/dist/config/types/model.d.ts +2 -0
- package/dist/core/client.d.ts +23 -8
- package/dist/dedicated/server.js +35 -11
- package/dist/esm/index.mjs +527 -42
- package/dist/index.d.ts +3 -1
- package/dist/index.js +544 -42
- package/dist/schemas/crm-schema.d.ts +10 -0
- package/dist/schemas.d.ts +44 -0
- package/dist/sequencer/backends/index.d.ts +10 -0
- package/dist/sequencer/backends/memory.d.ts +26 -0
- package/dist/sequencer/backends/platform.d.ts +22 -0
- package/dist/sequencer/config-loader.d.ts +9 -0
- package/dist/sequencer/errors.d.ts +17 -0
- package/dist/sequencer/index.d.ts +24 -0
- package/dist/sequencer/resolve-sequencer-key.d.ts +7 -0
- package/dist/sequencer/types.d.ts +50 -0
- package/dist/server.js +35 -11
- package/dist/serverless/server.mjs +35 -11
- package/package.json +2 -2
|
@@ -280,6 +280,11 @@ export declare const CRMPageSchemaZ: z.ZodObject<{
|
|
|
280
280
|
icon: z.ZodOptional<z.ZodString>;
|
|
281
281
|
modelHandle: z.ZodString;
|
|
282
282
|
parentPath: z.ZodOptional<z.ZodString>;
|
|
283
|
+
isDefault: z.ZodOptional<z.ZodBoolean>;
|
|
284
|
+
visibility: z.ZodOptional<z.ZodEnum<{
|
|
285
|
+
team: "team";
|
|
286
|
+
private: "private";
|
|
287
|
+
}>>;
|
|
283
288
|
baseQuery: z.ZodOptional<z.ZodUnknown>;
|
|
284
289
|
blocks: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
285
290
|
type: z.ZodEnum<{
|
|
@@ -406,6 +411,11 @@ export declare const CRMSchemaZ: z.ZodObject<{
|
|
|
406
411
|
icon: z.ZodOptional<z.ZodString>;
|
|
407
412
|
modelHandle: z.ZodString;
|
|
408
413
|
parentPath: z.ZodOptional<z.ZodString>;
|
|
414
|
+
isDefault: z.ZodOptional<z.ZodBoolean>;
|
|
415
|
+
visibility: z.ZodOptional<z.ZodEnum<{
|
|
416
|
+
team: "team";
|
|
417
|
+
private: "private";
|
|
418
|
+
}>>;
|
|
409
419
|
baseQuery: z.ZodOptional<z.ZodUnknown>;
|
|
410
420
|
blocks: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
411
421
|
type: z.ZodEnum<{
|
package/dist/schemas.d.ts
CHANGED
|
@@ -327,6 +327,17 @@ export declare const ModelDefinitionSchema: z.ZodObject<{
|
|
|
327
327
|
addDefaultPages: z.ZodOptional<z.ZodBoolean>;
|
|
328
328
|
addNavigation: z.ZodOptional<z.ZodBoolean>;
|
|
329
329
|
page: z.ZodOptional<z.ZodString>;
|
|
330
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
331
|
+
label: z.ZodString;
|
|
332
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
333
|
+
visibility: z.ZodOptional<z.ZodEnum<{
|
|
334
|
+
visible: "visible";
|
|
335
|
+
encrypted: "encrypted";
|
|
336
|
+
}>>;
|
|
337
|
+
default: z.ZodOptional<z.ZodString>;
|
|
338
|
+
description: z.ZodOptional<z.ZodString>;
|
|
339
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
340
|
+
}, z.core.$strip>>>;
|
|
330
341
|
}, z.core.$strip>;
|
|
331
342
|
export declare const RelationshipCardinalitySchema: z.ZodEnum<{
|
|
332
343
|
ONE_TO_ONE: "ONE_TO_ONE";
|
|
@@ -3218,6 +3229,17 @@ export declare const InstallConfigSchema: z.ZodObject<{
|
|
|
3218
3229
|
addDefaultPages: z.ZodOptional<z.ZodBoolean>;
|
|
3219
3230
|
addNavigation: z.ZodOptional<z.ZodBoolean>;
|
|
3220
3231
|
page: z.ZodOptional<z.ZodString>;
|
|
3232
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
3233
|
+
label: z.ZodString;
|
|
3234
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
3235
|
+
visibility: z.ZodOptional<z.ZodEnum<{
|
|
3236
|
+
visible: "visible";
|
|
3237
|
+
encrypted: "encrypted";
|
|
3238
|
+
}>>;
|
|
3239
|
+
default: z.ZodOptional<z.ZodString>;
|
|
3240
|
+
description: z.ZodOptional<z.ZodString>;
|
|
3241
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
3242
|
+
}, z.core.$strip>>>;
|
|
3221
3243
|
}, z.core.$strip>>>;
|
|
3222
3244
|
relationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
3223
3245
|
source: z.ZodObject<{
|
|
@@ -3341,6 +3363,17 @@ export declare const ProvisionConfigSchema: z.ZodObject<{
|
|
|
3341
3363
|
addDefaultPages: z.ZodOptional<z.ZodBoolean>;
|
|
3342
3364
|
addNavigation: z.ZodOptional<z.ZodBoolean>;
|
|
3343
3365
|
page: z.ZodOptional<z.ZodString>;
|
|
3366
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
3367
|
+
label: z.ZodString;
|
|
3368
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
3369
|
+
visibility: z.ZodOptional<z.ZodEnum<{
|
|
3370
|
+
visible: "visible";
|
|
3371
|
+
encrypted: "encrypted";
|
|
3372
|
+
}>>;
|
|
3373
|
+
default: z.ZodOptional<z.ZodString>;
|
|
3374
|
+
description: z.ZodOptional<z.ZodString>;
|
|
3375
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
3376
|
+
}, z.core.$strip>>>;
|
|
3344
3377
|
}, z.core.$strip>>>;
|
|
3345
3378
|
relationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
3346
3379
|
source: z.ZodObject<{
|
|
@@ -4076,6 +4109,17 @@ export declare const SkedyulConfigSchema: z.ZodObject<{
|
|
|
4076
4109
|
addDefaultPages: z.ZodOptional<z.ZodBoolean>;
|
|
4077
4110
|
addNavigation: z.ZodOptional<z.ZodBoolean>;
|
|
4078
4111
|
page: z.ZodOptional<z.ZodString>;
|
|
4112
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
4113
|
+
label: z.ZodString;
|
|
4114
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
4115
|
+
visibility: z.ZodOptional<z.ZodEnum<{
|
|
4116
|
+
visible: "visible";
|
|
4117
|
+
encrypted: "encrypted";
|
|
4118
|
+
}>>;
|
|
4119
|
+
default: z.ZodOptional<z.ZodString>;
|
|
4120
|
+
description: z.ZodOptional<z.ZodString>;
|
|
4121
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
4122
|
+
}, z.core.$strip>>>;
|
|
4079
4123
|
}, z.core.$strip>>>;
|
|
4080
4124
|
relationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
4081
4125
|
source: z.ZodObject<{
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { platformSequencerBackend } from './platform';
|
|
2
|
+
import { memorySequencerBackend, resetMemorySequencerBackendForTests } from './memory';
|
|
3
|
+
import type { SequencerBackend } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the active sequencer backend.
|
|
6
|
+
* Uses platform proxy by default; falls back to in-memory when configured or on local errors.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getSequencerBackend(): SequencerBackend;
|
|
9
|
+
export declare function resetSequencerBackendForTests(): void;
|
|
10
|
+
export { platformSequencerBackend, memorySequencerBackend, resetMemorySequencerBackendForTests };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { SequencerBackend, SequencerAllowResult } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* In-process sequencer backend for local development and tests.
|
|
4
|
+
*/
|
|
5
|
+
export declare class MemorySequencerBackend implements SequencerBackend {
|
|
6
|
+
private readonly state;
|
|
7
|
+
private getState;
|
|
8
|
+
allow(sequencerKey: string, input: {
|
|
9
|
+
timestamp: number;
|
|
10
|
+
leaseId?: string;
|
|
11
|
+
watermarkTtlMs?: number;
|
|
12
|
+
}): Promise<SequencerAllowResult>;
|
|
13
|
+
acquire(sequencerKey: string, input: {
|
|
14
|
+
leaseId: string;
|
|
15
|
+
timestamp?: number;
|
|
16
|
+
lockTtlMs?: number;
|
|
17
|
+
watermarkTtlMs?: number;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
acquired: boolean;
|
|
20
|
+
reason: 'ok' | 'locked';
|
|
21
|
+
}>;
|
|
22
|
+
release(sequencerKey: string, leaseId: string): Promise<void>;
|
|
23
|
+
resetForTests(): void;
|
|
24
|
+
}
|
|
25
|
+
export declare const memorySequencerBackend: MemorySequencerBackend;
|
|
26
|
+
export declare function resetMemorySequencerBackendForTests(): void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SequencerBackend, SequencerAllowResult } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* HTTP backend that delegates allow/acquire/release to the Skedyul platform proxy.
|
|
4
|
+
*/
|
|
5
|
+
export declare class PlatformSequencerBackend implements SequencerBackend {
|
|
6
|
+
allow(sequencerKey: string, input: {
|
|
7
|
+
timestamp: number;
|
|
8
|
+
leaseId?: string;
|
|
9
|
+
watermarkTtlMs?: number;
|
|
10
|
+
}): Promise<SequencerAllowResult>;
|
|
11
|
+
acquire(sequencerKey: string, input: {
|
|
12
|
+
leaseId: string;
|
|
13
|
+
timestamp?: number;
|
|
14
|
+
lockTtlMs?: number;
|
|
15
|
+
watermarkTtlMs?: number;
|
|
16
|
+
}): Promise<{
|
|
17
|
+
acquired: boolean;
|
|
18
|
+
reason: 'ok' | 'locked';
|
|
19
|
+
}>;
|
|
20
|
+
release(sequencerKey: string, leaseId: string): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export declare const platformSequencerBackend: PlatformSequencerBackend;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SkedyulConfig } from '../config/app-config';
|
|
2
|
+
import type { SerializableSequencerConfig } from '../config/sequencer-config';
|
|
3
|
+
/**
|
|
4
|
+
* Register in-process server config for sequencer resolution at runtime.
|
|
5
|
+
*/
|
|
6
|
+
export declare function registerSequencerConfig(config: SkedyulConfig): void;
|
|
7
|
+
export declare function clearRegisteredSequencerConfig(): void;
|
|
8
|
+
export declare function getSequencerDefinitions(): Record<string, SerializableSequencerConfig>;
|
|
9
|
+
export declare function getSequencerConfig(sequencerName: string): SerializableSequencerConfig | undefined;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class SequencerContextError extends Error {
|
|
2
|
+
readonly code = "SEQUENCER_CONTEXT_ERROR";
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
export declare class SequencerNotFoundError extends Error {
|
|
6
|
+
readonly code = "SEQUENCER_NOT_FOUND";
|
|
7
|
+
constructor(name: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class SequencerBackendError extends Error {
|
|
10
|
+
readonly code = "SEQUENCER_BACKEND_ERROR";
|
|
11
|
+
readonly statusCode?: number;
|
|
12
|
+
constructor(message: string, statusCode?: number);
|
|
13
|
+
}
|
|
14
|
+
export declare class SequencerLockError extends Error {
|
|
15
|
+
readonly code = "SEQUENCER_LOCK_ERROR";
|
|
16
|
+
constructor(message: string);
|
|
17
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SequencerInput, SequencerAllowInput, SequencerAcquireInput, SequencerReleaseInput, SequencerAllowResult, ResolvedSequencer } from './types';
|
|
2
|
+
import type { RateLimitExecutionContext } from '../ratelimit/types';
|
|
3
|
+
export declare function resolveSequencer(sequencerInput: SequencerInput, ctxOverride?: Partial<RateLimitExecutionContext>): ResolvedSequencer;
|
|
4
|
+
export declare function createSequencerHandle(sequencerInput: SequencerInput, ctxOverride?: Partial<RateLimitExecutionContext>): {
|
|
5
|
+
allow(input: Omit<SequencerAllowInput, "key">): Promise<SequencerAllowResult>;
|
|
6
|
+
acquire(input: Omit<SequencerAcquireInput, "key">): Promise<void>;
|
|
7
|
+
release(input: Omit<SequencerReleaseInput, "key">): Promise<void>;
|
|
8
|
+
};
|
|
9
|
+
export declare function allow(sequencerInput: SequencerInput, input: SequencerAllowInput, ctxOverride?: Partial<RateLimitExecutionContext>): Promise<SequencerAllowResult>;
|
|
10
|
+
export declare function acquire(sequencerInput: SequencerInput, input: SequencerAcquireInput, ctxOverride?: Partial<RateLimitExecutionContext>): Promise<void>;
|
|
11
|
+
export declare function release(sequencerInput: SequencerInput, input: SequencerReleaseInput, ctxOverride?: Partial<RateLimitExecutionContext>): Promise<void>;
|
|
12
|
+
export { registerSequencerConfig, clearRegisteredSequencerConfig, getSequencerConfig, getSequencerDefinitions, } from './config-loader';
|
|
13
|
+
export { resolveSequencerKey } from './resolve-sequencer-key';
|
|
14
|
+
export { getSequencerBackend, resetSequencerBackendForTests, memorySequencerBackend, platformSequencerBackend, resetMemorySequencerBackendForTests, } from './backends';
|
|
15
|
+
export { SequencerContextError, SequencerNotFoundError, SequencerBackendError, SequencerLockError, } from './errors';
|
|
16
|
+
export type { SequencerInput, SequencerSelector, SequencerAllowInput, SequencerAcquireInput, SequencerReleaseInput, SequencerAllowResult, ResolvedSequencer, SequencerBackend, SequencerReason, SequencerExecutionContext, } from './types';
|
|
17
|
+
export type { SequencerScope, SerializableSequencerConfig, SequencerRegistry, } from '../config/sequencer-config';
|
|
18
|
+
export declare const sequencer: {
|
|
19
|
+
allow: typeof allow;
|
|
20
|
+
acquire: typeof acquire;
|
|
21
|
+
release: typeof release;
|
|
22
|
+
resolve: typeof resolveSequencer;
|
|
23
|
+
createHandle: typeof createSequencerHandle;
|
|
24
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RateLimitExecutionContext } from '../ratelimit/types';
|
|
2
|
+
import type { SerializableSequencerConfig } from '../config/sequencer-config';
|
|
3
|
+
/**
|
|
4
|
+
* Build the Redis sequencer key for a named sequencer definition.
|
|
5
|
+
* Must stay in sync with skedyul-core sequencer validation.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveSequencerKey(sequencerName: string, config: SerializableSequencerConfig, ctx: RateLimitExecutionContext, subKey?: string): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { SerializableSequencerConfig } from '../config/sequencer-config';
|
|
2
|
+
export type { RateLimitExecutionContext as SequencerExecutionContext } from '../ratelimit/types';
|
|
3
|
+
export type SequencerReason = 'ok' | 'stale' | 'locked' | 'disabled';
|
|
4
|
+
export interface SequencerSelector {
|
|
5
|
+
sequencer: string;
|
|
6
|
+
key?: string;
|
|
7
|
+
}
|
|
8
|
+
export type SequencerInput = string | SequencerSelector;
|
|
9
|
+
export interface SequencerAllowInput {
|
|
10
|
+
key?: string;
|
|
11
|
+
timestamp: number;
|
|
12
|
+
leaseId?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface SequencerAcquireInput {
|
|
15
|
+
key?: string;
|
|
16
|
+
leaseId: string;
|
|
17
|
+
timestamp?: number;
|
|
18
|
+
lockTtlMs?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface SequencerReleaseInput {
|
|
21
|
+
key?: string;
|
|
22
|
+
leaseId: string;
|
|
23
|
+
}
|
|
24
|
+
export interface SequencerAllowResult {
|
|
25
|
+
allowed: boolean;
|
|
26
|
+
reason: SequencerReason;
|
|
27
|
+
watermark?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface ResolvedSequencer {
|
|
30
|
+
name: string;
|
|
31
|
+
sequencerKey: string;
|
|
32
|
+
config: SerializableSequencerConfig;
|
|
33
|
+
}
|
|
34
|
+
export interface SequencerBackend {
|
|
35
|
+
allow(sequencerKey: string, input: {
|
|
36
|
+
timestamp: number;
|
|
37
|
+
leaseId?: string;
|
|
38
|
+
watermarkTtlMs?: number;
|
|
39
|
+
}): Promise<SequencerAllowResult>;
|
|
40
|
+
acquire(sequencerKey: string, input: {
|
|
41
|
+
leaseId: string;
|
|
42
|
+
timestamp?: number;
|
|
43
|
+
lockTtlMs?: number;
|
|
44
|
+
watermarkTtlMs?: number;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
acquired: boolean;
|
|
47
|
+
reason: 'ok' | 'locked';
|
|
48
|
+
}>;
|
|
49
|
+
release(sequencerKey: string, leaseId: string): Promise<void>;
|
|
50
|
+
}
|
package/dist/server.js
CHANGED
|
@@ -97,6 +97,16 @@ function registerQueueConfig(config) {
|
|
|
97
97
|
cachedRuntimeQueues = config.queues ?? null;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
// src/sequencer/config-loader.ts
|
|
101
|
+
var fs2 = __toESM(require("fs"));
|
|
102
|
+
var path2 = __toESM(require("path"));
|
|
103
|
+
var cachedRuntimeSequencers = null;
|
|
104
|
+
var registeredServerConfig2 = null;
|
|
105
|
+
function registerSequencerConfig(config) {
|
|
106
|
+
registeredServerConfig2 = config;
|
|
107
|
+
cachedRuntimeSequencers = config.sequencers ?? null;
|
|
108
|
+
}
|
|
109
|
+
|
|
100
110
|
// src/server/utils/schema.ts
|
|
101
111
|
var z = __toESM(require("zod"));
|
|
102
112
|
function normalizeBilling(billing) {
|
|
@@ -733,7 +743,7 @@ function printStartupLog(config, tools, port) {
|
|
|
733
743
|
|
|
734
744
|
// src/server/route-handlers/adapters.ts
|
|
735
745
|
function fromLambdaEvent(event) {
|
|
736
|
-
const
|
|
746
|
+
const path4 = event.path || event.rawPath || "/";
|
|
737
747
|
const method = event.httpMethod || event.requestContext?.http?.method || "POST";
|
|
738
748
|
const forwardedProto = event.headers?.["x-forwarded-proto"] ?? event.headers?.["X-Forwarded-Proto"];
|
|
739
749
|
const protocol = forwardedProto ?? "https";
|
|
@@ -741,9 +751,9 @@ function fromLambdaEvent(event) {
|
|
|
741
751
|
const queryString = event.queryStringParameters ? "?" + new URLSearchParams(
|
|
742
752
|
event.queryStringParameters
|
|
743
753
|
).toString() : "";
|
|
744
|
-
const url = `${protocol}://${host}${
|
|
754
|
+
const url = `${protocol}://${host}${path4}${queryString}`;
|
|
745
755
|
return {
|
|
746
|
-
path:
|
|
756
|
+
path: path4,
|
|
747
757
|
method,
|
|
748
758
|
headers: event.headers,
|
|
749
759
|
query: event.queryStringParameters ?? {},
|
|
@@ -825,8 +835,8 @@ function parseBodyByContentType(req) {
|
|
|
825
835
|
}
|
|
826
836
|
|
|
827
837
|
// src/server/route-handlers/handlers.ts
|
|
828
|
-
var
|
|
829
|
-
var
|
|
838
|
+
var fs3 = __toESM(require("fs"));
|
|
839
|
+
var path3 = __toESM(require("path"));
|
|
830
840
|
|
|
831
841
|
// src/server/core-api-handler.ts
|
|
832
842
|
async function handleCoreMethod(method, params) {
|
|
@@ -1293,8 +1303,13 @@ async function handleOAuthCallback(parsedBody, hooks) {
|
|
|
1293
1303
|
}
|
|
1294
1304
|
}
|
|
1295
1305
|
|
|
1306
|
+
// src/types/webhook.ts
|
|
1307
|
+
function isRuntimeWebhookContext(ctx) {
|
|
1308
|
+
return "appInstallationId" in ctx && ctx.appInstallationId !== void 0;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1296
1311
|
// src/server/handlers/webhook-handler.ts
|
|
1297
|
-
function parseWebhookRequest(parsedBody, method, url,
|
|
1312
|
+
function parseWebhookRequest(parsedBody, method, url, path4, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
|
|
1298
1313
|
const isEnvelope = typeof parsedBody === "object" && parsedBody !== null && "env" in parsedBody && "request" in parsedBody && "context" in parsedBody;
|
|
1299
1314
|
if (isEnvelope) {
|
|
1300
1315
|
const envelope = parsedBody;
|
|
@@ -1348,7 +1363,7 @@ function parseWebhookRequest(parsedBody, method, url, path3, headers, query, raw
|
|
|
1348
1363
|
const webhookRequest = {
|
|
1349
1364
|
method,
|
|
1350
1365
|
url,
|
|
1351
|
-
path:
|
|
1366
|
+
path: path4,
|
|
1352
1367
|
headers,
|
|
1353
1368
|
query,
|
|
1354
1369
|
body: parsedBody,
|
|
@@ -1377,9 +1392,17 @@ async function executeWebhookHandler(handle, webhookRegistry, data) {
|
|
|
1377
1392
|
};
|
|
1378
1393
|
let webhookResponse;
|
|
1379
1394
|
try {
|
|
1395
|
+
const rateLimitContext = {
|
|
1396
|
+
app: data.webhookContext.app,
|
|
1397
|
+
appInstallationId: isRuntimeWebhookContext(data.webhookContext) ? data.webhookContext.appInstallationId : void 0,
|
|
1398
|
+
invocation: data.invocation,
|
|
1399
|
+
isProvisionContext: !isRuntimeWebhookContext(data.webhookContext)
|
|
1400
|
+
};
|
|
1380
1401
|
webhookResponse = await runWithLogContext({ invocation: data.invocation }, async () => {
|
|
1381
1402
|
return await runWithConfig(requestConfig, async () => {
|
|
1382
|
-
return await
|
|
1403
|
+
return await runWithRateLimitExecutionContext(rateLimitContext, async () => {
|
|
1404
|
+
return await webhookDef.handler(data.webhookRequest, data.webhookContext);
|
|
1405
|
+
});
|
|
1383
1406
|
});
|
|
1384
1407
|
});
|
|
1385
1408
|
} catch (err) {
|
|
@@ -1406,7 +1429,7 @@ function isMethodAllowed(webhookRegistry, handle, method) {
|
|
|
1406
1429
|
|
|
1407
1430
|
// src/server/route-handlers/handlers.ts
|
|
1408
1431
|
function getConfigFilePath() {
|
|
1409
|
-
return process.env.LAMBDA_TASK_ROOT ?
|
|
1432
|
+
return process.env.LAMBDA_TASK_ROOT ? path3.join(process.env.LAMBDA_TASK_ROOT, ".skedyul", "config.json") : ".skedyul/config.json";
|
|
1410
1433
|
}
|
|
1411
1434
|
function findToolInRegistry(registry, toolName) {
|
|
1412
1435
|
for (const [key, t] of Object.entries(registry)) {
|
|
@@ -1445,8 +1468,8 @@ function handleHealthRoute(ctx) {
|
|
|
1445
1468
|
function handleConfigRoute(ctx) {
|
|
1446
1469
|
const configFilePath = getConfigFilePath();
|
|
1447
1470
|
try {
|
|
1448
|
-
if (
|
|
1449
|
-
const fileConfig = JSON.parse(
|
|
1471
|
+
if (fs3.existsSync(configFilePath)) {
|
|
1472
|
+
const fileConfig = JSON.parse(fs3.readFileSync(configFilePath, "utf-8"));
|
|
1450
1473
|
return { status: 200, body: fileConfig };
|
|
1451
1474
|
}
|
|
1452
1475
|
} catch (err) {
|
|
@@ -2134,6 +2157,7 @@ installContextLogger();
|
|
|
2134
2157
|
function createSkedyulServer(config) {
|
|
2135
2158
|
mergeRuntimeEnv();
|
|
2136
2159
|
registerQueueConfig(config);
|
|
2160
|
+
registerSequencerConfig(config);
|
|
2137
2161
|
const registry = config.tools;
|
|
2138
2162
|
const webhookRegistry = config.webhooks;
|
|
2139
2163
|
if (config.coreApi?.service) {
|
|
@@ -58,6 +58,16 @@ function registerQueueConfig(config) {
|
|
|
58
58
|
cachedRuntimeQueues = config.queues ?? null;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// src/sequencer/config-loader.ts
|
|
62
|
+
import * as fs2 from "fs";
|
|
63
|
+
import * as path2 from "path";
|
|
64
|
+
var cachedRuntimeSequencers = null;
|
|
65
|
+
var registeredServerConfig2 = null;
|
|
66
|
+
function registerSequencerConfig(config) {
|
|
67
|
+
registeredServerConfig2 = config;
|
|
68
|
+
cachedRuntimeSequencers = config.sequencers ?? null;
|
|
69
|
+
}
|
|
70
|
+
|
|
61
71
|
// src/server/utils/schema.ts
|
|
62
72
|
import * as z from "zod";
|
|
63
73
|
function normalizeBilling(billing) {
|
|
@@ -694,7 +704,7 @@ function printStartupLog(config, tools, port) {
|
|
|
694
704
|
|
|
695
705
|
// src/server/route-handlers/adapters.ts
|
|
696
706
|
function fromLambdaEvent(event) {
|
|
697
|
-
const
|
|
707
|
+
const path4 = event.path || event.rawPath || "/";
|
|
698
708
|
const method = event.httpMethod || event.requestContext?.http?.method || "POST";
|
|
699
709
|
const forwardedProto = event.headers?.["x-forwarded-proto"] ?? event.headers?.["X-Forwarded-Proto"];
|
|
700
710
|
const protocol = forwardedProto ?? "https";
|
|
@@ -702,9 +712,9 @@ function fromLambdaEvent(event) {
|
|
|
702
712
|
const queryString = event.queryStringParameters ? "?" + new URLSearchParams(
|
|
703
713
|
event.queryStringParameters
|
|
704
714
|
).toString() : "";
|
|
705
|
-
const url = `${protocol}://${host}${
|
|
715
|
+
const url = `${protocol}://${host}${path4}${queryString}`;
|
|
706
716
|
return {
|
|
707
|
-
path:
|
|
717
|
+
path: path4,
|
|
708
718
|
method,
|
|
709
719
|
headers: event.headers,
|
|
710
720
|
query: event.queryStringParameters ?? {},
|
|
@@ -786,8 +796,8 @@ function parseBodyByContentType(req) {
|
|
|
786
796
|
}
|
|
787
797
|
|
|
788
798
|
// src/server/route-handlers/handlers.ts
|
|
789
|
-
import * as
|
|
790
|
-
import * as
|
|
799
|
+
import * as fs3 from "fs";
|
|
800
|
+
import * as path3 from "path";
|
|
791
801
|
|
|
792
802
|
// src/server/core-api-handler.ts
|
|
793
803
|
async function handleCoreMethod(method, params) {
|
|
@@ -1254,8 +1264,13 @@ async function handleOAuthCallback(parsedBody, hooks) {
|
|
|
1254
1264
|
}
|
|
1255
1265
|
}
|
|
1256
1266
|
|
|
1267
|
+
// src/types/webhook.ts
|
|
1268
|
+
function isRuntimeWebhookContext(ctx) {
|
|
1269
|
+
return "appInstallationId" in ctx && ctx.appInstallationId !== void 0;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1257
1272
|
// src/server/handlers/webhook-handler.ts
|
|
1258
|
-
function parseWebhookRequest(parsedBody, method, url,
|
|
1273
|
+
function parseWebhookRequest(parsedBody, method, url, path4, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
|
|
1259
1274
|
const isEnvelope = typeof parsedBody === "object" && parsedBody !== null && "env" in parsedBody && "request" in parsedBody && "context" in parsedBody;
|
|
1260
1275
|
if (isEnvelope) {
|
|
1261
1276
|
const envelope = parsedBody;
|
|
@@ -1309,7 +1324,7 @@ function parseWebhookRequest(parsedBody, method, url, path3, headers, query, raw
|
|
|
1309
1324
|
const webhookRequest = {
|
|
1310
1325
|
method,
|
|
1311
1326
|
url,
|
|
1312
|
-
path:
|
|
1327
|
+
path: path4,
|
|
1313
1328
|
headers,
|
|
1314
1329
|
query,
|
|
1315
1330
|
body: parsedBody,
|
|
@@ -1338,9 +1353,17 @@ async function executeWebhookHandler(handle, webhookRegistry, data) {
|
|
|
1338
1353
|
};
|
|
1339
1354
|
let webhookResponse;
|
|
1340
1355
|
try {
|
|
1356
|
+
const rateLimitContext = {
|
|
1357
|
+
app: data.webhookContext.app,
|
|
1358
|
+
appInstallationId: isRuntimeWebhookContext(data.webhookContext) ? data.webhookContext.appInstallationId : void 0,
|
|
1359
|
+
invocation: data.invocation,
|
|
1360
|
+
isProvisionContext: !isRuntimeWebhookContext(data.webhookContext)
|
|
1361
|
+
};
|
|
1341
1362
|
webhookResponse = await runWithLogContext({ invocation: data.invocation }, async () => {
|
|
1342
1363
|
return await runWithConfig(requestConfig, async () => {
|
|
1343
|
-
return await
|
|
1364
|
+
return await runWithRateLimitExecutionContext(rateLimitContext, async () => {
|
|
1365
|
+
return await webhookDef.handler(data.webhookRequest, data.webhookContext);
|
|
1366
|
+
});
|
|
1344
1367
|
});
|
|
1345
1368
|
});
|
|
1346
1369
|
} catch (err) {
|
|
@@ -1367,7 +1390,7 @@ function isMethodAllowed(webhookRegistry, handle, method) {
|
|
|
1367
1390
|
|
|
1368
1391
|
// src/server/route-handlers/handlers.ts
|
|
1369
1392
|
function getConfigFilePath() {
|
|
1370
|
-
return process.env.LAMBDA_TASK_ROOT ?
|
|
1393
|
+
return process.env.LAMBDA_TASK_ROOT ? path3.join(process.env.LAMBDA_TASK_ROOT, ".skedyul", "config.json") : ".skedyul/config.json";
|
|
1371
1394
|
}
|
|
1372
1395
|
function findToolInRegistry(registry, toolName) {
|
|
1373
1396
|
for (const [key, t] of Object.entries(registry)) {
|
|
@@ -1406,8 +1429,8 @@ function handleHealthRoute(ctx) {
|
|
|
1406
1429
|
function handleConfigRoute(ctx) {
|
|
1407
1430
|
const configFilePath = getConfigFilePath();
|
|
1408
1431
|
try {
|
|
1409
|
-
if (
|
|
1410
|
-
const fileConfig = JSON.parse(
|
|
1432
|
+
if (fs3.existsSync(configFilePath)) {
|
|
1433
|
+
const fileConfig = JSON.parse(fs3.readFileSync(configFilePath, "utf-8"));
|
|
1411
1434
|
return { status: 200, body: fileConfig };
|
|
1412
1435
|
}
|
|
1413
1436
|
} catch (err) {
|
|
@@ -2095,6 +2118,7 @@ installContextLogger();
|
|
|
2095
2118
|
function createSkedyulServer(config) {
|
|
2096
2119
|
mergeRuntimeEnv();
|
|
2097
2120
|
registerQueueConfig(config);
|
|
2121
|
+
registerSequencerConfig(config);
|
|
2098
2122
|
const registry = config.tools;
|
|
2099
2123
|
const webhookRegistry = config.webhooks;
|
|
2100
2124
|
if (config.coreApi?.service) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skedyul",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "The Skedyul SDK for Node.js",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"build": "rm -rf dist tsconfig.tsbuildinfo && tsc --emitDeclarationOnly && pnpm exec tsup-node",
|
|
77
77
|
"db:generate": "echo 'No database generation needed for this package'",
|
|
78
78
|
"dev": "npx nodemon --watch src --ext js,ts --exec \"pnpm run build\"",
|
|
79
|
-
"test": "tsc --project tsconfig.tests.json && node --test dist-tests/tests/server.test.js dist-tests/tests/cli.test.js dist-tests/tests/agent-schema-v3.test.js dist-tests/tests/ratelimit.test.js dist-tests/tests/config-loader.test.js dist-tests/tests/gsm7.test.js"
|
|
79
|
+
"test": "tsc --project tsconfig.tests.json && node --test dist-tests/tests/server.test.js dist-tests/tests/cli.test.js dist-tests/tests/agent-schema-v3.test.js dist-tests/tests/ratelimit.test.js dist-tests/tests/sequencer.test.js dist-tests/tests/config-loader.test.js dist-tests/tests/gsm7.test.js"
|
|
80
80
|
},
|
|
81
81
|
"keywords": [
|
|
82
82
|
"mcp",
|