@friggframework/core 2.0.0--canary.686.3e27a92.0 → 2.0.0--canary.663.8de669c.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/CLAUDE.md +0 -28
- package/README.md +0 -105
- package/application/commands/integration-commands.js +10 -20
- package/application/commands/scheduler-commands.js +7 -11
- package/application/commands/user-commands.js +5 -17
- package/application/index.js +2 -6
- package/core/Worker.js +7 -31
- package/core/create-handler.js +0 -9
- package/credential/repositories/credential-repository-documentdb.js +0 -34
- package/credential/repositories/credential-repository-interface.js +0 -15
- package/credential/repositories/credential-repository-mongo.js +0 -23
- package/credential/repositories/credential-repository-postgres.js +0 -28
- package/database/config.js +24 -48
- package/database/documentdb-utils.js +1 -6
- package/database/encryption/encryption-config.js +31 -10
- package/database/encryption/encryption-schema-registry.js +12 -93
- package/database/prisma.js +2 -4
- package/generated/prisma-mongodb/edge.js +4 -43
- package/generated/prisma-mongodb/index-browser.js +1 -40
- package/generated/prisma-mongodb/index.d.ts +111 -4739
- package/generated/prisma-mongodb/index.js +4 -43
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/schema.prisma +0 -92
- package/generated/prisma-mongodb/wasm.js +4 -43
- package/generated/prisma-postgresql/edge.js +4 -43
- package/generated/prisma-postgresql/index-browser.js +1 -40
- package/generated/prisma-postgresql/index.d.ts +33 -4966
- package/generated/prisma-postgresql/index.js +4 -43
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/schema.prisma +0 -87
- package/generated/prisma-postgresql/wasm.js +4 -43
- package/handlers/app-definition-loader.js +19 -121
- package/handlers/app-handler-helpers.js +3 -25
- package/handlers/backend-utils.js +25 -31
- package/handlers/middleware/admin-auth.js +1 -14
- package/handlers/routers/auth.js +10 -46
- package/handlers/routers/health.js +4 -13
- package/handlers/routers/integration-defined-routers.js +92 -144
- package/handlers/routers/integration-webhook-routers.js +64 -102
- package/handlers/workers/integration-defined-workers.js +2 -5
- package/index.js +1 -65
- package/infrastructure/scheduler/index.js +6 -19
- package/infrastructure/scheduler/scheduler-service-factory.js +7 -55
- package/integrations/index.js +0 -1
- package/integrations/integration-router.js +96 -131
- package/integrations/repositories/integration-repository-documentdb.js +3 -35
- package/integrations/repositories/integration-repository-interface.js +1 -17
- package/integrations/repositories/integration-repository-mongo.js +76 -59
- package/integrations/repositories/integration-repository-postgres.js +76 -62
- package/integrations/tests/doubles/test-integration-repository.js +1 -12
- package/integrations/use-cases/create-integration.js +20 -55
- package/integrations/use-cases/get-integrations-for-user.js +40 -80
- package/integrations/use-cases/index.js +1 -7
- package/integrations/utils/map-integration-dto.js +14 -43
- package/modules/index.js +0 -14
- package/modules/module-factory.js +0 -12
- package/modules/module.js +2 -53
- package/modules/repositories/module-repository-documentdb.js +6 -51
- package/modules/repositories/module-repository-interface.js +2 -19
- package/modules/repositories/module-repository-mongo.js +74 -67
- package/modules/repositories/module-repository-postgres.js +74 -66
- package/modules/repositories/module-repository.js +1 -2
- package/modules/requester/requester.js +2 -27
- package/modules/use-cases/get-entities-for-user.js +13 -26
- package/modules/use-cases/get-entity-options-by-id.js +4 -10
- package/modules/use-cases/get-entity-options-by-type.js +1 -1
- package/modules/use-cases/get-module-instance-from-type.js +1 -1
- package/modules/use-cases/get-module.js +4 -10
- package/modules/use-cases/process-authorization-callback.js +19 -53
- package/modules/use-cases/refresh-entity-options.js +4 -10
- package/modules/use-cases/test-module-auth.js +4 -10
- package/package.json +5 -6
- package/prisma-mongodb/schema.prisma +0 -92
- package/prisma-postgresql/schema.prisma +0 -87
- package/queues/index.js +0 -25
- package/types/index.d.ts +0 -2
- package/user/repositories/user-repository-documentdb.js +2 -27
- package/user/repositories/user-repository-interface.js +0 -18
- package/user/repositories/user-repository-mongo.js +0 -24
- package/user/repositories/user-repository-postgres.js +0 -18
- package/user/use-cases/authenticate-user.js +1 -7
- package/user/use-cases/get-user-from-adopter-jwt.js +124 -95
- package/user/use-cases/get-user-from-x-frigg-headers.js +80 -83
- package/user/user.js +1 -64
- package/credential/use-cases/credential-operations-for-user.js +0 -202
- package/credential/use-cases/reauthorize-credential-for-user.js +0 -73
- package/database/organization-where.js +0 -18
- package/database/unique-violation.js +0 -25
- package/extensions/bootstrap-runner.js +0 -43
- package/extensions/extension-loader.js +0 -187
- package/extensions/index.js +0 -41
- package/extensions/initialize-app.js +0 -123
- package/extensions/route-mounter.js +0 -103
- package/extensions/schema-composer.js +0 -188
- package/infrastructure/scheduler/netlify-scheduler-adapter.js +0 -216
- package/infrastructure/scheduler/scheduled-job-repository.js +0 -118
- package/integrations/repositories/integration-not-found.js +0 -14
- package/integrations/schedule-config.js +0 -80
- package/integrations/use-cases/dispatch-ongoing-syncs.js +0 -100
- package/integrations/use-cases/integration-operations-for-user.js +0 -256
- package/integrations/use-cases/resolve-integration-ownership.js +0 -177
- package/management-api/create-management-api-router.js +0 -49
- package/management-api/error-response.js +0 -116
- package/management-api/management-api-config.js +0 -151
- package/management-api/meta-router.js +0 -76
- package/management-api/openapi/build-openapi.js +0 -144
- package/management-api/openapi/components.js +0 -408
- package/management-api/openapi/v1-operations.js +0 -83
- package/management-api/openapi/v2-operations.js +0 -264
- package/management-api/route-registry.js +0 -411
- package/management-api/test-support/http-client.js +0 -39
- package/management-api/use-cases/get-management-api-meta.js +0 -57
- package/management-api/v1-deprecation.js +0 -120
- package/management-api/v2/create-v2-router.js +0 -85
- package/management-api/v2/dependencies.js +0 -281
- package/management-api/v2/dto.js +0 -143
- package/management-api/v2/handlers/authorization.js +0 -94
- package/management-api/v2/handlers/credentials.js +0 -33
- package/management-api/v2/handlers/entities.js +0 -77
- package/management-api/v2/handlers/integrations.js +0 -128
- package/management-api/v2/handlers/proxy.js +0 -34
- package/management-api/v2/request.js +0 -85
- package/management-api/v2/test-support/fake-dependencies.js +0 -103
- package/modules/domain/authorization-session.js +0 -144
- package/modules/entity-scope.js +0 -15
- package/modules/entity-type-registry.js +0 -311
- package/modules/proxy/proxy-errors.js +0 -20
- package/modules/proxy/proxy-path.js +0 -179
- package/modules/proxy/proxy-policy.js +0 -248
- package/modules/repositories/authorization-session-repository-documentdb.js +0 -112
- package/modules/repositories/authorization-session-repository-factory.js +0 -31
- package/modules/repositories/authorization-session-repository-interface.js +0 -47
- package/modules/repositories/authorization-session-repository-prisma.js +0 -87
- package/modules/repositories/entity-not-found.js +0 -18
- package/modules/requester/proxy-request.js +0 -244
- package/modules/scope-config.js +0 -192
- package/modules/scope-policy.js +0 -112
- package/modules/scope-resolution.js +0 -288
- package/modules/scope-visibility.js +0 -247
- package/modules/tests/doubles/in-memory-authorization-session-repository.js +0 -45
- package/modules/tests/doubles/ownership-matching.js +0 -18
- package/modules/use-cases/authorize-entity-for-user.js +0 -61
- package/modules/use-cases/create-entity-from-credential.js +0 -113
- package/modules/use-cases/entity-operations-for-user.js +0 -162
- package/modules/use-cases/entity-types.js +0 -139
- package/modules/use-cases/execute-entity-proxy-request.js +0 -286
- package/modules/use-cases/get-authorization-requirements.js +0 -100
- package/modules/use-cases/get-entity-module-for-user.js +0 -113
- package/modules/use-cases/manage-access.js +0 -21
- package/modules/use-cases/multi-step-authorization.js +0 -329
- package/prisma-postgresql/migrations/20261003000000_add_authorization_session/migration.sql +0 -28
- package/prisma-postgresql/migrations/20261015000000_add_organization_membership/migration.sql +0 -26
- package/prisma-postgresql/migrations/20261016000000_add_entity_integration_organization/migration.sql +0 -25
- package/prisma-postgresql/migrations/20261017000000_add_scheduled_job/migration.sql +0 -28
- package/providers/index.js +0 -23
- package/providers/resolve-provider.js +0 -93
- package/providers/runtime-detection.js +0 -124
- package/queues/providers/index.js +0 -11
- package/queues/providers/netlify-background-provider.js +0 -150
- package/queues/providers/qstash-queue-provider.js +0 -219
- package/queues/providers/sqs-queue-provider.js +0 -70
- package/queues/queue-client-interface.js +0 -55
- package/queues/queue-message-auth.js +0 -193
- package/queues/queue-provider-factory.js +0 -101
- package/queues/queue-provider.js +0 -65
- package/queues/sqs-queue-client.js +0 -81
- package/types/modules/index.d.ts +0 -197
- package/types/user/index.d.ts +0 -134
- package/user/adopter-jwt-config.js +0 -177
- package/user/adopter-jwt-errors.js +0 -59
- package/user/adopter-token-verifier.js +0 -122
- package/user/app-user-helpers.js +0 -97
- package/user/create-user-authentication.js +0 -64
- package/user/membership.js +0 -51
- package/user/repositories/organization-membership-record.js +0 -19
- package/user/repositories/organization-membership-repository-documentdb.js +0 -106
- package/user/repositories/organization-membership-repository-factory.js +0 -42
- package/user/repositories/organization-membership-repository-interface.js +0 -57
- package/user/repositories/organization-membership-repository-mongo.js +0 -13
- package/user/repositories/organization-membership-repository-postgres.js +0 -29
- package/user/repositories/organization-membership-repository-prisma.js +0 -81
- package/user/tests/doubles/adopter-jwt-fixtures.js +0 -220
- package/user/use-cases/ensure-organization-membership.js +0 -92
- package/user/use-cases/find-individual-users-by-organization.js +0 -54
|
@@ -6,120 +6,82 @@ const {
|
|
|
6
6
|
IntegrationEventDispatcher,
|
|
7
7
|
} = require('../integration-event-dispatcher');
|
|
8
8
|
|
|
9
|
+
const handlers = {};
|
|
10
|
+
const { integrations: integrationClasses } = loadAppDefinition();
|
|
11
|
+
|
|
9
12
|
// `webhooks.received` is counted at the DB-connected ON_WEBHOOK dispatch (see
|
|
10
13
|
// usage-rollup-subscriber), not in this DB-free receipt handler.
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* enabled. Pure: no handler wrapping, so the AWS handlers below and other
|
|
15
|
-
* hosts (provider-netlify's webhooks function) mount the same routers.
|
|
16
|
-
*
|
|
17
|
-
* @param {Array<Function>} integrationClasses
|
|
18
|
-
* @returns {Array<{ key: string, eventName: string, router: import('express').Router }>}
|
|
19
|
-
*/
|
|
20
|
-
function buildWebhookRouters(integrationClasses) {
|
|
21
|
-
const entries = [];
|
|
22
|
-
for (const IntegrationClass of integrationClasses) {
|
|
23
|
-
const webhookConfig = IntegrationClass.Definition.webhooks;
|
|
24
|
-
|
|
25
|
-
// Skip if webhooks not enabled
|
|
26
|
-
if (
|
|
27
|
-
!webhookConfig ||
|
|
28
|
-
(typeof webhookConfig === 'object' && !webhookConfig.enabled)
|
|
29
|
-
) {
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const router = Router();
|
|
34
|
-
const basePath = `/api/${IntegrationClass.Definition.name}-integration/webhooks`;
|
|
15
|
+
for (const IntegrationClass of integrationClasses) {
|
|
16
|
+
const webhookConfig = IntegrationClass.Definition.webhooks;
|
|
35
17
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
18
|
+
// Skip if webhooks not enabled
|
|
19
|
+
if (
|
|
20
|
+
!webhookConfig ||
|
|
21
|
+
(typeof webhookConfig === 'object' && !webhookConfig.enabled)
|
|
22
|
+
) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
39
25
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const integrationInstance = new IntegrationClass();
|
|
44
|
-
const dispatcher = new IntegrationEventDispatcher(
|
|
45
|
-
integrationInstance
|
|
46
|
-
);
|
|
47
|
-
await dispatcher.dispatchHttp({
|
|
48
|
-
event: 'WEBHOOK_RECEIVED',
|
|
49
|
-
req,
|
|
50
|
-
res,
|
|
51
|
-
next,
|
|
52
|
-
});
|
|
53
|
-
} catch (error) {
|
|
54
|
-
next(error);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
console.log(`│ POST ${basePath}`);
|
|
26
|
+
const router = Router();
|
|
27
|
+
const basePath = `/api/${IntegrationClass.Definition.name}-integration/webhooks`;
|
|
58
28
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const integrationInstance = new IntegrationClass();
|
|
63
|
-
const dispatcher = new IntegrationEventDispatcher(
|
|
64
|
-
integrationInstance
|
|
65
|
-
);
|
|
66
|
-
// Logs only: the id comes from an unauthenticated URL, so it must
|
|
67
|
-
// not reach the telemetry context that drives usage attribution.
|
|
68
|
-
await runInContext(
|
|
69
|
-
{
|
|
70
|
-
[LOGGER_SCOPE_KEY]: {
|
|
71
|
-
integrationId: req.params.integrationId,
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
() =>
|
|
75
|
-
dispatcher.dispatchHttp({
|
|
76
|
-
event: 'WEBHOOK_RECEIVED',
|
|
77
|
-
req,
|
|
78
|
-
res,
|
|
79
|
-
next,
|
|
80
|
-
})
|
|
81
|
-
);
|
|
82
|
-
} catch (error) {
|
|
83
|
-
next(error);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
console.log(`│ POST ${basePath}/:integrationId`);
|
|
87
|
-
console.log('│');
|
|
29
|
+
console.log(
|
|
30
|
+
`\n│ Configuring webhook routes for ${IntegrationClass.Definition.name}:`
|
|
31
|
+
);
|
|
88
32
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
33
|
+
// General webhook route (no integration ID)
|
|
34
|
+
router.post(basePath, async (req, res, next) => {
|
|
35
|
+
try {
|
|
36
|
+
const integrationInstance = new IntegrationClass();
|
|
37
|
+
const dispatcher = new IntegrationEventDispatcher(
|
|
38
|
+
integrationInstance
|
|
39
|
+
);
|
|
40
|
+
await dispatcher.dispatchHttp({
|
|
41
|
+
event: 'WEBHOOK_RECEIVED',
|
|
42
|
+
req,
|
|
43
|
+
res,
|
|
44
|
+
next,
|
|
45
|
+
});
|
|
46
|
+
} catch (error) {
|
|
47
|
+
next(error);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
console.log(`│ POST ${basePath}`);
|
|
97
51
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
52
|
+
// Integration-specific webhook route (with integration ID)
|
|
53
|
+
router.post(`${basePath}/:integrationId`, async (req, res, next) => {
|
|
54
|
+
try {
|
|
55
|
+
const integrationInstance = new IntegrationClass();
|
|
56
|
+
const dispatcher = new IntegrationEventDispatcher(
|
|
57
|
+
integrationInstance
|
|
58
|
+
);
|
|
59
|
+
// Logs only: the id comes from an unauthenticated URL, so it must
|
|
60
|
+
// not reach the telemetry context that drives usage attribution.
|
|
61
|
+
await runInContext(
|
|
62
|
+
{ [LOGGER_SCOPE_KEY]: { integrationId: req.params.integrationId } },
|
|
63
|
+
() =>
|
|
64
|
+
dispatcher.dispatchHttp({
|
|
65
|
+
event: 'WEBHOOK_RECEIVED',
|
|
66
|
+
req,
|
|
67
|
+
res,
|
|
68
|
+
next,
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
next(error);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
console.log(`│ POST ${basePath}/:integrationId`);
|
|
76
|
+
console.log('│');
|
|
113
77
|
|
|
114
|
-
|
|
115
|
-
for (const entry of buildWebhookRouters(loadAppDefinition().integrations)) {
|
|
116
|
-
handlers[entry.key] = {
|
|
78
|
+
handlers[`${IntegrationClass.Definition.name}Webhook`] = {
|
|
117
79
|
handler: createAppHandler(
|
|
118
|
-
|
|
119
|
-
|
|
80
|
+
`HTTP Event: ${IntegrationClass.Definition.name} Webhook`,
|
|
81
|
+
router,
|
|
120
82
|
false // shouldUseDatabase = false
|
|
121
83
|
),
|
|
122
84
|
};
|
|
123
85
|
}
|
|
124
86
|
|
|
125
|
-
module.exports = { handlers
|
|
87
|
+
module.exports = { handlers };
|
|
@@ -10,13 +10,10 @@ const { createQueueWorker } = require('../backend-utils');
|
|
|
10
10
|
// const { getExtensionWorkers } = require('../../integrations/extension');
|
|
11
11
|
|
|
12
12
|
const handlers = {};
|
|
13
|
-
const { integrations: integrationClasses
|
|
14
|
-
loadAppDefinition();
|
|
13
|
+
const { integrations: integrationClasses } = loadAppDefinition();
|
|
15
14
|
|
|
16
15
|
integrationClasses.forEach((IntegrationClass) => {
|
|
17
|
-
const defaultQueueWorker = createQueueWorker(IntegrationClass
|
|
18
|
-
moduleDefinitions,
|
|
19
|
-
});
|
|
16
|
+
const defaultQueueWorker = createQueueWorker(IntegrationClass);
|
|
20
17
|
|
|
21
18
|
handlers[`${IntegrationClass.Definition.name}`] = {
|
|
22
19
|
queueWorker: createHandler({
|
package/index.js
CHANGED
|
@@ -25,14 +25,6 @@ const {
|
|
|
25
25
|
UserRepositoryMongo,
|
|
26
26
|
UserRepositoryPostgres,
|
|
27
27
|
} = require('./user/repositories/user-repository-factory');
|
|
28
|
-
const {
|
|
29
|
-
createOrganizationMembershipRepository,
|
|
30
|
-
OrganizationMembershipRepositoryMongo,
|
|
31
|
-
OrganizationMembershipRepositoryPostgres,
|
|
32
|
-
} = require('./user/repositories/organization-membership-repository-factory');
|
|
33
|
-
const {
|
|
34
|
-
EnsureOrganizationMembership,
|
|
35
|
-
} = require('./user/use-cases/ensure-organization-membership');
|
|
36
28
|
const {
|
|
37
29
|
GetUserFromXFriggHeaders,
|
|
38
30
|
} = require('./user/use-cases/get-user-from-x-frigg-headers');
|
|
@@ -107,36 +99,11 @@ const {
|
|
|
107
99
|
Requester,
|
|
108
100
|
ModuleConstants,
|
|
109
101
|
ModuleFactory,
|
|
110
|
-
getEntityTypeRegistry,
|
|
111
|
-
EntityRegistryError,
|
|
112
|
-
resolveScope,
|
|
113
|
-
listBindingScopes,
|
|
114
|
-
OwnershipConfigError,
|
|
115
102
|
} = require('./modules/index');
|
|
116
|
-
const {
|
|
117
|
-
ManagementApiConfigError,
|
|
118
|
-
} = require('./management-api/management-api-config');
|
|
119
103
|
const application = require('./application');
|
|
120
104
|
const utils = require('./utils');
|
|
121
105
|
|
|
122
|
-
const {
|
|
123
|
-
QueuerUtil,
|
|
124
|
-
QueueProvider,
|
|
125
|
-
QueueClientInterface,
|
|
126
|
-
createQueueProvider,
|
|
127
|
-
QUEUE_PROVIDERS,
|
|
128
|
-
} = require('./queues');
|
|
129
|
-
const {
|
|
130
|
-
resolveProvider,
|
|
131
|
-
determineProviderName,
|
|
132
|
-
providerPackageName,
|
|
133
|
-
KNOWN_PROVIDERS,
|
|
134
|
-
isDeployedRuntime,
|
|
135
|
-
} = require('./providers');
|
|
136
|
-
|
|
137
|
-
// App-level core extensions (appDefinition.coreExtensions): Prisma models, encrypted
|
|
138
|
-
// fields, admin routes and bootstrap hooks (friggframework/frigg#545).
|
|
139
|
-
const extensions = require('./extensions');
|
|
106
|
+
const { QueuerUtil } = require('./queues');
|
|
140
107
|
|
|
141
108
|
module.exports = {
|
|
142
109
|
// assertions
|
|
@@ -163,10 +130,6 @@ module.exports = {
|
|
|
163
130
|
createUserRepository,
|
|
164
131
|
UserRepositoryMongo,
|
|
165
132
|
UserRepositoryPostgres,
|
|
166
|
-
createOrganizationMembershipRepository,
|
|
167
|
-
OrganizationMembershipRepositoryMongo,
|
|
168
|
-
OrganizationMembershipRepositoryPostgres,
|
|
169
|
-
EnsureOrganizationMembership,
|
|
170
133
|
GetUserFromXFriggHeaders,
|
|
171
134
|
GetUserFromAdopterJwt,
|
|
172
135
|
AuthenticateUser,
|
|
@@ -187,7 +150,6 @@ module.exports = {
|
|
|
187
150
|
Options,
|
|
188
151
|
checkRequiredParams,
|
|
189
152
|
createIntegrationRouter,
|
|
190
|
-
// Deprecated (ADR-059): use getEntityTypeRegistry.
|
|
191
153
|
getModulesDefinitionFromIntegrationClasses,
|
|
192
154
|
LoadIntegrationContextUseCase,
|
|
193
155
|
CreateProcess,
|
|
@@ -244,34 +206,8 @@ module.exports = {
|
|
|
244
206
|
Requester,
|
|
245
207
|
ModuleConstants,
|
|
246
208
|
ModuleFactory,
|
|
247
|
-
getEntityTypeRegistry,
|
|
248
|
-
EntityRegistryError,
|
|
249
|
-
resolveScope,
|
|
250
|
-
listBindingScopes,
|
|
251
|
-
OwnershipConfigError,
|
|
252
|
-
ManagementApiConfigError,
|
|
253
209
|
// queues
|
|
254
210
|
QueuerUtil,
|
|
255
|
-
QueueProvider,
|
|
256
|
-
QueueClientInterface,
|
|
257
|
-
createQueueProvider,
|
|
258
|
-
QUEUE_PROVIDERS,
|
|
259
|
-
|
|
260
|
-
// provider plugins (appDefinition.provider)
|
|
261
|
-
resolveProvider,
|
|
262
|
-
determineProviderName,
|
|
263
|
-
providerPackageName,
|
|
264
|
-
KNOWN_PROVIDERS,
|
|
265
|
-
isDeployedRuntime,
|
|
266
|
-
|
|
267
|
-
// app-level extensions
|
|
268
|
-
extensions,
|
|
269
|
-
loadExtensions: extensions.loadExtensions,
|
|
270
|
-
composeSchemas: extensions.composeSchemas,
|
|
271
|
-
mountExtensionRoutes: extensions.mountExtensionRoutes,
|
|
272
|
-
createExtensionRoutesRouter: extensions.createExtensionRoutesRouter,
|
|
273
|
-
runExtensionBootstraps: extensions.runExtensionBootstraps,
|
|
274
|
-
initializeApp: extensions.initializeApp,
|
|
275
211
|
|
|
276
212
|
// utils
|
|
277
213
|
...utils,
|
|
@@ -5,19 +5,13 @@
|
|
|
5
5
|
* Follows hexagonal architecture with interface + adapters pattern.
|
|
6
6
|
*
|
|
7
7
|
* Providers:
|
|
8
|
-
* - eventbridge: AWS EventBridge Scheduler (production
|
|
9
|
-
* - netlify: poll-and-dispatch from a Netlify scheduled function
|
|
8
|
+
* - eventbridge: AWS EventBridge Scheduler (production)
|
|
10
9
|
* - mock: In-memory mock scheduler (local development)
|
|
11
|
-
*
|
|
12
|
-
* Adapters are lazy getters (friggframework/frigg#545, 1176a004): the
|
|
13
|
-
* EventBridge adapter requires @aws-sdk/client-scheduler, which is not a
|
|
14
|
-
* core dependency, and core/index -> application -> scheduler-commands ->
|
|
15
|
-
* this barrel runs on every require('@friggframework/core'). An eager
|
|
16
|
-
* require crashed any deployment without that SDK (e.g. a pruned Netlify
|
|
17
|
-
* function bundle).
|
|
18
10
|
*/
|
|
19
11
|
|
|
20
12
|
const { SchedulerServiceInterface } = require('./scheduler-service-interface');
|
|
13
|
+
const { EventBridgeSchedulerAdapter } = require('./eventbridge-scheduler-adapter');
|
|
14
|
+
const { MockSchedulerAdapter } = require('./mock-scheduler-adapter');
|
|
21
15
|
const {
|
|
22
16
|
createSchedulerService,
|
|
23
17
|
SCHEDULER_PROVIDERS,
|
|
@@ -28,16 +22,9 @@ module.exports = {
|
|
|
28
22
|
// Interface (Port)
|
|
29
23
|
SchedulerServiceInterface,
|
|
30
24
|
|
|
31
|
-
// Adapters
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
},
|
|
35
|
-
get MockSchedulerAdapter() {
|
|
36
|
-
return require('./mock-scheduler-adapter').MockSchedulerAdapter;
|
|
37
|
-
},
|
|
38
|
-
get NetlifySchedulerAdapter() {
|
|
39
|
-
return require('./netlify-scheduler-adapter').NetlifySchedulerAdapter;
|
|
40
|
-
},
|
|
25
|
+
// Adapters
|
|
26
|
+
EventBridgeSchedulerAdapter,
|
|
27
|
+
MockSchedulerAdapter,
|
|
41
28
|
|
|
42
29
|
// Factory
|
|
43
30
|
createSchedulerService,
|
|
@@ -7,22 +7,16 @@
|
|
|
7
7
|
* Environment Detection:
|
|
8
8
|
* - SCHEDULER_PROVIDER=eventbridge -> Use AWS EventBridge Scheduler
|
|
9
9
|
* - SCHEDULER_PROVIDER=mock -> Use in-memory mock scheduler
|
|
10
|
-
* - SCHEDULER_PROVIDER=netlify -> Netlify poll-and-dispatch scheduler
|
|
11
|
-
* (friggframework/frigg#545; needs `repository`, usually `queueProvider`)
|
|
12
|
-
* - Default on Netlify (NETLIFY=true, set by the Netlify runtime and build;
|
|
13
|
-
* provider-netlify's generated functions also set SCHEDULER_PROVIDER) -> Netlify
|
|
14
10
|
* - Default in dev/test/local stages -> Mock scheduler
|
|
15
11
|
* - Default in other stages -> EventBridge scheduler
|
|
16
|
-
* - Any other name -> require('@friggframework/provider-<name>').SchedulerAdapter
|
|
17
|
-
*
|
|
18
|
-
* Adapters are required inside their branch so building one never loads
|
|
19
|
-
* another's SDK (@aws-sdk/client-scheduler is not a core dependency).
|
|
20
12
|
*/
|
|
21
13
|
|
|
14
|
+
const { EventBridgeSchedulerAdapter } = require('./eventbridge-scheduler-adapter');
|
|
15
|
+
const { MockSchedulerAdapter } = require('./mock-scheduler-adapter');
|
|
16
|
+
|
|
22
17
|
const SCHEDULER_PROVIDERS = {
|
|
23
18
|
EVENTBRIDGE: 'eventbridge',
|
|
24
19
|
MOCK: 'mock',
|
|
25
|
-
NETLIFY: 'netlify',
|
|
26
20
|
};
|
|
27
21
|
|
|
28
22
|
const LOCAL_STAGES = ['dev', 'test', 'local'];
|
|
@@ -38,12 +32,6 @@ function determineProvider() {
|
|
|
38
32
|
return explicitProvider;
|
|
39
33
|
}
|
|
40
34
|
|
|
41
|
-
// Checked before the stage: a Netlify site with no STAGE (or STAGE=dev)
|
|
42
|
-
// must still persist schedules where scheduled-sync reads them.
|
|
43
|
-
if (process.env.NETLIFY === 'true') {
|
|
44
|
-
return SCHEDULER_PROVIDERS.NETLIFY;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
35
|
const stage = process.env.STAGE || 'dev';
|
|
48
36
|
if (LOCAL_STAGES.includes(stage)) {
|
|
49
37
|
return SCHEDULER_PROVIDERS.MOCK;
|
|
@@ -52,13 +40,6 @@ function determineProvider() {
|
|
|
52
40
|
return SCHEDULER_PROVIDERS.EVENTBRIDGE;
|
|
53
41
|
}
|
|
54
42
|
|
|
55
|
-
function createDefaultScheduledJobRepository() {
|
|
56
|
-
const { ScheduledJobRepository } = require('./scheduled-job-repository');
|
|
57
|
-
// The prisma export is a lazy proxy: nothing connects until a query runs.
|
|
58
|
-
const { prisma } = require('../../database/prisma');
|
|
59
|
-
return new ScheduledJobRepository({ prismaClient: prisma });
|
|
60
|
-
}
|
|
61
|
-
|
|
62
43
|
/**
|
|
63
44
|
* Create a scheduler service instance
|
|
64
45
|
*
|
|
@@ -66,51 +47,22 @@ function createDefaultScheduledJobRepository() {
|
|
|
66
47
|
* @param {string} options.provider - Scheduler provider ('eventbridge' or 'mock')
|
|
67
48
|
* @param {string} options.region - AWS region (for EventBridge)
|
|
68
49
|
* @param {boolean} options.verbose - Verbose logging (for Mock)
|
|
69
|
-
* @param {Object} [options.repository] - Schedule repository (for Netlify: persists schedules)
|
|
70
|
-
* @param {Object} [options.queueProvider] - Queue provider (for Netlify: dispatches due jobs)
|
|
71
50
|
* @returns {SchedulerServiceInterface} Implementation of scheduler interface
|
|
72
51
|
*/
|
|
73
52
|
function createSchedulerService(options = {}) {
|
|
74
53
|
const provider = options.provider || determineProvider();
|
|
75
54
|
|
|
76
55
|
switch (provider) {
|
|
77
|
-
case SCHEDULER_PROVIDERS.EVENTBRIDGE:
|
|
78
|
-
const { EventBridgeSchedulerAdapter } = require('./eventbridge-scheduler-adapter');
|
|
56
|
+
case SCHEDULER_PROVIDERS.EVENTBRIDGE:
|
|
79
57
|
return new EventBridgeSchedulerAdapter({
|
|
80
58
|
region: options.region,
|
|
81
59
|
});
|
|
82
|
-
|
|
83
|
-
case SCHEDULER_PROVIDERS.MOCK: {
|
|
84
|
-
const { MockSchedulerAdapter } = require('./mock-scheduler-adapter');
|
|
60
|
+
case SCHEDULER_PROVIDERS.MOCK:
|
|
85
61
|
return new MockSchedulerAdapter({
|
|
86
62
|
verbose: options.verbose,
|
|
87
63
|
});
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const { NetlifySchedulerAdapter } = require('./netlify-scheduler-adapter');
|
|
91
|
-
return new NetlifySchedulerAdapter({
|
|
92
|
-
// Default: the Prisma ScheduledJob rows that the Netlify
|
|
93
|
-
// scheduled-sync function polls. Without it the adapter
|
|
94
|
-
// falls back to memory, and a schedule made in one function
|
|
95
|
-
// is never seen by the cron.
|
|
96
|
-
repository: options.repository || createDefaultScheduledJobRepository(),
|
|
97
|
-
queueProvider: options.queueProvider,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
default: {
|
|
101
|
-
let plugin;
|
|
102
|
-
try {
|
|
103
|
-
plugin = require('../../providers/resolve-provider').resolveProvider(null, {
|
|
104
|
-
provider,
|
|
105
|
-
});
|
|
106
|
-
} catch (error) {
|
|
107
|
-
throw new Error(`Unknown scheduler provider: ${provider} (${error.message})`);
|
|
108
|
-
}
|
|
109
|
-
if (!plugin.SchedulerAdapter) {
|
|
110
|
-
throw new Error(`Unknown scheduler provider: ${provider}`);
|
|
111
|
-
}
|
|
112
|
-
return new plugin.SchedulerAdapter(options);
|
|
113
|
-
}
|
|
64
|
+
default:
|
|
65
|
+
throw new Error(`Unknown scheduler provider: ${provider}`);
|
|
114
66
|
}
|
|
115
67
|
}
|
|
116
68
|
|
package/integrations/index.js
CHANGED