@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.
Files changed (77) hide show
  1. package/LICENSE.md +16 -0
  2. package/README.md +285 -2
  3. package/bin/run.js +4 -0
  4. package/dist/browser/client/react.d.ts +174 -0
  5. package/dist/browser/client/react.d.ts.map +1 -0
  6. package/dist/browser/client/react.js +195 -0
  7. package/dist/browser/client/react.js.map +1 -0
  8. package/dist/browser/client/solid.d.ts +177 -0
  9. package/dist/browser/client/solid.d.ts.map +1 -0
  10. package/dist/browser/client/solid.js +130 -0
  11. package/dist/browser/client/solid.js.map +1 -0
  12. package/dist/browser/client/svelte.d.ts +177 -0
  13. package/dist/browser/client/svelte.d.ts.map +1 -0
  14. package/dist/browser/client/svelte.js +132 -0
  15. package/dist/browser/client/svelte.js.map +1 -0
  16. package/dist/browser/client/vanilla.d.ts +204 -0
  17. package/dist/browser/client/vanilla.d.ts.map +1 -0
  18. package/dist/browser/client/vanilla.js +160 -0
  19. package/dist/browser/client/vanilla.js.map +1 -0
  20. package/dist/browser/client/vue.d.ts +177 -0
  21. package/dist/browser/client/vue.d.ts.map +1 -0
  22. package/dist/browser/client/vue.js +128 -0
  23. package/dist/browser/client/vue.js.map +1 -0
  24. package/dist/browser/client-BCzNDSlW.d.ts +711 -0
  25. package/dist/browser/client-BCzNDSlW.d.ts.map +1 -0
  26. package/dist/browser/index.d.ts +504 -0
  27. package/dist/browser/index.d.ts.map +1 -0
  28. package/dist/browser/index.js +2 -0
  29. package/dist/browser/src-CSPQuoKz.js +2286 -0
  30. package/dist/browser/src-CSPQuoKz.js.map +1 -0
  31. package/dist/cli/authorization-browser.js +20 -0
  32. package/dist/cli/authorization-browser.js.map +1 -0
  33. package/dist/cli/cli.d.ts +6 -0
  34. package/dist/cli/cli.d.ts.map +1 -0
  35. package/dist/cli/cli.js +258 -0
  36. package/dist/cli/cli.js.map +1 -0
  37. package/dist/cli/definition.js +13 -0
  38. package/dist/cli/definition.js.map +1 -0
  39. package/dist/cli/index.js +14 -0
  40. package/dist/cli/index.js.map +1 -0
  41. package/dist/cli/project-connector-client.js +235 -0
  42. package/dist/cli/project-connector-client.js.map +1 -0
  43. package/dist/cli/project-connector-contracts.js +125 -0
  44. package/dist/cli/project-connector-contracts.js.map +1 -0
  45. package/dist/cli/routes.js +449 -0
  46. package/dist/cli/routes.js.map +1 -0
  47. package/dist/cli/schema.js +18 -0
  48. package/dist/cli/schema.js.map +1 -0
  49. package/dist/node/definition.d.ts +170 -0
  50. package/dist/node/definition.d.ts.map +1 -0
  51. package/dist/node/definition.js +13 -0
  52. package/dist/node/definition.js.map +1 -0
  53. package/dist/node/index.d.ts +456 -0
  54. package/dist/node/index.d.ts.map +1 -0
  55. package/dist/node/index.js +36 -0
  56. package/dist/node/index.js.map +1 -0
  57. package/dist/node/project-connector-client.d.ts +13 -0
  58. package/dist/node/project-connector-client.d.ts.map +1 -0
  59. package/dist/node/project-connector-client.js +235 -0
  60. package/dist/node/project-connector-client.js.map +1 -0
  61. package/dist/node/project-connector-contracts.d.ts +179 -0
  62. package/dist/node/project-connector-contracts.d.ts.map +1 -0
  63. package/dist/node/project-connector-contracts.js +125 -0
  64. package/dist/node/project-connector-contracts.js.map +1 -0
  65. package/dist/node/routes.d.ts +307 -0
  66. package/dist/node/routes.d.ts.map +1 -0
  67. package/dist/node/routes.js +449 -0
  68. package/dist/node/routes.js.map +1 -0
  69. package/dist/node/schema.d.ts +49 -0
  70. package/dist/node/schema.d.ts.map +1 -0
  71. package/dist/node/schema.js +18 -0
  72. package/dist/node/schema.js.map +1 -0
  73. package/dist/node/testing/project-connector-test-gateway.d.ts +63 -0
  74. package/dist/node/testing/project-connector-test-gateway.d.ts.map +1 -0
  75. package/dist/node/testing/project-connector-test-gateway.js +370 -0
  76. package/dist/node/testing/project-connector-test-gateway.js.map +1 -0
  77. 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.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
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
  }