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
|
@@ -9,7 +9,9 @@ import type { CoreApiConfig } from '../core/types';
|
|
|
9
9
|
import type { EnvSchema, ComputeLayer, ModelDefinition, RelationshipDefinition, ChannelDefinition, WorkflowDefinition, PageDefinition, NavigationConfig, AgentDefinition, SignalDefinition } from './types';
|
|
10
10
|
import type { AppEventDefinition } from './types/app-event';
|
|
11
11
|
import type { QueueRegistry, SerializableQueueConfig } from './queue-config';
|
|
12
|
+
import type { SequencerRegistry, SerializableSequencerConfig } from './sequencer-config';
|
|
12
13
|
export type { QueueScope, QueueConfig, SerializableQueueConfig, QueueRegistry, } from './queue-config';
|
|
14
|
+
export type { SequencerScope, SerializableSequencerConfig, SequencerRegistry, } from './sequencer-config';
|
|
13
15
|
/**
|
|
14
16
|
* Install configuration - defines per-install env vars and SHARED models.
|
|
15
17
|
* This is configured by users during app installation.
|
|
@@ -109,6 +111,8 @@ export interface SkedyulConfig {
|
|
|
109
111
|
build?: BuildConfig;
|
|
110
112
|
/** Rate-limit queue definitions for queuedFetch */
|
|
111
113
|
queues?: QueueRegistry;
|
|
114
|
+
/** Sequencer definitions for timestamp-aware ordering and short-lived locks */
|
|
115
|
+
sequencers?: SequencerRegistry;
|
|
112
116
|
}
|
|
113
117
|
/**
|
|
114
118
|
* Serializable config (for database storage).
|
|
@@ -131,6 +135,8 @@ export interface SerializableSkedyulConfig {
|
|
|
131
135
|
events?: AppEventDefinition[];
|
|
132
136
|
/** Rate-limit queue definitions */
|
|
133
137
|
queues?: Record<string, SerializableQueueConfig>;
|
|
138
|
+
/** Sequencer definitions */
|
|
139
|
+
sequencers?: Record<string, SerializableSequencerConfig>;
|
|
134
140
|
}
|
|
135
141
|
/**
|
|
136
142
|
* Define a Skedyul app configuration with full type safety.
|
package/dist/config/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - All definition types extend BaseDefinition
|
|
10
10
|
*/
|
|
11
11
|
export * from './types';
|
|
12
|
-
export type { InstallConfig, ProvisionConfig, BuildConfig, CorsOptions, SkedyulConfig, SerializableSkedyulConfig, QueueScope, QueueConfig, SerializableQueueConfig, QueueRegistry, } from './app-config';
|
|
12
|
+
export type { InstallConfig, ProvisionConfig, BuildConfig, CorsOptions, SkedyulConfig, SerializableSkedyulConfig, QueueScope, QueueConfig, SerializableQueueConfig, QueueRegistry, SequencerScope, SerializableSequencerConfig, SequencerRegistry, } from './app-config';
|
|
13
13
|
export { defineConfig } from './app-config';
|
|
14
14
|
export { defineModel, defineChannel, definePage, defineWorkflow, defineAgent, defineEnv, defineNavigation, } from './define';
|
|
15
15
|
export { SCHEMA_FILE_EXTENSIONS, loadSchema, saveSchema, serializeSchemaToJson, serializeSchemaToTypeScript, transformToBackendSchema, transformFromBackendSchema, type LoadSchemaOptions, type LoadSchemaResult, type SerializeSchemaOptions, type BackendModelDefinition, type BackendFieldDefinition, type BackendRelationshipDefinition, type BackendDesiredSchema, } from './schema-loader';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sequencer configuration for skedyul.config sequencers.
|
|
3
|
+
*/
|
|
4
|
+
import type { QueueScope } from './queue-config';
|
|
5
|
+
export type SequencerScope = QueueScope;
|
|
6
|
+
/**
|
|
7
|
+
* Serializable sequencer config (stored in DB / .skedyul/config.json).
|
|
8
|
+
*/
|
|
9
|
+
export interface SerializableSequencerConfig {
|
|
10
|
+
scope: SequencerScope;
|
|
11
|
+
/** Override endpoint handle for provision_endpoint / install_endpoint scopes */
|
|
12
|
+
endpoint?: string;
|
|
13
|
+
/** Opt-in per named sequencer (default false) */
|
|
14
|
+
enabled?: boolean;
|
|
15
|
+
/** Lock TTL for acquire() — default 60_000 ms */
|
|
16
|
+
lockTtlMs?: number;
|
|
17
|
+
/** Watermark key TTL in Redis — default 7 days */
|
|
18
|
+
watermarkTtlMs?: number;
|
|
19
|
+
}
|
|
20
|
+
export type SequencerRegistry = Record<string, SerializableSequencerConfig>;
|
|
@@ -160,6 +160,8 @@ export interface ModelDefinition extends BaseDefinition {
|
|
|
160
160
|
addNavigation?: boolean;
|
|
161
161
|
/** Root path for developer resource UI (e.g., '/access_requests'). Links internal model to a provision.pages entry. */
|
|
162
162
|
page?: string;
|
|
163
|
+
/** Encrypted env vars scoped to each instance of this internal model */
|
|
164
|
+
env?: import('./env').EnvSchema;
|
|
163
165
|
}
|
|
164
166
|
/**
|
|
165
167
|
* One side of a relationship link.
|
package/dist/core/client.d.ts
CHANGED
|
@@ -255,9 +255,27 @@ export interface InstanceData {
|
|
|
255
255
|
id: string;
|
|
256
256
|
/** The app installation this instance belongs to (if any) */
|
|
257
257
|
appInstallationId?: string | null;
|
|
258
|
+
/** Encrypted env vars for this instance (only when requested via includeEnv) */
|
|
259
|
+
env?: Record<string, string>;
|
|
258
260
|
_meta: InstanceMeta;
|
|
259
261
|
[fieldHandle: string]: unknown;
|
|
260
262
|
}
|
|
263
|
+
export type InstanceEnv = Record<string, string>;
|
|
264
|
+
export interface InstanceWriteOptions {
|
|
265
|
+
env?: InstanceEnv;
|
|
266
|
+
}
|
|
267
|
+
export interface InstanceGetOptions {
|
|
268
|
+
includeEnv?: boolean;
|
|
269
|
+
}
|
|
270
|
+
export type InstanceCreateManyItem = Record<string, unknown> | {
|
|
271
|
+
data: Record<string, unknown>;
|
|
272
|
+
env?: InstanceEnv;
|
|
273
|
+
};
|
|
274
|
+
export type InstanceUpdateManyItem = {
|
|
275
|
+
id: string;
|
|
276
|
+
data: Record<string, unknown>;
|
|
277
|
+
env?: InstanceEnv;
|
|
278
|
+
};
|
|
261
279
|
/**
|
|
262
280
|
* Result from instance.list().
|
|
263
281
|
*/
|
|
@@ -282,9 +300,9 @@ export interface InstanceListArgs {
|
|
|
282
300
|
*/
|
|
283
301
|
export interface InstanceClient {
|
|
284
302
|
list(modelHandle: string, args?: InstanceListArgs): Promise<InstanceListResult>;
|
|
285
|
-
get(modelHandle: string, id: string): Promise<InstanceData | null>;
|
|
286
|
-
create(modelHandle: string, data: Record<string, unknown
|
|
287
|
-
update(modelHandle: string, id: string, data: Record<string, unknown
|
|
303
|
+
get(modelHandle: string, id: string, options?: InstanceGetOptions): Promise<InstanceData | null>;
|
|
304
|
+
create(modelHandle: string, data: Record<string, unknown>, options?: InstanceWriteOptions): Promise<InstanceData>;
|
|
305
|
+
update(modelHandle: string, id: string, data: Record<string, unknown>, options?: InstanceWriteOptions): Promise<InstanceData>;
|
|
288
306
|
delete(modelHandle: string, id: string): Promise<{
|
|
289
307
|
deleted: boolean;
|
|
290
308
|
}>;
|
|
@@ -299,17 +317,14 @@ export interface InstanceClient {
|
|
|
299
317
|
error: string;
|
|
300
318
|
}>;
|
|
301
319
|
}>;
|
|
302
|
-
createMany(modelHandle: string, items:
|
|
320
|
+
createMany(modelHandle: string, items: InstanceCreateManyItem[]): Promise<{
|
|
303
321
|
created: InstanceData[];
|
|
304
322
|
errors: Array<{
|
|
305
323
|
index: number;
|
|
306
324
|
error: string;
|
|
307
325
|
}>;
|
|
308
326
|
}>;
|
|
309
|
-
updateMany(modelHandle: string, items:
|
|
310
|
-
id: string;
|
|
311
|
-
data: Record<string, unknown>;
|
|
312
|
-
}>): Promise<{
|
|
327
|
+
updateMany(modelHandle: string, items: InstanceUpdateManyItem[]): Promise<{
|
|
313
328
|
updated: InstanceData[];
|
|
314
329
|
errors: Array<{
|
|
315
330
|
index: number;
|
package/dist/dedicated/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) {
|