Add API package
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
|||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
dist_*/
|
||||||
|
dist_ts/
|
||||||
|
coverage/
|
||||||
|
.nyc_output/
|
||||||
|
.nogit/
|
||||||
|
.playwright-mcp/
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "@smarthome.exchange/api",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": false,
|
||||||
|
"description": "Typed API client for smarthome.exchange hubs.",
|
||||||
|
"exports": {
|
||||||
|
".": "./dist_ts/index.js"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"author": "Task Venture Capital GmbH",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"test": "tstest test/ --verbose --logfile --timeout 60",
|
||||||
|
"build": "tsbuild tsfolders --allowimplicitany",
|
||||||
|
"buildDocs": "tsdoc"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@api.global/typedrequest": "^3.3.0",
|
||||||
|
"@api.global/typedrequest-interfaces": "^3.0.19",
|
||||||
|
"@api.global/typedsocket": "^4.1.2",
|
||||||
|
"@push.rocks/smartpromise": "^4.2.4",
|
||||||
|
"@smarthome.exchange/interfaces": "workspace:*"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@git.zone/tsbuild": "^4.4.0",
|
||||||
|
"@git.zone/tsdoc": "^2.0.3",
|
||||||
|
"@git.zone/tsrun": "^2.0.3",
|
||||||
|
"@git.zone/tstest": "^3.6.3",
|
||||||
|
"@types/node": "^25.6.0"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"ts/**/*",
|
||||||
|
"dist/**/*",
|
||||||
|
"dist_*/**/*",
|
||||||
|
"dist_ts/**/*",
|
||||||
|
"readme.md",
|
||||||
|
"changelog.md",
|
||||||
|
"license"
|
||||||
|
],
|
||||||
|
"browserslist": [
|
||||||
|
"last 1 chrome versions"
|
||||||
|
],
|
||||||
|
"packageManager": "pnpm@10.28.2"
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# @smarthome.exchange/api
|
||||||
|
|
||||||
|
Typed API client for connecting tools, CLIs, and apps to a smarthome.exchange hub.
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
|
import { SmarthomeExchangeApiClient } from '../ts/index.js';
|
||||||
|
|
||||||
|
tap.test('creates an API client', async () => {
|
||||||
|
const client = new SmarthomeExchangeApiClient({ hubUrl: 'http://localhost:8080/' });
|
||||||
|
expect(client).toBeInstanceOf(SmarthomeExchangeApiClient);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default tap.start();
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import * as plugins from './plugins.js';
|
||||||
|
|
||||||
|
export interface IShxApiClientOptions {
|
||||||
|
hubUrl?: string;
|
||||||
|
useSocket?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SmarthomeExchangeApiClient {
|
||||||
|
private hubUrl: string;
|
||||||
|
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||||||
|
public typedsocketClient?: plugins.typedsocket.TypedSocket;
|
||||||
|
|
||||||
|
constructor(optionsArg: IShxApiClientOptions = {}) {
|
||||||
|
this.hubUrl = (optionsArg.hubUrl || 'http://localhost:8080').replace(/\/$/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
private get httpEndpoint() {
|
||||||
|
return `${this.hubUrl}/typedrequest`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private createWsRequest<T extends plugins.typedRequestInterfaces.ITypedRequest>(operationArg: string) {
|
||||||
|
return this.typedsocketClient?.createTypedRequest<T>(operationArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createHttpRequest<T extends plugins.typedRequestInterfaces.ITypedRequest>(operationArg: string) {
|
||||||
|
return new plugins.typedrequest.TypedRequest<T>(this.httpEndpoint, operationArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async fire<T extends plugins.typedRequestInterfaces.ITypedRequest>(
|
||||||
|
operationArg: string,
|
||||||
|
payloadArg: T['request']
|
||||||
|
): Promise<T['response']> {
|
||||||
|
const wsRequest = this.createWsRequest<T>(operationArg);
|
||||||
|
if (wsRequest) {
|
||||||
|
return wsRequest.fire(payloadArg);
|
||||||
|
}
|
||||||
|
return this.createHttpRequest<T>(operationArg).fire(payloadArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async start() {
|
||||||
|
this.typedsocketClient = await plugins.typedsocket.TypedSocket.createClient(
|
||||||
|
this.typedrouter,
|
||||||
|
this.hubUrl
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async stop() {
|
||||||
|
await this.typedsocketClient?.stop();
|
||||||
|
this.typedsocketClient = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async listDevices(requestArg: plugins.shxInterfaces.request.IReq_ListDevices['request'] = {}) {
|
||||||
|
return this.fire<plugins.shxInterfaces.request.IReq_ListDevices>('listDevices', requestArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async listAgents() {
|
||||||
|
return this.fire<plugins.shxInterfaces.request.IReq_ListAgents>('listAgents', {});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async listTools(requestArg: plugins.shxInterfaces.request.IReq_ListTools['request'] = {}) {
|
||||||
|
return this.fire<plugins.shxInterfaces.request.IReq_ListTools>('listTools', requestArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getHomeSnapshot() {
|
||||||
|
return this.fire<plugins.shxInterfaces.request.IReq_GetHomeSnapshot>('getHomeSnapshot', {});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async executeToolPlan(planArg: plugins.shxInterfaces.data.IToolPlan) {
|
||||||
|
return this.fire<plugins.shxInterfaces.request.IReq_ExecuteToolPlan>('executeToolPlan', {
|
||||||
|
plan: planArg,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async listApprovals(requestArg: plugins.shxInterfaces.request.IReq_ListApprovals['request'] = {}) {
|
||||||
|
return this.fire<plugins.shxInterfaces.request.IReq_ListApprovals>('listApprovals', requestArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async submitApproval(requestArg: plugins.shxInterfaces.request.IReq_SubmitApproval['request']) {
|
||||||
|
return this.fire<plugins.shxInterfaces.request.IReq_SubmitApproval>('submitApproval', requestArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './classes.smarthomeexchangeapiclient.js';
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Project scope
|
||||||
|
import * as shxInterfaces from '@smarthome.exchange/interfaces';
|
||||||
|
|
||||||
|
export { shxInterfaces };
|
||||||
|
|
||||||
|
// @api.global scope
|
||||||
|
import * as typedrequest from '@api.global/typedrequest';
|
||||||
|
import * as typedRequestInterfaces from '@api.global/typedrequest-interfaces';
|
||||||
|
import * as typedsocket from '@api.global/typedsocket';
|
||||||
|
|
||||||
|
export { typedrequest, typedRequestInterfaces, typedsocket };
|
||||||
|
|
||||||
|
// @push.rocks scope
|
||||||
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
|
|
||||||
|
export { smartpromise };
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"types": ["node"]
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"dist_*/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user