@friggframework/core 2.0.0-next.80 → 2.0.0-next.82

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.
Files changed (40) hide show
  1. package/CLAUDE.md +8 -0
  2. package/generated/prisma-mongodb/edge.js +3 -3
  3. package/generated/prisma-mongodb/index.d.ts +2 -2
  4. package/generated/prisma-mongodb/index.js +9 -9
  5. package/generated/prisma-mongodb/{query-engine-debian-openssl-3.0.x → libquery_engine-debian-openssl-3.0.x.so.node} +0 -0
  6. package/generated/prisma-mongodb/{query-engine-rhel-openssl-3.0.x → libquery_engine-rhel-openssl-3.0.x.so.node} +0 -0
  7. package/generated/prisma-mongodb/package.json +1 -1
  8. package/generated/prisma-mongodb/runtime/library.js +146 -0
  9. package/generated/prisma-mongodb/schema.prisma +7 -1
  10. package/generated/prisma-mongodb/wasm.js +3 -3
  11. package/generated/prisma-postgresql/edge.js +3 -3
  12. package/generated/prisma-postgresql/index.d.ts +6 -2
  13. package/generated/prisma-postgresql/index.js +9 -9
  14. package/generated/prisma-postgresql/{query-engine-debian-openssl-3.0.x → libquery_engine-debian-openssl-3.0.x.so.node} +0 -0
  15. package/generated/prisma-postgresql/{query-engine-rhel-openssl-3.0.x → libquery_engine-rhel-openssl-3.0.x.so.node} +0 -0
  16. package/generated/prisma-postgresql/package.json +1 -1
  17. package/generated/prisma-postgresql/runtime/library.js +146 -0
  18. package/generated/prisma-postgresql/schema.prisma +7 -1
  19. package/generated/prisma-postgresql/wasm.js +3 -3
  20. package/integrations/integration-router.js +27 -6
  21. package/integrations/repositories/process-repository-documentdb.js +68 -0
  22. package/integrations/repositories/process-repository-interface.js +46 -0
  23. package/integrations/repositories/process-repository-mongo.js +72 -0
  24. package/integrations/repositories/process-repository-postgres.js +163 -0
  25. package/integrations/repositories/process-update-ops-shared.js +112 -0
  26. package/integrations/use-cases/update-process-metrics.js +106 -102
  27. package/integrations/use-cases/update-process-state.js +58 -19
  28. package/modules/module.js +3 -1
  29. package/modules/requester/requester.js +145 -37
  30. package/modules/use-cases/get-module-instance-from-type.js +4 -1
  31. package/modules/use-cases/process-authorization-callback.js +49 -5
  32. package/package.json +5 -5
  33. package/prisma-mongodb/schema.prisma +7 -1
  34. package/prisma-postgresql/migrations/20260422120000_add_entity_data_column/migration.sql +10 -0
  35. package/prisma-postgresql/migrations/20260422120001_create_process_table/migration.sql +48 -0
  36. package/prisma-postgresql/schema.prisma +7 -1
  37. package/generated/prisma-mongodb/runtime/binary.d.ts +0 -1
  38. package/generated/prisma-mongodb/runtime/binary.js +0 -289
  39. package/generated/prisma-postgresql/runtime/binary.d.ts +0 -1
  40. package/generated/prisma-postgresql/runtime/binary.js +0 -289
@@ -28,6 +28,11 @@ class ProcessAuthorizationCallback {
28
28
  }
29
29
 
30
30
  async execute(userId, entityType, params) {
31
+ const hasCode = Boolean(params && params.code);
32
+ console.log(
33
+ `[Frigg] processAuthorizationCallback start userId=${userId} entityType=${entityType} hasCode=${hasCode}`
34
+ );
35
+
31
36
  const moduleDefinition = this.moduleDefinitions.find((def) => {
32
37
  return entityType === def.moduleName;
33
38
  });
@@ -38,12 +43,29 @@ class ProcessAuthorizationCallback {
38
43
  );
39
44
  }
40
45
 
41
- // todo: check if we need to pass entity to Module, right now it's null
42
- let entity = null;
46
+ // Bootstrap the Module with the existing entity (if any) so the API
47
+ // requester is preloaded with prior tokens. This enables a refresh
48
+ // fallback when callers lack a fresh OAuth code, and lets us match a
49
+ // re-auth back to the existing credential record by id.
50
+ const existingEntities =
51
+ await this.moduleRepository.findEntitiesByUserIdAndModuleName(
52
+ userId,
53
+ entityType
54
+ );
55
+ const existingEntity =
56
+ existingEntities && existingEntities.length > 0
57
+ ? existingEntities[0]
58
+ : null;
59
+
60
+ if (existingEntity) {
61
+ console.log(
62
+ `[Frigg] processAuthorizationCallback found existing entity id=${existingEntity.id} credentialId=${existingEntity.credential?.id}`
63
+ );
64
+ }
43
65
 
