@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 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}),C=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{getConnectorState:e=>p(s,g,i,t.viewerDID,e),getConnectorStates:()=>Promise.all(g.list().map(e=>p(s,g,i,t.viewerDID,e))),startConnectorAuth:e=>C.startAuth(e),completeConnectorAuth:e=>C.completeAuth(e,t.viewerDID,i),triggerConnectorSync: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},subscribeToConnectorSyncEvents: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)}()},executeConnectorAction: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};
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
- getConnectorState: (name: string) => Promise<ConnectorState>;
98
- getConnectorStates: () => Promise<Array<ConnectorState>>;
99
- startConnectorAuth: (args: StartConnectorAuthInput) => Promise<StartConnectorAuthOutput>;
100
- completeConnectorAuth: (args: CompleteConnectorAuthInput) => Promise<CompleteConnectorAuthOutput>;
101
- triggerConnectorSync: (args: SyncTriggerInput) => Promise<SyncTriggerOutput>;
102
- subscribeToConnectorSyncEvents: (connector?: string | null) => AsyncIterable<ConnectorSyncEventResult>;
103
- executeConnectorAction?: (args: ConnectorActionInput) => Promise<ConnectorActionResult>;
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(n){let o=n.registry,r=[];r.push(`
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 c=[];if(null!=o){let t=new Set;for(let n of o.getAll()){if(null==n.actions||0===n.actions.length)continue;let o=n.actions.some(t=>"create"===t.name),i=n.actions.some(t=>"update"===t.name);if(o||i)for(let s of e(n).filter(t=>"ExternalEntity"!==t))t.has(s)||(t.add(s),r.push(`
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&&(r.push(`
85
+ `)),o&&(c.push(`
86
86
  input ConnectorCreate${s}Input {
87
87
  input: JSON!
88
88
  }
89
- `),c.push(` connectorCreate${s}(input: ConnectorCreate${s}Input!): Connector${s}Payload!`)),i&&(r.push(`
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
- `),c.push(` connectorUpdate${s}(input: ConnectorUpdate${s}Input!): Connector${s}Payload!`))}}c.length>0&&r.push(`extend type Mutation {
95
- ${c.join("\n")}
96
- }`);let i=r.join("\n"),s={startConnectorAuth:(t,e,n)=>n.startConnectorAuth(e),completeConnectorAuth:(t,e,n)=>n.completeConnectorAuth(e),syncConnector:(t,e,n)=>n.triggerConnectorSync(e)};if(null!=o)for(let t of o.getAll()){if(null==t.actions||0===t.actions.length)continue;let n=t.actions.some(t=>"create"===t.name),o=t.actions.some(t=>"update"===t.name);if(n||o)for(let r of e(t).filter(t=>"ExternalEntity"!==t)){if(n){let e=t.name;s[`connectorCreate${r}`]=async(t,n,o)=>{if(null==o.executeConnectorAction)throw Error("executeConnectorAction is not available in this context");let c=n.input;return await o.executeConnectorAction({connector:e,action:"create",model:r,input:c.input})}}if(o){let e=t.name;s[`connectorUpdate${r}`]=async(t,n,o)=>{if(null==o.executeConnectorAction)throw Error("executeConnectorAction is not available in this context");let c=n.input;return await o.executeConnectorAction({connector:e,action:"update",model:r,input:c.input,sourceID:c.sourceID})}}}}return{sdl:i,resolvers:{queryFields:{connector:(t,e,n)=>n.getConnectorState(e.name),connectors:(t,e,n)=>n.getConnectorStates()},mutationFields:s,subscriptionFields:{connectorSyncEvents:{resolve:t=>t,subscribe:(t,e,n)=>n.subscribeToConnectorSyncEvents(e.connector)}},typeFields:{Connector:{id:e=>t.create("connector","Connector",e.name).toString()}},nodeResolvers:{Connector:{resolve:(t,e)=>e.getConnectorState(t)}}}}}
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.8.1",
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.14.0",
18
- "@enkaku/event": "^0.14.1",
19
- "@enkaku/generator": "^0.14.0",
20
- "@enkaku/runtime": "^0.14.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.16",
24
- "@kubun/connector": "^0.8.0",
25
- "@kubun/db": "^0.8.1",
26
- "@kubun/store-graph": "^0.8.0",
27
- "@kubun/graphql": "^0.8.1",
28
- "@kubun/logger": "^0.8.0",
29
- "@kubun/id": "^0.8.0",
30
- "@kubun/store-connector": "^0.8.0",
31
- "@kubun/engine": "^0.8.1",
32
- "@kubun/protocol": "^0.8.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/test-utils": "^0.8.0",
38
- "@kubun/db-postgres": "^0.8.1"
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",