@fragno-dev/project-connector-fragment 0.0.0-stage → 0.0.1
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/LICENSE.md +16 -0
- package/README.md +285 -2
- package/bin/run.js +4 -0
- package/dist/browser/client/react.d.ts +174 -0
- package/dist/browser/client/react.d.ts.map +1 -0
- package/dist/browser/client/react.js +195 -0
- package/dist/browser/client/react.js.map +1 -0
- package/dist/browser/client/solid.d.ts +177 -0
- package/dist/browser/client/solid.d.ts.map +1 -0
- package/dist/browser/client/solid.js +130 -0
- package/dist/browser/client/solid.js.map +1 -0
- package/dist/browser/client/svelte.d.ts +177 -0
- package/dist/browser/client/svelte.d.ts.map +1 -0
- package/dist/browser/client/svelte.js +132 -0
- package/dist/browser/client/svelte.js.map +1 -0
- package/dist/browser/client/vanilla.d.ts +204 -0
- package/dist/browser/client/vanilla.d.ts.map +1 -0
- package/dist/browser/client/vanilla.js +160 -0
- package/dist/browser/client/vanilla.js.map +1 -0
- package/dist/browser/client/vue.d.ts +177 -0
- package/dist/browser/client/vue.d.ts.map +1 -0
- package/dist/browser/client/vue.js +128 -0
- package/dist/browser/client/vue.js.map +1 -0
- package/dist/browser/client-BCzNDSlW.d.ts +711 -0
- package/dist/browser/client-BCzNDSlW.d.ts.map +1 -0
- package/dist/browser/index.d.ts +504 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +2 -0
- package/dist/browser/src-CSPQuoKz.js +2286 -0
- package/dist/browser/src-CSPQuoKz.js.map +1 -0
- package/dist/cli/authorization-browser.js +20 -0
- package/dist/cli/authorization-browser.js.map +1 -0
- package/dist/cli/cli.d.ts +6 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +258 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/definition.js +13 -0
- package/dist/cli/definition.js.map +1 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/project-connector-client.js +235 -0
- package/dist/cli/project-connector-client.js.map +1 -0
- package/dist/cli/project-connector-contracts.js +125 -0
- package/dist/cli/project-connector-contracts.js.map +1 -0
- package/dist/cli/routes.js +449 -0
- package/dist/cli/routes.js.map +1 -0
- package/dist/cli/schema.js +18 -0
- package/dist/cli/schema.js.map +1 -0
- package/dist/node/definition.d.ts +170 -0
- package/dist/node/definition.d.ts.map +1 -0
- package/dist/node/definition.js +13 -0
- package/dist/node/definition.js.map +1 -0
- package/dist/node/index.d.ts +456 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +36 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/project-connector-client.d.ts +13 -0
- package/dist/node/project-connector-client.d.ts.map +1 -0
- package/dist/node/project-connector-client.js +235 -0
- package/dist/node/project-connector-client.js.map +1 -0
- package/dist/node/project-connector-contracts.d.ts +179 -0
- package/dist/node/project-connector-contracts.d.ts.map +1 -0
- package/dist/node/project-connector-contracts.js +125 -0
- package/dist/node/project-connector-contracts.js.map +1 -0
- package/dist/node/routes.d.ts +307 -0
- package/dist/node/routes.d.ts.map +1 -0
- package/dist/node/routes.js +449 -0
- package/dist/node/routes.js.map +1 -0
- package/dist/node/schema.d.ts +49 -0
- package/dist/node/schema.d.ts.map +1 -0
- package/dist/node/schema.js +18 -0
- package/dist/node/schema.js.map +1 -0
- package/dist/node/testing/project-connector-test-gateway.d.ts +63 -0
- package/dist/node/testing/project-connector-test-gateway.d.ts.map +1 -0
- package/dist/node/testing/project-connector-test-gateway.js +370 -0
- package/dist/node/testing/project-connector-test-gateway.js.map +1 -0
- package/package.json +111 -3
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { projectConnectorProviderConfigsSchema } from "../project-connector-contracts.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/testing/project-connector-test-gateway.d.ts
|
|
4
|
+
type GatewayProviderConfig = z.infer<typeof projectConnectorProviderConfigsSchema>["providerConfigs"][number] & {
|
|
5
|
+
actionIds: string[];
|
|
6
|
+
};
|
|
7
|
+
type ConnectionRequest = {
|
|
8
|
+
id: string;
|
|
9
|
+
projectId: string;
|
|
10
|
+
providerConfigId: string;
|
|
11
|
+
externalUserId: string;
|
|
12
|
+
service: string;
|
|
13
|
+
alias: string;
|
|
14
|
+
authorizationUrl: string;
|
|
15
|
+
expiresAt: string;
|
|
16
|
+
status: "initiated" | "connected" | "failed" | "expired";
|
|
17
|
+
connectedAccountId: string | null;
|
|
18
|
+
errorCode: string | null;
|
|
19
|
+
errorMessage: string | null;
|
|
20
|
+
};
|
|
21
|
+
/** Stateful local SaaS gateway: real HTTP, OAuth completion, account ownership, and action failures. */
|
|
22
|
+
declare function startProjectConnectorTestGateway(): Promise<{
|
|
23
|
+
baseUrl: string;
|
|
24
|
+
links: {
|
|
25
|
+
userId: string;
|
|
26
|
+
service: string;
|
|
27
|
+
providerConfigId: string;
|
|
28
|
+
alias: string;
|
|
29
|
+
returnUri: string;
|
|
30
|
+
}[];
|
|
31
|
+
requests: Map<string, ConnectionRequest>;
|
|
32
|
+
accounts: Map<string, ConnectionRequest>;
|
|
33
|
+
providerConfigs: GatewayProviderConfig[];
|
|
34
|
+
catalogActions: Map<string, {
|
|
35
|
+
id: string;
|
|
36
|
+
service: string;
|
|
37
|
+
name: string;
|
|
38
|
+
description: string | null;
|
|
39
|
+
inputSchema: Record<string, unknown>;
|
|
40
|
+
outputSchema: Record<string, unknown>;
|
|
41
|
+
}>;
|
|
42
|
+
executions: {
|
|
43
|
+
externalUserId: string;
|
|
44
|
+
providerConfigId: string;
|
|
45
|
+
connectedAccountId: string;
|
|
46
|
+
input: Record<string, unknown>;
|
|
47
|
+
}[];
|
|
48
|
+
control: {
|
|
49
|
+
actionFailure: "flat" | "envelope" | "text" | "malformed" | null;
|
|
50
|
+
profileUserId: string | null;
|
|
51
|
+
requestReads: number;
|
|
52
|
+
discoveryFailure: "flat" | "envelope" | "text" | "malformed" | "duplicate" | "not-found" | "invalid-json" | "redirect" | "network" | null;
|
|
53
|
+
discoveryReads: number;
|
|
54
|
+
catalogReads: string[];
|
|
55
|
+
catalogFailure: "wrong-service" | "redirect" | null;
|
|
56
|
+
redirectReads: number;
|
|
57
|
+
};
|
|
58
|
+
authorize(requestId: string, accountId: string): void;
|
|
59
|
+
close(): Promise<void>;
|
|
60
|
+
}>;
|
|
61
|
+
//#endregion
|
|
62
|
+
export { startProjectConnectorTestGateway };
|
|
63
|
+
//# sourceMappingURL=project-connector-test-gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-connector-test-gateway.d.ts","names":[],"sources":["../../../src/testing/project-connector-test-gateway.ts"],"mappings":";;;KAUK,wBAAwB,EAAE,aACtB;EACwB;;KAgB5B;EACH;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;iBAIoB,oCAAgC;;;;;;;;;;;;;;;;;;;;;;;;WAmE3C;;;;;;;;;;;;+BA6QoB"}
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createServer } from "node:http";
|
|
3
|
+
//#region src/testing/project-connector-test-gateway.ts
|
|
4
|
+
const connectSchema = z.object({
|
|
5
|
+
userId: z.string(),
|
|
6
|
+
service: z.string().default("gmail"),
|
|
7
|
+
providerConfigId: z.string().default("gmail-provider"),
|
|
8
|
+
alias: z.string(),
|
|
9
|
+
returnUri: z.string()
|
|
10
|
+
});
|
|
11
|
+
const actionSchema = z.object({
|
|
12
|
+
userId: z.string(),
|
|
13
|
+
providerConfigId: z.string(),
|
|
14
|
+
connectedAccountId: z.string(),
|
|
15
|
+
input: z.record(z.string(), z.unknown())
|
|
16
|
+
});
|
|
17
|
+
/** Stateful local SaaS gateway: real HTTP, OAuth completion, account ownership, and action failures. */
|
|
18
|
+
async function startProjectConnectorTestGateway() {
|
|
19
|
+
const requests = /* @__PURE__ */ new Map();
|
|
20
|
+
const links = [];
|
|
21
|
+
const accounts = /* @__PURE__ */ new Map();
|
|
22
|
+
const providerConfigs = [{
|
|
23
|
+
id: "gmail-provider",
|
|
24
|
+
service: "gmail",
|
|
25
|
+
displayName: "Work Gmail",
|
|
26
|
+
callbackUrl: "https://connector.example/oauth/callback",
|
|
27
|
+
effectiveScopes: ["https://www.googleapis.com/auth/gmail.readonly"],
|
|
28
|
+
actionIds: ["gmail.search_threads"],
|
|
29
|
+
proxyAvailable: false
|
|
30
|
+
}];
|
|
31
|
+
const catalogActions = /* @__PURE__ */ new Map([["gmail.search_threads", {
|
|
32
|
+
id: "gmail.search_threads",
|
|
33
|
+
service: "gmail",
|
|
34
|
+
name: "Search Gmail threads",
|
|
35
|
+
description: "Search the selected Gmail account.",
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: { query: { type: "string" } },
|
|
39
|
+
required: ["query"],
|
|
40
|
+
additionalProperties: false
|
|
41
|
+
},
|
|
42
|
+
outputSchema: {
|
|
43
|
+
type: "object",
|
|
44
|
+
properties: {
|
|
45
|
+
query: { type: "string" },
|
|
46
|
+
threads: {
|
|
47
|
+
type: "array",
|
|
48
|
+
items: { type: "object" }
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
required: ["query", "threads"]
|
|
52
|
+
}
|
|
53
|
+
}], ["gmail.send_email", {
|
|
54
|
+
id: "gmail.send_email",
|
|
55
|
+
service: "gmail",
|
|
56
|
+
name: "Send Gmail email",
|
|
57
|
+
description: null,
|
|
58
|
+
inputSchema: {
|
|
59
|
+
type: "object",
|
|
60
|
+
properties: {
|
|
61
|
+
to: { type: "string" },
|
|
62
|
+
subject: { type: "string" },
|
|
63
|
+
body: { type: "string" }
|
|
64
|
+
},
|
|
65
|
+
required: [
|
|
66
|
+
"to",
|
|
67
|
+
"subject",
|
|
68
|
+
"body"
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
outputSchema: {
|
|
72
|
+
type: "object",
|
|
73
|
+
properties: { messageId: { type: "string" } },
|
|
74
|
+
required: ["messageId"]
|
|
75
|
+
}
|
|
76
|
+
}]]);
|
|
77
|
+
const executions = [];
|
|
78
|
+
const control = {
|
|
79
|
+
actionFailure: null,
|
|
80
|
+
profileUserId: null,
|
|
81
|
+
requestReads: 0,
|
|
82
|
+
discoveryFailure: null,
|
|
83
|
+
discoveryReads: 0,
|
|
84
|
+
catalogReads: [],
|
|
85
|
+
catalogFailure: null,
|
|
86
|
+
redirectReads: 0
|
|
87
|
+
};
|
|
88
|
+
let origin = "";
|
|
89
|
+
async function handleRequest(req, res) {
|
|
90
|
+
function json(data, status = 200) {
|
|
91
|
+
res.writeHead(status, { "content-type": "application/json" }).end(JSON.stringify(data));
|
|
92
|
+
}
|
|
93
|
+
function failure(code, status) {
|
|
94
|
+
json({
|
|
95
|
+
errorCode: code,
|
|
96
|
+
errorMessage: code
|
|
97
|
+
}, status);
|
|
98
|
+
}
|
|
99
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
100
|
+
if (url.pathname === "/v1/saas/redirect-target") {
|
|
101
|
+
control.redirectReads += 1;
|
|
102
|
+
failure("redirect_followed", 500);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (req.method === "GET" && url.pathname === "/v1/actions") {
|
|
106
|
+
if (req.headers.authorization !== "Bearer test-catalog-key") {
|
|
107
|
+
res.writeHead(401).end("Unauthorized test-catalog-key");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const service = url.searchParams.get("service");
|
|
111
|
+
if (!service) {
|
|
112
|
+
failure("service_required", 400);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
control.catalogReads.push(service);
|
|
116
|
+
if (control.catalogFailure === "redirect") {
|
|
117
|
+
res.writeHead(302, { location: `${origin}/v1/saas/redirect-target` }).end();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
json({
|
|
121
|
+
success: true,
|
|
122
|
+
data: [...catalogActions.values()].filter((action) => action.service === service).map((action) => ({
|
|
123
|
+
...action,
|
|
124
|
+
service: control.catalogFailure === "wrong-service" ? "slack" : action.service,
|
|
125
|
+
description: action.description ?? void 0,
|
|
126
|
+
clientSecret: "test-catalog-key"
|
|
127
|
+
}))
|
|
128
|
+
});
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (req.headers.authorization !== "Bearer test-project-key") {
|
|
132
|
+
res.writeHead(401).end("Unauthorized");
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const segments = url.pathname.split("/");
|
|
136
|
+
const route = segments[3];
|
|
137
|
+
const id = decodeURIComponent(segments[4] ?? "");
|
|
138
|
+
let payload = null;
|
|
139
|
+
if (req.method === "POST") {
|
|
140
|
+
req.setEncoding("utf8");
|
|
141
|
+
const chunks = [];
|
|
142
|
+
for await (const chunk of req) chunks.push(chunk);
|
|
143
|
+
payload = JSON.parse(chunks.join(""));
|
|
144
|
+
}
|
|
145
|
+
if (req.method === "GET" && url.pathname === "/v1/saas/oauth/provider-configs") {
|
|
146
|
+
control.discoveryReads += 1;
|
|
147
|
+
if (control.discoveryFailure === "flat") {
|
|
148
|
+
json({
|
|
149
|
+
errorCode: "provider_not_configured",
|
|
150
|
+
errorMessage: "test-project-key"
|
|
151
|
+
}, 503);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (control.discoveryFailure === "envelope") {
|
|
155
|
+
json({
|
|
156
|
+
success: false,
|
|
157
|
+
errorCode: "rate_limited",
|
|
158
|
+
message: "test-project-key"
|
|
159
|
+
}, 429);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (control.discoveryFailure === "text") {
|
|
163
|
+
res.writeHead(502).end("test-project-key upstream HTML error");
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (control.discoveryFailure === "malformed") {
|
|
167
|
+
json({
|
|
168
|
+
success: true,
|
|
169
|
+
data: {
|
|
170
|
+
projectId: "project-1",
|
|
171
|
+
providerConfigs: [{}]
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (control.discoveryFailure === "duplicate") {
|
|
177
|
+
json({
|
|
178
|
+
success: true,
|
|
179
|
+
data: {
|
|
180
|
+
projectId: "project-1",
|
|
181
|
+
providerConfigs: providerConfigs.concat(providerConfigs)
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (control.discoveryFailure === "not-found") {
|
|
187
|
+
failure("not_found", 404);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (control.discoveryFailure === "invalid-json") {
|
|
191
|
+
res.writeHead(200, { "content-type": "application/json" }).end("not JSON test-project-key");
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (control.discoveryFailure === "redirect") {
|
|
195
|
+
res.writeHead(302, { location: `${origin}/v1/saas/redirect-target` }).end();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (control.discoveryFailure === "network") {
|
|
199
|
+
req.socket.destroy();
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
json({
|
|
203
|
+
success: true,
|
|
204
|
+
data: {
|
|
205
|
+
projectId: "project-1",
|
|
206
|
+
providerConfigs: providerConfigs.map((config) => ({
|
|
207
|
+
...config,
|
|
208
|
+
clientSecret: "test-project-key"
|
|
209
|
+
})),
|
|
210
|
+
apiKey: "test-project-key"
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (route === "connected-accounts" && id === "link") {
|
|
216
|
+
const input = connectSchema.parse(payload);
|
|
217
|
+
links.push(input);
|
|
218
|
+
const requestId = `request-${requests.size + 1}`;
|
|
219
|
+
const connection = {
|
|
220
|
+
id: requestId,
|
|
221
|
+
projectId: "project-1",
|
|
222
|
+
providerConfigId: input.providerConfigId,
|
|
223
|
+
externalUserId: input.userId,
|
|
224
|
+
service: input.service,
|
|
225
|
+
alias: input.alias,
|
|
226
|
+
authorizationUrl: `${origin}/authorize/${requestId}`,
|
|
227
|
+
expiresAt: "2030-01-01T00:00:00.000Z",
|
|
228
|
+
status: "initiated",
|
|
229
|
+
connectedAccountId: null,
|
|
230
|
+
errorCode: null,
|
|
231
|
+
errorMessage: null
|
|
232
|
+
};
|
|
233
|
+
requests.set(requestId, connection);
|
|
234
|
+
json({
|
|
235
|
+
success: true,
|
|
236
|
+
data: connection
|
|
237
|
+
});
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (route === "connection-requests") {
|
|
241
|
+
control.requestReads += 1;
|
|
242
|
+
const connection = requests.get(id);
|
|
243
|
+
if (!connection) {
|
|
244
|
+
failure("connection_request_not_found", 404);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
json({
|
|
248
|
+
success: true,
|
|
249
|
+
data: connection
|
|
250
|
+
});
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (route === "connected-accounts" && segments[5] === "profile") {
|
|
254
|
+
const account = accounts.get(id);
|
|
255
|
+
if (!account) {
|
|
256
|
+
failure("connected_account_not_found", 404);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
json({
|
|
260
|
+
success: true,
|
|
261
|
+
data: {
|
|
262
|
+
connectedAccountId: id,
|
|
263
|
+
externalUserId: control.profileUserId ?? account.externalUserId,
|
|
264
|
+
service: account.service,
|
|
265
|
+
profile: {
|
|
266
|
+
id: "google-user",
|
|
267
|
+
kind: "user",
|
|
268
|
+
username: null,
|
|
269
|
+
displayName: "Test Gmail User",
|
|
270
|
+
avatarUrl: null,
|
|
271
|
+
email: "gmail-user@example.test",
|
|
272
|
+
metadata: {}
|
|
273
|
+
},
|
|
274
|
+
fetchedAt: 1234
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (route === "actions") {
|
|
280
|
+
const input = actionSchema.parse(payload);
|
|
281
|
+
const account = accounts.get(input.connectedAccountId);
|
|
282
|
+
if (!account || input.userId !== account.externalUserId || input.providerConfigId !== account.providerConfigId) {
|
|
283
|
+
failure("connected_account_not_found", 404);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
executions.push({
|
|
287
|
+
externalUserId: input.userId,
|
|
288
|
+
providerConfigId: input.providerConfigId,
|
|
289
|
+
connectedAccountId: input.connectedAccountId,
|
|
290
|
+
input: input.input
|
|
291
|
+
});
|
|
292
|
+
if (control.actionFailure === "flat") {
|
|
293
|
+
failure("credential_expired", 403);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (control.actionFailure === "envelope") {
|
|
297
|
+
json({
|
|
298
|
+
success: false,
|
|
299
|
+
errorCode: "rate_limited",
|
|
300
|
+
message: "Rate limit"
|
|
301
|
+
}, 429);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (control.actionFailure === "text") {
|
|
305
|
+
res.writeHead(502).end("test-project-key upstream HTML error");
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (control.actionFailure === "malformed") {
|
|
309
|
+
json({
|
|
310
|
+
success: true,
|
|
311
|
+
data: { result: "wrong" }
|
|
312
|
+
});
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
json({
|
|
316
|
+
success: true,
|
|
317
|
+
data: {
|
|
318
|
+
executionId: `execution-${executions.length}`,
|
|
319
|
+
actionId: id,
|
|
320
|
+
output: {
|
|
321
|
+
threads: [],
|
|
322
|
+
query: input.input["query"]
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
failure("not_found", 404);
|
|
329
|
+
}
|
|
330
|
+
const server = createServer((req, res) => {
|
|
331
|
+
handleRequest(req, res).catch(() => {
|
|
332
|
+
res.writeHead(500).end("Test connector gateway request failed");
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
await new Promise((resolve, reject) => {
|
|
336
|
+
server.once("error", reject);
|
|
337
|
+
server.listen(0, "127.0.0.1", resolve);
|
|
338
|
+
});
|
|
339
|
+
origin = `http://127.0.0.1:${server.address().port}`;
|
|
340
|
+
return {
|
|
341
|
+
baseUrl: `${origin}/v1`,
|
|
342
|
+
links,
|
|
343
|
+
requests,
|
|
344
|
+
accounts,
|
|
345
|
+
providerConfigs,
|
|
346
|
+
catalogActions,
|
|
347
|
+
executions,
|
|
348
|
+
control,
|
|
349
|
+
authorize(requestId, accountId) {
|
|
350
|
+
const connection = requests.get(requestId);
|
|
351
|
+
if (!connection) throw new Error("Test connector request does not exist");
|
|
352
|
+
connection.status = "connected";
|
|
353
|
+
connection.connectedAccountId = accountId;
|
|
354
|
+
accounts.set(accountId, { ...connection });
|
|
355
|
+
},
|
|
356
|
+
async close() {
|
|
357
|
+
server.closeAllConnections();
|
|
358
|
+
await new Promise((resolve, reject) => {
|
|
359
|
+
server.close((error) => {
|
|
360
|
+
if (error) reject(error);
|
|
361
|
+
else resolve();
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
//#endregion
|
|
368
|
+
export { startProjectConnectorTestGateway };
|
|
369
|
+
|
|
370
|
+
//# sourceMappingURL=project-connector-test-gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-connector-test-gateway.js","names":[],"sources":["../../../src/testing/project-connector-test-gateway.ts"],"sourcesContent":["import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\n\nimport { z } from \"zod\";\n\nimport type {\n projectConnectorActionSchema,\n projectConnectorProviderConfigsSchema,\n} from \"../project-connector-contracts\";\n\ntype GatewayProviderConfig = z.infer<\n typeof projectConnectorProviderConfigsSchema\n>[\"providerConfigs\"][number] & { actionIds: string[] };\n\nconst connectSchema = z.object({\n userId: z.string(),\n service: z.string().default(\"gmail\"),\n providerConfigId: z.string().default(\"gmail-provider\"),\n alias: z.string(),\n returnUri: z.string(),\n});\nconst actionSchema = z.object({\n userId: z.string(),\n providerConfigId: z.string(),\n connectedAccountId: z.string(),\n input: z.record(z.string(), z.unknown()),\n});\n\ntype ConnectionRequest = {\n id: string;\n projectId: string;\n providerConfigId: string;\n externalUserId: string;\n service: string;\n alias: string;\n authorizationUrl: string;\n expiresAt: string;\n status: \"initiated\" | \"connected\" | \"failed\" | \"expired\";\n connectedAccountId: string | null;\n errorCode: string | null;\n errorMessage: string | null;\n};\n\n/** Stateful local SaaS gateway: real HTTP, OAuth completion, account ownership, and action failures. */\nexport async function startProjectConnectorTestGateway() {\n const requests = new Map<string, ConnectionRequest>();\n const links: z.infer<typeof connectSchema>[] = [];\n const accounts = new Map<string, ConnectionRequest>();\n const providerConfigs: GatewayProviderConfig[] = [\n {\n id: \"gmail-provider\",\n service: \"gmail\",\n displayName: \"Work Gmail\",\n callbackUrl: \"https://connector.example/oauth/callback\",\n effectiveScopes: [\"https://www.googleapis.com/auth/gmail.readonly\"],\n actionIds: [\"gmail.search_threads\"],\n proxyAvailable: false,\n },\n ];\n const catalogActions = new Map<string, z.output<typeof projectConnectorActionSchema>>([\n [\n \"gmail.search_threads\",\n {\n id: \"gmail.search_threads\",\n service: \"gmail\",\n name: \"Search Gmail threads\",\n description: \"Search the selected Gmail account.\",\n inputSchema: {\n type: \"object\",\n properties: { query: { type: \"string\" } },\n required: [\"query\"],\n additionalProperties: false,\n },\n outputSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\" },\n threads: { type: \"array\", items: { type: \"object\" } },\n },\n required: [\"query\", \"threads\"],\n },\n },\n ],\n [\n \"gmail.send_email\",\n {\n id: \"gmail.send_email\",\n service: \"gmail\",\n name: \"Send Gmail email\",\n description: null,\n inputSchema: {\n type: \"object\",\n properties: {\n to: { type: \"string\" },\n subject: { type: \"string\" },\n body: { type: \"string\" },\n },\n required: [\"to\", \"subject\", \"body\"],\n },\n outputSchema: {\n type: \"object\",\n properties: { messageId: { type: \"string\" } },\n required: [\"messageId\"],\n },\n },\n ],\n ]);\n const executions: {\n externalUserId: string;\n providerConfigId: string;\n connectedAccountId: string;\n input: Record<string, unknown>;\n }[] = [];\n const control: {\n actionFailure: \"flat\" | \"envelope\" | \"text\" | \"malformed\" | null;\n profileUserId: string | null;\n requestReads: number;\n discoveryFailure:\n | \"flat\"\n | \"envelope\"\n | \"text\"\n | \"malformed\"\n | \"duplicate\"\n | \"not-found\"\n | \"invalid-json\"\n | \"redirect\"\n | \"network\"\n | null;\n discoveryReads: number;\n catalogReads: string[];\n catalogFailure: \"wrong-service\" | \"redirect\" | null;\n redirectReads: number;\n } = {\n actionFailure: null,\n profileUserId: null,\n requestReads: 0,\n discoveryFailure: null,\n discoveryReads: 0,\n catalogReads: [],\n catalogFailure: null,\n redirectReads: 0,\n };\n let origin = \"\";\n async function handleRequest(req: IncomingMessage, res: ServerResponse) {\n function json(data: unknown, status = 200) {\n res.writeHead(status, { \"content-type\": \"application/json\" }).end(JSON.stringify(data));\n }\n function failure(code: string, status: number) {\n json({ errorCode: code, errorMessage: code }, status);\n }\n const url = new URL(req.url ?? \"/\", \"http://localhost\");\n if (url.pathname === \"/v1/saas/redirect-target\") {\n control.redirectReads += 1;\n failure(\"redirect_followed\", 500);\n return;\n }\n if (req.method === \"GET\" && url.pathname === \"/v1/actions\") {\n if (req.headers.authorization !== \"Bearer test-catalog-key\") {\n res.writeHead(401).end(\"Unauthorized test-catalog-key\");\n return;\n }\n const service = url.searchParams.get(\"service\");\n if (!service) {\n failure(\"service_required\", 400);\n return;\n }\n control.catalogReads.push(service);\n if (control.catalogFailure === \"redirect\") {\n res.writeHead(302, { location: `${origin}/v1/saas/redirect-target` }).end();\n return;\n }\n json({\n success: true,\n data: [...catalogActions.values()]\n .filter((action) => action.service === service)\n .map((action) => ({\n ...action,\n service: control.catalogFailure === \"wrong-service\" ? \"slack\" : action.service,\n description: action.description ?? undefined,\n clientSecret: \"test-catalog-key\",\n })),\n });\n return;\n }\n if (req.headers.authorization !== \"Bearer test-project-key\") {\n res.writeHead(401).end(\"Unauthorized\");\n return;\n }\n const segments = url.pathname.split(\"/\");\n const route = segments[3];\n const id = decodeURIComponent(segments[4] ?? \"\");\n let payload: unknown = null;\n if (req.method === \"POST\") {\n req.setEncoding(\"utf8\");\n const chunks: string[] = [];\n for await (const chunk of req) {\n chunks.push(chunk as string);\n }\n payload = JSON.parse(chunks.join(\"\"));\n }\n if (req.method === \"GET\" && url.pathname === \"/v1/saas/oauth/provider-configs\") {\n control.discoveryReads += 1;\n if (control.discoveryFailure === \"flat\") {\n json({ errorCode: \"provider_not_configured\", errorMessage: \"test-project-key\" }, 503);\n return;\n }\n if (control.discoveryFailure === \"envelope\") {\n json({ success: false, errorCode: \"rate_limited\", message: \"test-project-key\" }, 429);\n return;\n }\n if (control.discoveryFailure === \"text\") {\n res.writeHead(502).end(\"test-project-key upstream HTML error\");\n return;\n }\n if (control.discoveryFailure === \"malformed\") {\n json({ success: true, data: { projectId: \"project-1\", providerConfigs: [{}] } });\n return;\n }\n if (control.discoveryFailure === \"duplicate\") {\n json({\n success: true,\n data: {\n projectId: \"project-1\",\n providerConfigs: providerConfigs.concat(providerConfigs),\n },\n });\n return;\n }\n if (control.discoveryFailure === \"not-found\") {\n failure(\"not_found\", 404);\n return;\n }\n if (control.discoveryFailure === \"invalid-json\") {\n res.writeHead(200, { \"content-type\": \"application/json\" }).end(\"not JSON test-project-key\");\n return;\n }\n if (control.discoveryFailure === \"redirect\") {\n res.writeHead(302, { location: `${origin}/v1/saas/redirect-target` }).end();\n return;\n }\n if (control.discoveryFailure === \"network\") {\n req.socket.destroy();\n return;\n }\n // Extra upstream fields must not become public API or expose credentials.\n json({\n success: true,\n data: {\n projectId: \"project-1\",\n providerConfigs: providerConfigs.map((config) => ({\n ...config,\n clientSecret: \"test-project-key\",\n })),\n apiKey: \"test-project-key\",\n },\n });\n return;\n }\n if (route === \"connected-accounts\" && id === \"link\") {\n const input = connectSchema.parse(payload);\n links.push(input);\n const requestId = `request-${requests.size + 1}`;\n const connection: ConnectionRequest = {\n id: requestId,\n projectId: \"project-1\",\n providerConfigId: input.providerConfigId,\n externalUserId: input.userId,\n service: input.service,\n alias: input.alias,\n authorizationUrl: `${origin}/authorize/${requestId}`,\n expiresAt: \"2030-01-01T00:00:00.000Z\",\n status: \"initiated\",\n connectedAccountId: null,\n errorCode: null,\n errorMessage: null,\n };\n requests.set(requestId, connection);\n json({ success: true, data: connection });\n return;\n }\n if (route === \"connection-requests\") {\n control.requestReads += 1;\n const connection = requests.get(id);\n if (!connection) {\n failure(\"connection_request_not_found\", 404);\n return;\n }\n json({ success: true, data: connection });\n return;\n }\n if (route === \"connected-accounts\" && segments[5] === \"profile\") {\n const account = accounts.get(id);\n if (!account) {\n failure(\"connected_account_not_found\", 404);\n return;\n }\n json({\n success: true,\n data: {\n connectedAccountId: id,\n externalUserId: control.profileUserId ?? account.externalUserId,\n service: account.service,\n profile: {\n id: \"google-user\",\n kind: \"user\",\n username: null,\n displayName: \"Test Gmail User\",\n avatarUrl: null,\n email: \"gmail-user@example.test\",\n metadata: {},\n },\n fetchedAt: 1234,\n },\n });\n return;\n }\n if (route === \"actions\") {\n const input = actionSchema.parse(payload);\n const account = accounts.get(input.connectedAccountId);\n if (\n !account ||\n input.userId !== account.externalUserId ||\n input.providerConfigId !== account.providerConfigId\n ) {\n failure(\"connected_account_not_found\", 404);\n return;\n }\n executions.push({\n externalUserId: input.userId,\n providerConfigId: input.providerConfigId,\n connectedAccountId: input.connectedAccountId,\n input: input.input,\n });\n if (control.actionFailure === \"flat\") {\n failure(\"credential_expired\", 403);\n return;\n }\n if (control.actionFailure === \"envelope\") {\n json({ success: false, errorCode: \"rate_limited\", message: \"Rate limit\" }, 429);\n return;\n }\n if (control.actionFailure === \"text\") {\n res.writeHead(502).end(\"test-project-key upstream HTML error\");\n return;\n }\n if (control.actionFailure === \"malformed\") {\n json({ success: true, data: { result: \"wrong\" } });\n return;\n }\n json({\n success: true,\n data: {\n executionId: `execution-${executions.length}`,\n actionId: id,\n output: { threads: [], query: input.input[\"query\"] },\n },\n });\n return;\n }\n failure(\"not_found\", 404);\n }\n const server = createServer((req, res) => {\n void handleRequest(req, res).catch(() => {\n res.writeHead(500).end(\"Test connector gateway request failed\");\n });\n });\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", resolve);\n });\n origin = `http://127.0.0.1:${(server.address() as AddressInfo).port}`;\n return {\n baseUrl: `${origin}/v1`,\n links,\n requests,\n accounts,\n providerConfigs,\n catalogActions,\n executions,\n control,\n authorize(requestId: string, accountId: string) {\n const connection = requests.get(requestId);\n if (!connection) {\n throw new Error(\"Test connector request does not exist\");\n }\n connection.status = \"connected\";\n connection.connectedAccountId = accountId;\n accounts.set(accountId, { ...connection });\n },\n async close() {\n server.closeAllConnections();\n await new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n },\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,114 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fragno-dev/project-connector-fragment",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A Fragno fragment for OOMOL Project Connector integrations",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"fragno",
|
|
7
|
+
"project-connector",
|
|
8
|
+
"react",
|
|
9
|
+
"solidjs",
|
|
10
|
+
"svelte",
|
|
11
|
+
"typescript",
|
|
12
|
+
"vue"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/rejot-dev/fragno.git",
|
|
17
|
+
"directory": "packages/project-connector-fragment"
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"fragno-project-connector": "./bin/run.js"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"bin"
|
|
25
|
+
],
|
|
26
|
+
"type": "module",
|
|
27
|
+
"main": "./dist/node/index.js",
|
|
28
|
+
"module": "./dist/node/index.js",
|
|
29
|
+
"types": "./dist/node/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/node/index.d.ts",
|
|
33
|
+
"default": "./dist/node/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./cli": {
|
|
36
|
+
"types": "./dist/cli/cli.d.ts",
|
|
37
|
+
"default": "./dist/cli/cli.js"
|
|
38
|
+
},
|
|
39
|
+
"./definition": {
|
|
40
|
+
"types": "./dist/node/definition.d.ts",
|
|
41
|
+
"default": "./dist/node/definition.js"
|
|
42
|
+
},
|
|
43
|
+
"./routes": {
|
|
44
|
+
"types": "./dist/node/routes.d.ts",
|
|
45
|
+
"default": "./dist/node/routes.js"
|
|
46
|
+
},
|
|
47
|
+
"./schema": {
|
|
48
|
+
"types": "./dist/node/schema.d.ts",
|
|
49
|
+
"default": "./dist/node/schema.js"
|
|
50
|
+
},
|
|
51
|
+
"./testing": {
|
|
52
|
+
"types": "./dist/node/testing/project-connector-test-gateway.d.ts",
|
|
53
|
+
"default": "./dist/node/testing/project-connector-test-gateway.js"
|
|
54
|
+
},
|
|
55
|
+
"./contracts": {
|
|
56
|
+
"types": "./dist/node/project-connector-contracts.d.ts",
|
|
57
|
+
"default": "./dist/node/project-connector-contracts.js"
|
|
58
|
+
},
|
|
59
|
+
"./react": {
|
|
60
|
+
"types": "./dist/browser/client/react.d.ts",
|
|
61
|
+
"default": "./dist/browser/client/react.js"
|
|
62
|
+
},
|
|
63
|
+
"./vue": {
|
|
64
|
+
"types": "./dist/browser/client/vue.d.ts",
|
|
65
|
+
"default": "./dist/browser/client/vue.js"
|
|
66
|
+
},
|
|
67
|
+
"./svelte": {
|
|
68
|
+
"types": "./dist/browser/client/svelte.d.ts",
|
|
69
|
+
"default": "./dist/browser/client/svelte.js"
|
|
70
|
+
},
|
|
71
|
+
"./solid": {
|
|
72
|
+
"types": "./dist/browser/client/solid.d.ts",
|
|
73
|
+
"default": "./dist/browser/client/solid.js"
|
|
74
|
+
},
|
|
75
|
+
"./vanilla": {
|
|
76
|
+
"types": "./dist/browser/client/vanilla.d.ts",
|
|
77
|
+
"default": "./dist/browser/client/vanilla.js"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"dependencies": {
|
|
81
|
+
"@oomol-lab/connector": "^1.2.0",
|
|
82
|
+
"@standard-schema/spec": "^1.1.0",
|
|
83
|
+
"zod": "^4.5.4",
|
|
84
|
+
"@fragno-dev/core": "0.2.2",
|
|
85
|
+
"@fragno-dev/db": "0.4.1"
|
|
86
|
+
},
|
|
87
|
+
"devDependencies": {
|
|
88
|
+
"@types/node": "^25.2.2",
|
|
89
|
+
"tsdown": "^0.22.4",
|
|
90
|
+
"tsx": "^4.21.0",
|
|
91
|
+
"vitest": "^4.1.4",
|
|
92
|
+
"@fragno-dev/test": "2.0.2",
|
|
93
|
+
"@fragno-dev/unplugin-fragno": "0.0.9",
|
|
94
|
+
"@fragno-private/typescript-config": "0.0.1"
|
|
95
|
+
},
|
|
96
|
+
"peerDependencies": {
|
|
97
|
+
"react": ">=18.0.0",
|
|
98
|
+
"solid-js": ">=1.0.0",
|
|
99
|
+
"svelte": ">=4.0.0",
|
|
100
|
+
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
101
|
+
"vue": ">=3.0.0"
|
|
102
|
+
},
|
|
103
|
+
"scripts": {
|
|
104
|
+
"types:check": "tsc --noEmit",
|
|
105
|
+
"build": "tsdown",
|
|
106
|
+
"cli": "tsx src/cli/cli.ts",
|
|
107
|
+
"test": "vitest run",
|
|
108
|
+
"test:watch": "vitest --watch",
|
|
109
|
+
"format:package": "node ../../scripts/run-package-quality.mjs format",
|
|
110
|
+
"format:check:package": "node ../../scripts/run-package-quality.mjs format:check",
|
|
111
|
+
"lint:package": "node ../../scripts/run-package-quality.mjs lint",
|
|
112
|
+
"lint:fix:package": "node ../../scripts/run-package-quality.mjs lint:fix"
|
|
113
|
+
}
|
|
6
114
|
}
|