@kubun/plugin-connector 0.8.1 → 0.9.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/lib/index.js +1 -1
- package/lib/schema.d.ts +15 -7
- package/lib/schema.js +7 -7
- package/package.json +17 -17
package/lib/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fromEmitter as e}from"@enkaku/generator";import{connectorStoreDefinition as t}from"@kubun/store-connector";import{executeAction as r}from"./action.js";import{createConnectorAPI as n}from"./api.js";import{DBCredentialProvider as o}from"./credential.js";import{ConnectorManager as c}from"./manager.js";import{OAuthService as s}from"./oauth.js";import{ConnectorRegistry as i}from"./registry.js";import{createConnectorSchemaExtension as a,toConnectorSyncEventResult as u}from"./schema.js";import{orchestrateSync as l}from"./sync/orchestrate.js";import{DBSyncStateStore as m}from"./sync/state.js";export{executeAction}from"./action.js";export{ConnectorManager}from"./manager.js";export{OAuthService}from"./oauth.js";export{ConnectorRegistry}from"./registry.js";export{createConnectorSchemaExtension,toConnectorSyncEventResult}from"./schema.js";export{SyncEngine}from"./sync/engine.js";export{orchestrateSync}from"./sync/orchestrate.js";export{EntityProcessor}from"./sync/processor.js";export{DBSyncStateStore}from"./sync/state.js";async function p(e,t,r,n,o){let c=t.get(o);if(null==c)throw Error(`Connector "${o}" not found`);let s=await e.getSyncState(o,n),i=!1,a=!1,u=null;if("device"!==c.auth.provider){let e=await r.get(c.auth.provider,n);if(null!=e){i=!0,null!=e.expiresAt&&(u=e.expiresAt.toISOString());let t=c.auth;a=null==t.writeScopes||t.writeScopes.every(t=>e.scopes.includes(t))}}return null==s?{name:o,status:"IDLE",authenticated:i,hasWriteAccess:a,authExpiresAt:u,lastSyncedAt:null,entityCount:null,error:null}:{name:o,status:"idle"===s.status?"IDLE":"syncing"===s.status?"SYNCING":"ERROR",authenticated:i,hasWriteAccess:a,authExpiresAt:u,lastSyncedAt:s.lastSyncedAt??null,entityCount:s.entityCount??null,error:s.error??null}}export function createConnectorPlugin(y){let f=y.providers??[];return d=>{d.db.register(t);let g=new i;for(let e of y.connectors)g.register(e);let S=n({stores:d.db}),D=new o({api:S,runtime:d.runtime,providers:f}),h=new m({api:S}),w=new c({registry:g,logger:d.getLogger("connector"),defaults:y.defaults}),
|
|
1
|
+
import{fromEmitter as e}from"@enkaku/generator";import{connectorStoreDefinition as t}from"@kubun/store-connector";import{executeAction as r}from"./action.js";import{createConnectorAPI as n}from"./api.js";import{DBCredentialProvider as o}from"./credential.js";import{ConnectorManager as c}from"./manager.js";import{OAuthService as s}from"./oauth.js";import{ConnectorRegistry as i}from"./registry.js";import{createConnectorSchemaExtension as a,toConnectorSyncEventResult as u}from"./schema.js";import{orchestrateSync as l}from"./sync/orchestrate.js";import{DBSyncStateStore as m}from"./sync/state.js";export{executeAction}from"./action.js";export{ConnectorManager}from"./manager.js";export{OAuthService}from"./oauth.js";export{ConnectorRegistry}from"./registry.js";export{createConnectorSchemaExtension,toConnectorSyncEventResult}from"./schema.js";export{SyncEngine}from"./sync/engine.js";export{orchestrateSync}from"./sync/orchestrate.js";export{EntityProcessor}from"./sync/processor.js";export{DBSyncStateStore}from"./sync/state.js";async function p(e,t,r,n,o){let c=t.get(o);if(null==c)throw Error(`Connector "${o}" not found`);let s=await e.getSyncState(o,n),i=!1,a=!1,u=null;if("device"!==c.auth.provider){let e=await r.get(c.auth.provider,n);if(null!=e){i=!0,null!=e.expiresAt&&(u=e.expiresAt.toISOString());let t=c.auth;a=null==t.writeScopes||t.writeScopes.every(t=>e.scopes.includes(t))}}return null==s?{name:o,status:"IDLE",authenticated:i,hasWriteAccess:a,authExpiresAt:u,lastSyncedAt:null,entityCount:null,error:null}:{name:o,status:"idle"===s.status?"IDLE":"syncing"===s.status?"SYNCING":"ERROR",authenticated:i,hasWriteAccess:a,authExpiresAt:u,lastSyncedAt:s.lastSyncedAt??null,entityCount:s.entityCount??null,error:s.error??null}}export function createConnectorPlugin(y){let f=y.providers??[];return d=>{d.db.register(t);let g=new i;for(let e of y.connectors)g.register(e);let S=n({stores:d.db}),D=new o({api:S,runtime:d.runtime,providers:f}),h=new m({api:S}),w=new c({registry:g,logger:d.getLogger("connector"),defaults:y.defaults}),j=new s({runtime:d.runtime,providers:f,registry:g,credentialProvider:D});return{name:"connector",schemaExtension:e=>a({registry:g,config:e}),api:S,createContextFactory:()=>(t,c)=>{let s=n({stores:c}),i=new o({api:s,runtime:d.runtime,providers:f});return{getState:e=>p(s,g,i,t.viewerDID,e),getStates:()=>Promise.all(g.list().map(e=>p(s,g,i,t.viewerDID,e))),startAuth:e=>j.startAuth(e),completeAuth:e=>j.completeAuth(e,t.viewerDID,i),triggerSync:async e=>g.has(e.connector)?(c.onCommit(()=>{l({connectorName:e.connector,full:e.full??!1,registry:g,syncEventEmitter:w,stateStore:h,credentialProvider:D,ownerDID:t.viewerDID,stores:d.db,boundary:y.defaults?.boundary}).catch(()=>{})}),{status:"STARTED",connectorName:e.connector}):{status:"ERROR",connectorName:e.connector},subscribeToSyncEvents:t=>{let r=null!=t?e=>e.connectorName===t:void 0,n=e(w.syncEvents,"sync",{filter:r});return async function*(){for await(let e of n)yield u(e)}()},executeAction:async e=>{try{let n=await r({connector:e.connector,action:e.action,model:e.model,input:e.input,sourceID:e.sourceID},{stores:c,registry:g,credentialProvider:i,ownerDID:t.viewerDID});return{documentID:n.documentID,entity:n.entity,error:null}}catch(t){let e=t.code??"API_ERROR";return{documentID:null,entity:null,error:{code:e,message:t instanceof Error?t.message:String(t),requiredScopes:t.requiredScopes}}}}}}}}}export{o as DBCredentialProvider};
|
package/lib/schema.d.ts
CHANGED
|
@@ -92,16 +92,24 @@ export declare function toConnectorSyncEventResult(event: ConnectorSyncEventPayl
|
|
|
92
92
|
/**
|
|
93
93
|
* Per-request context methods for the Connector query and mutation fields.
|
|
94
94
|
* Provided by the context factory when registry + credentials are configured.
|
|
95
|
+
*
|
|
96
|
+
* Fields land on the GraphQL resolver context under `ctx.connector` via the
|
|
97
|
+
* `declare module '@kubun/graphql'` augmentation below.
|
|
95
98
|
*/
|
|
96
99
|
export type ConnectorQueryContext = {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
getState: (name: string) => Promise<ConnectorState>;
|
|
101
|
+
getStates: () => Promise<Array<ConnectorState>>;
|
|
102
|
+
startAuth: (args: StartConnectorAuthInput) => Promise<StartConnectorAuthOutput>;
|
|
103
|
+
completeAuth: (args: CompleteConnectorAuthInput) => Promise<CompleteConnectorAuthOutput>;
|
|
104
|
+
triggerSync: (args: SyncTriggerInput) => Promise<SyncTriggerOutput>;
|
|
105
|
+
subscribeToSyncEvents: (connector?: string | null) => AsyncIterable<ConnectorSyncEventResult>;
|
|
106
|
+
executeAction?: (args: ConnectorActionInput) => Promise<ConnectorActionResult>;
|
|
104
107
|
};
|
|
108
|
+
declare module '@kubun/graphql' {
|
|
109
|
+
interface PluginContextMap {
|
|
110
|
+
connector: ConnectorQueryContext;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
105
113
|
export type ConnectorExtensionConfig = {
|
|
106
114
|
connectors?: Array<string>;
|
|
107
115
|
};
|
package/lib/schema.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{PluginNodeID as t}from"@kubun/id";export function toConnectorSyncEventResult(t){return{type:"started"===t.type?"STARTED":"progress"===t.type?"PROGRESS":"completed"===t.type?"COMPLETED":"ERROR",connectorName:t.connectorName,entitiesProcessed:t.entitiesProcessed??null,entitiesFailed:t.entitiesFailed??null,totalProcessed:t.totalProcessed??null,totalFailed:t.totalFailed??null,duration:t.duration??null,error:t.error??null}}function e(t){let e=[];for(let n of Object.values(t.clusters))for(let t of Object.values(n.record)){let o=n.models[t];o?.name==null||e.includes(o.name)||e.push(o.name)}return e}export function createConnectorSchemaExtension(
|
|
1
|
+
import{PluginNodeID as t}from"@kubun/id";export function toConnectorSyncEventResult(t){return{type:"started"===t.type?"STARTED":"progress"===t.type?"PROGRESS":"completed"===t.type?"COMPLETED":"ERROR",connectorName:t.connectorName,entitiesProcessed:t.entitiesProcessed??null,entitiesFailed:t.entitiesFailed??null,totalProcessed:t.totalProcessed??null,totalFailed:t.totalFailed??null,duration:t.duration??null,error:t.error??null}}function e(t){if(null==t.connector)throw Error("connector plugin is not wired into this context");return t.connector}function n(t){let e=[];for(let n of Object.values(t.clusters))for(let t of Object.values(n.record)){let o=n.models[t];o?.name==null||e.includes(o.name)||e.push(o.name)}return e}export function createConnectorSchemaExtension(o){let r=o.registry,c=[];c.push(`
|
|
2
2
|
enum ConnectorSyncStatus {
|
|
3
3
|
IDLE
|
|
4
4
|
SYNCING
|
|
@@ -76,21 +76,21 @@ extend type Mutation {
|
|
|
76
76
|
extend type Subscription {
|
|
77
77
|
connectorSyncEvents(connector: String): ConnectorSyncEvent!
|
|
78
78
|
}
|
|
79
|
-
`);let
|
|
79
|
+
`);let i=[];if(null!=r){let t=new Set;for(let e of r.getAll()){if(null==e.actions||0===e.actions.length)continue;let o=e.actions.some(t=>"create"===t.name),r=e.actions.some(t=>"update"===t.name);if(o||r)for(let s of n(e).filter(t=>"ExternalEntity"!==t))t.has(s)||(t.add(s),c.push(`
|
|
80
80
|
type Connector${s}Payload {
|
|
81
81
|
documentID: String
|
|
82
82
|
entity: JSON
|
|
83
83
|
error: ConnectorActionError
|
|
84
84
|
}
|
|
85
|
-
`)),o&&(
|
|
85
|
+
`)),o&&(c.push(`
|
|
86
86
|
input ConnectorCreate${s}Input {
|
|
87
87
|
input: JSON!
|
|
88
88
|
}
|
|
89
|
-
`),
|
|
89
|
+
`),i.push(` connectorCreate${s}(input: ConnectorCreate${s}Input!): Connector${s}Payload!`)),r&&(c.push(`
|
|
90
90
|
input ConnectorUpdate${s}Input {
|
|
91
91
|
sourceID: String!
|
|
92
92
|
input: JSON!
|
|
93
93
|
}
|
|
94
|
-
`),
|
|
95
|
-
${
|
|
96
|
-
}`);let
|
|
94
|
+
`),i.push(` connectorUpdate${s}(input: ConnectorUpdate${s}Input!): Connector${s}Payload!`))}}i.length>0&&c.push(`extend type Mutation {
|
|
95
|
+
${i.join("\n")}
|
|
96
|
+
}`);let s=c.join("\n"),l={startConnectorAuth:(t,n,o)=>e(o).startAuth(n),completeConnectorAuth:(t,n,o)=>e(o).completeAuth(n),syncConnector:(t,n,o)=>e(o).triggerSync(n)};if(null!=r)for(let t of r.getAll()){if(null==t.actions||0===t.actions.length)continue;let o=t.actions.some(t=>"create"===t.name),r=t.actions.some(t=>"update"===t.name);if(o||r)for(let c of n(t).filter(t=>"ExternalEntity"!==t)){if(o){let n=t.name;l[`connectorCreate${c}`]=async(t,o,r)=>{let i=e(r);if(null==i.executeAction)throw Error("connector.executeAction is not available in this context");let s=o.input;return await i.executeAction({connector:n,action:"create",model:c,input:s.input})}}if(r){let n=t.name;l[`connectorUpdate${c}`]=async(t,o,r)=>{let i=e(r);if(null==i.executeAction)throw Error("connector.executeAction is not available in this context");let s=o.input;return await i.executeAction({connector:n,action:"update",model:c,input:s.input,sourceID:s.sourceID})}}}}return{sdl:s,resolvers:{queryFields:{connector:(t,n,o)=>e(o).getState(n.name),connectors:(t,n,o)=>e(o).getStates()},mutationFields:l,subscriptionFields:{connectorSyncEvents:{resolve:t=>t,subscribe:(t,n,o)=>e(o).subscribeToSyncEvents(n.connector)}},typeFields:{Connector:{id:e=>t.create("connector","Connector",e.name).toString()}},nodeResolvers:{Connector:{resolve:(t,n)=>e(n).getState(t)}}}}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubun/plugin-connector",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"license": "see LICENSE.md",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -14,28 +14,28 @@
|
|
|
14
14
|
],
|
|
15
15
|
"sideEffects": false,
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@enkaku/async": "^0.
|
|
18
|
-
"@enkaku/event": "^0.
|
|
19
|
-
"@enkaku/generator": "^0.
|
|
20
|
-
"@enkaku/runtime": "^0.
|
|
17
|
+
"@enkaku/async": "^0.15.0",
|
|
18
|
+
"@enkaku/event": "^0.15.0",
|
|
19
|
+
"@enkaku/generator": "^0.15.0",
|
|
20
|
+
"@enkaku/runtime": "^0.15.0",
|
|
21
21
|
"graphql": "^16.13.2",
|
|
22
22
|
"graphql-scalars": "^1.25.0",
|
|
23
|
-
"kysely": "^0.28.
|
|
24
|
-
"@kubun/connector": "^0.
|
|
25
|
-
"@kubun/db": "^0.
|
|
26
|
-
"@kubun/store-graph": "^0.
|
|
27
|
-
"@kubun/
|
|
28
|
-
"@kubun/
|
|
29
|
-
"@kubun/
|
|
30
|
-
"@kubun/
|
|
31
|
-
"@kubun/
|
|
32
|
-
"@kubun/protocol": "^0.
|
|
23
|
+
"kysely": "^0.28.17",
|
|
24
|
+
"@kubun/connector": "^0.9.0",
|
|
25
|
+
"@kubun/db": "^0.9.0",
|
|
26
|
+
"@kubun/store-graph": "^0.9.0",
|
|
27
|
+
"@kubun/store-connector": "^0.9.0",
|
|
28
|
+
"@kubun/engine": "^0.9.0",
|
|
29
|
+
"@kubun/graphql": "^0.9.0",
|
|
30
|
+
"@kubun/id": "^0.9.0",
|
|
31
|
+
"@kubun/logger": "^0.9.0",
|
|
32
|
+
"@kubun/protocol": "^0.9.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@testcontainers/postgresql": "^11.14.0",
|
|
36
36
|
"get-port": "^7.2.0",
|
|
37
|
-
"@kubun/
|
|
38
|
-
"@kubun/
|
|
37
|
+
"@kubun/db-postgres": "^0.9.0",
|
|
38
|
+
"@kubun/test-utils": "^0.9.0"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build:clean": "del lib",
|