44
66
  const module = new Module({
45
67
  userId,
46
- entity,
68
+ entity: existingEntity,
47
69
  definition: moduleDefinition,
48
70
  });
49
71
 
@@ -53,6 +75,16 @@ class ProcessAuthorizationCallback {
53
75
  module.api,
54
76
  params
55
77
  );
78
+ console.log(
79
+ `[Frigg] processAuthorizationCallback OAuth getToken complete userId=${userId} entityType=${entityType}`
80
+ );
81
+ // Belt-and-suspenders: persist tokens explicitly here rather than
82
+ // relying solely on the DLGT_TOKEN_UPDATE notification chain
83
+ // inside setTokens. The notification path remains in place but
84
+ // has been observed to no-op silently in some prod paths,
85
+ // leaving newly-issued tokens unsaved while the user-visible
86
+ // OAuth flow appears to succeed.
87
+ await this.onTokenUpdate(module, moduleDefinition, userId);
56
88
  } else {
57
89
  tokenResponse =
58
90
  await moduleDefinition.requiredAuthMethods.setAuthParams(
@@ -62,6 +94,10 @@ class ProcessAuthorizationCallback {
62
94
  await this.onTokenUpdate(module, moduleDefinition, userId);
63
95
  }
64
96
 
97
+ console.log(
98
+ `[Frigg] processAuthorizationCallback credential persisted credentialId=${module.credential?.id} authIsValid=${module.credential?.authIsValid}`
99
+ );
100
+
65
101
  const authRes = await module.testAuth();
66
102
  if (!authRes) {
67
103
  throw new Error('Authorization failed');
@@ -90,7 +126,12 @@ class ProcessAuthorizationCallback {
90
126
  // credential + entity are already persisted. Operators can recover
91
127
  // stuck integrations manually.
92
128
  try {
93
- await this.restoreIntegrationsForEntity(persistedEntity.id);
129
+ const restoredCount = await this.restoreIntegrationsForEntity(
130
+ persistedEntity.id
131
+ );
132
+ console.log(
133
+ `[Frigg] processAuthorizationCallback restored ${restoredCount} integration(s) for entityId=${persistedEntity.id}`
134
+ );
94
135
  } catch (err) {
95
136
  console.error(
96
137
  `[Frigg] Failed to restore integrations for entity ${persistedEntity.id} after successful re-auth — manual intervention may be needed`,
@@ -106,11 +147,12 @@ class ProcessAuthorizationCallback {
106
147
  }
107
148
 
108
149
  async restoreIntegrationsForEntity(entityId) {
109
- if (!this.integrationRepository) return;
150
+ if (!this.integrationRepository) return 0;
110
151
  const integrations =
111
152
  await this.integrationRepository.findIntegrationsByEntityId(
112
153
  entityId
113
154
  );
155
+ let restored = 0;
114
156
  for (const integration of integrations) {
115
157
  if (STATUSES_RESET_ON_REAUTH.includes(integration.status)) {
116
158
  console.log(
@@ -120,8 +162,10 @@ class ProcessAuthorizationCallback {
120
162
  integration.id,
121
163
  'ENABLED'
122
164
  );
165
+ restored++;
123
166
  }
124
167
  }
168
+ return restored;
125
169
  }
126
170
 
127
171
  async onTokenUpdate(module, moduleDefinition, userId) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@friggframework/core",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0-next.80",
4
+ "version": "2.0.0-next.82",
5
5
  "dependencies": {
6
6
  "@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
7
7
  "@aws-sdk/client-kms": "^3.588.0",
@@ -38,9 +38,9 @@
38
38
  }
39
39
  },
40
40
  "devDependencies": {
41
- "@friggframework/eslint-config": "2.0.0-next.80",
42
- "@friggframework/prettier-config": "2.0.0-next.80",
43
- "@friggframework/test": "2.0.0-next.80",
41
+ "@friggframework/eslint-config": "2.0.0-next.82",
42
+ "@friggframework/prettier-config": "2.0.0-next.82",
43
+ "@friggframework/test": "2.0.0-next.82",
44
44
  "@prisma/client": "^6.17.0",
45
45
  "@types/lodash": "4.17.15",
46
46
  "@typescript-eslint/eslint-plugin": "^8.0.0",
@@ -80,5 +80,5 @@
80
80
  "publishConfig": {
81
81
  "access": "public"
82
82
  },
83
- "gitHead": "7a66dfcb02143941411ff26aaee866afc1473df8"
83
+ "gitHead": "765f34d4ea2b2861f4a1723f8b319bfef9a5aea8"
84
84
  }
@@ -6,7 +6,13 @@ generator client {
6
6
  provider = "prisma-client-js"
7
7
  output = "../generated/prisma-mongodb"
8
8
  binaryTargets = ["native", "rhel-openssl-3.0.x"] // native for local dev, rhel for Lambda deployment
9
- engineType = "binary" // Use binary engines (smaller size)
9
+ // Library engine (default since Prisma 3.x): Rust query engine loads as a
10
+ // Node-API addon inside the same process. The binary engine forks a child
11
+ // query-engine subprocess and communicates over a local HTTP/IPC pipe with
12
+ // NO client-side timeout — a zombied child wedges the Node process until
13
+ // Lambda's 900s cap. Switching to library eliminates that entire class of
14
+ // silent hangs. See friggframework/frigg#580 for the investigation.
15
+ engineType = "library"
10
16
  }
11
17
 
12
18
  datasource db {
@@ -0,0 +1,10 @@
1
+ -- AlterTable
2
+ -- Backfill the Entity.data JSONB field declared in schema.prisma but never
3
+ -- migrated. ModuleRepositoryPostgres.createEntity / findEntity use this
4
+ -- column to persist & rehydrate identifiers/details fields that fall
5
+ -- outside the six named columns (id, userId, credentialId, name,
6
+ -- moduleName, externalId). Without the column, any integration whose
7
+ -- getEntityDetails returns an extra field (e.g. `firm_subdomain`) causes
8
+ -- prisma.entity.create to throw P2022 at runtime.
9
+ ALTER TABLE "Entity"
10
+ ADD COLUMN IF NOT EXISTS "data" JSONB NOT NULL DEFAULT '{}';
@@ -0,0 +1,48 @@
1
+ -- CreateTable
2
+ -- The Process model is declared in schema.prisma but was never created by
3
+ -- any prior migration. ProcessRepositoryPostgres (read/write) and
4
+ -- FriggProcessManager rely on this table for long-running job tracking —
5
+ -- e.g. fan-out sync progress, batch state machines. Without the table,
6
+ -- any `prisma.process.create` at runtime throws P2021.
7
+ CREATE TABLE "Process" (
8
+ "id" SERIAL NOT NULL,
9
+ "userId" INTEGER NOT NULL,
10
+ "integrationId" INTEGER NOT NULL,
11
+ "name" TEXT NOT NULL,
12
+ "type" TEXT NOT NULL,
13
+ "state" TEXT NOT NULL,
14
+ "context" JSONB NOT NULL DEFAULT '{}',
15
+ "results" JSONB NOT NULL DEFAULT '{}',
16
+ "parentProcessId" INTEGER,
17
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
18
+ "updatedAt" TIMESTAMP(3) NOT NULL,
19
+
20
+ CONSTRAINT "Process_pkey" PRIMARY KEY ("id")
21
+ );
22
+
23
+ -- CreateIndex
24
+ CREATE INDEX "Process_userId_idx" ON "Process"("userId");
25
+
26
+ -- CreateIndex
27
+ CREATE INDEX "Process_integrationId_idx" ON "Process"("integrationId");
28
+
29
+ -- CreateIndex
30
+ CREATE INDEX "Process_type_idx" ON "Process"("type");
31
+
32
+ -- CreateIndex
33
+ CREATE INDEX "Process_state_idx" ON "Process"("state");
34
+
35
+ -- CreateIndex
36
+ CREATE INDEX "Process_name_idx" ON "Process"("name");
37
+
38
+ -- CreateIndex
39
+ CREATE INDEX "Process_parentProcessId_idx" ON "Process"("parentProcessId");
40
+
41
+ -- AddForeignKey
42
+ ALTER TABLE "Process" ADD CONSTRAINT "Process_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
43
+
44
+ -- AddForeignKey
45
+ ALTER TABLE "Process" ADD CONSTRAINT "Process_integrationId_fkey" FOREIGN KEY ("integrationId") REFERENCES "Integration"("id") ON DELETE CASCADE ON UPDATE CASCADE;
46
+
47
+ -- AddForeignKey
48
+ ALTER TABLE "Process" ADD CONSTRAINT "Process_parentProcessId_fkey" FOREIGN KEY ("parentProcessId") REFERENCES "Process"("id") ON DELETE SET NULL ON UPDATE CASCADE;
@@ -6,7 +6,13 @@ generator client {
6
6
  provider = "prisma-client-js"
7
7
  output = "../generated/prisma-postgresql"
8
8
  binaryTargets = ["native", "rhel-openssl-3.0.x"] // native for local dev, rhel for Lambda deployment
9
- engineType = "binary" // Use binary engines (smaller size)
9
+ // Library engine (default since Prisma 3.x): Rust query engine loads as a
10
+ // Node-API addon inside the same process. The binary engine forks a child
11
+ // query-engine subprocess and communicates over a local HTTP/IPC pipe with
12
+ // NO client-side timeout — a zombied child wedges the Node process until
13
+ // Lambda's 900s cap. Switching to library eliminates that entire class of
14
+ // silent hangs. See friggframework/frigg#580 for the investigation.
15
+ engineType = "library"
10
16
  }
11
17
 
12
18
  datasource db {
@@ -1 +0,0 @@
1
- export * from "./library"