stellarium-ts 0.1.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/README.md +3 -0
- package/dist/db/db.d.ts +5 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +52 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/peer/repository.d.ts +13 -0
- package/dist/peer/repository.d.ts.map +1 -0
- package/dist/peer/repository.js +25 -0
- package/dist/resource/invoker.d.ts +15 -0
- package/dist/resource/invoker.d.ts.map +1 -0
- package/dist/resource/invoker.js +43 -0
- package/dist/resource/resolver.d.ts +14 -0
- package/dist/resource/resolver.d.ts.map +1 -0
- package/dist/resource/resolver.js +15 -0
- package/dist/resource/resource.d.ts +16 -0
- package/dist/resource/resource.d.ts.map +1 -0
- package/dist/resource/resource.js +78 -0
- package/dist/routes.d.ts +13 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +57 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +32 -0
- package/dist/service.d.ts +11 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +16 -0
- package/dist/startup.d.ts +10 -0
- package/dist/startup.d.ts.map +1 -0
- package/dist/startup.js +41 -0
- package/package.json +53 -0
package/README.md
ADDED
package/dist/db/db.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAG9B,QAAA,MAAM,EAAE,gEAGN,CAAC;AAIH,wBAAsB,YAAY,kBA2CjC;eAGc,EAAE"}
|
package/dist/db/db.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import sqlite3 from 'sqlite3';
|
|
2
|
+
import { open } from 'sqlite';
|
|
3
|
+
const db = await open({
|
|
4
|
+
filename: './requestscript.db', // Specify the database file
|
|
5
|
+
driver: sqlite3.Database,
|
|
6
|
+
});
|
|
7
|
+
// Create tables
|
|
8
|
+
export async function createTables() {
|
|
9
|
+
await db.exec(`
|
|
10
|
+
CREATE TABLE IF NOT EXISTS peer (
|
|
11
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
12
|
+
base_url TEXT NOT NULL,
|
|
13
|
+
name TEXT NOT NULL,
|
|
14
|
+
created_at TEXT NOT NULL,
|
|
15
|
+
updated_at TEXT NOT NULL,
|
|
16
|
+
|
|
17
|
+
UNIQUE (base_url)
|
|
18
|
+
UNIQUE (name)
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
CREATE TABLE IF NOT EXISTS resources (
|
|
22
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23
|
+
path TEXT NOT NULL,
|
|
24
|
+
name TEXT NOT NULL,
|
|
25
|
+
base_url TEXT NOT NULL,
|
|
26
|
+
created_at TEXT NOT NULL,
|
|
27
|
+
updated_at TEXT NOT NULL,
|
|
28
|
+
|
|
29
|
+
UNIQUE (path, name)
|
|
30
|
+
UNIQUE (base_url)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
CREATE TABLE IF NOT EXISTS resource_functions (
|
|
34
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
35
|
+
resource_id INTEGER NOT NULL,
|
|
36
|
+
name TEXT NOT NULL,
|
|
37
|
+
return_type TEXT NOT NULL,
|
|
38
|
+
created_at TEXT NOT NULL,
|
|
39
|
+
updated_at TEXT NOT NULL
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
CREATE TABLE IF NOT EXISTS resource_function_parameters (
|
|
43
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
44
|
+
resource_function_id INTEGER NOT NULL,
|
|
45
|
+
name TEXT NOT NULL,
|
|
46
|
+
parameter_type TEXT NOT NULL,
|
|
47
|
+
created_at TEXT NOT NULL,
|
|
48
|
+
updated_at TEXT NOT NULL
|
|
49
|
+
);
|
|
50
|
+
`);
|
|
51
|
+
}
|
|
52
|
+
export default db;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StellariumNode } from './server.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Database } from "sqlite";
|
|
2
|
+
export interface Peer {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class PeerRepository {
|
|
7
|
+
private readonly db;
|
|
8
|
+
constructor(db: Database);
|
|
9
|
+
create(peer: Peer): Promise<void>;
|
|
10
|
+
deleteAll(): Promise<void>;
|
|
11
|
+
getPeerList(): Promise<Peer[]>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/peer/repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,MAAM,WAAW,IAAI;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,cAAc;IACX,OAAO,CAAC,QAAQ,CAAC,EAAE;IAA/B,YAA6B,EAAE,EAAE,QAAQ,EAAI;IAEvC,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBtC;IAEK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAE/B;IAEK,WAAW,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAMnC;CACJ"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export class PeerRepository {
|
|
2
|
+
db;
|
|
3
|
+
constructor(db) {
|
|
4
|
+
this.db = db;
|
|
5
|
+
}
|
|
6
|
+
async create(peer) {
|
|
7
|
+
// Check if the peer already exists
|
|
8
|
+
const existingPeer = await this.db.get('SELECT * FROM peer WHERE base_url = ?', [peer.baseUrl, peer.name]);
|
|
9
|
+
if (existingPeer) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const createdAt = new Date().toISOString();
|
|
13
|
+
await this.db.run('INSERT INTO peer (base_url, name, created_at, updated_at) VALUES (?, ?, ?, ?)', [peer.baseUrl, peer.name, createdAt, createdAt]);
|
|
14
|
+
}
|
|
15
|
+
async deleteAll() {
|
|
16
|
+
await this.db.run('DELETE FROM peer');
|
|
17
|
+
}
|
|
18
|
+
async getPeerList() {
|
|
19
|
+
const results = await this.db.all('SELECT * FROM peer');
|
|
20
|
+
return results.map(result => ({
|
|
21
|
+
baseUrl: result.base_url,
|
|
22
|
+
name: result.name,
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Resource, ResourceFunctionCallParameter, ResourceInvoker } from "requestscript";
|
|
2
|
+
export declare class CombinationResourceInvoker implements ResourceInvoker {
|
|
3
|
+
/**
|
|
4
|
+
* Invoke a function on a resource.
|
|
5
|
+
* If the resource has a baseUrl, it will be invoked as a remote function.
|
|
6
|
+
* Otherwise, it will be invoked as a local function.
|
|
7
|
+
*
|
|
8
|
+
* @param resource - The resource to invoke
|
|
9
|
+
* @param functionName - The name of the function to invoke
|
|
10
|
+
* @param parameters - The parameters to pass to the function
|
|
11
|
+
* @returns The return value of the function
|
|
12
|
+
*/
|
|
13
|
+
invoke(resource: Resource, functionName: string, parameters: ResourceFunctionCallParameter[]): Promise<any>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=invoker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoker.d.ts","sourceRoot":"","sources":["../../src/resource/invoker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,6BAA6B,EAA6B,eAAe,EAAE,MAAM,eAAe,CAAC;AAEpH,qBAAa,0BAA2B,YAAW,eAAe;IAE9D;;;;;;;;;OASG;IACG,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,6BAA6B,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAoChH;CACJ"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export class CombinationResourceInvoker {
|
|
2
|
+
/**
|
|
3
|
+
* Invoke a function on a resource.
|
|
4
|
+
* If the resource has a baseUrl, it will be invoked as a remote function.
|
|
5
|
+
* Otherwise, it will be invoked as a local function.
|
|
6
|
+
*
|
|
7
|
+
* @param resource - The resource to invoke
|
|
8
|
+
* @param functionName - The name of the function to invoke
|
|
9
|
+
* @param parameters - The parameters to pass to the function
|
|
10
|
+
* @returns The return value of the function
|
|
11
|
+
*/
|
|
12
|
+
async invoke(resource, functionName, parameters) {
|
|
13
|
+
if (resource.metadata.baseUrl) {
|
|
14
|
+
const query = `
|
|
15
|
+
request Invoke${resource.name}${functionName} {
|
|
16
|
+
const ${resource.name.toLowerCase()} = ${resource.path}.${resource.name}
|
|
17
|
+
|
|
18
|
+
return ${resource.name.toLowerCase()}.${functionName}(${parameters.map(p => `${p.name}: ${p.value}`).join(', ')})
|
|
19
|
+
}`;
|
|
20
|
+
console.log(query);
|
|
21
|
+
const url = resource.metadata.baseUrl;
|
|
22
|
+
if (!url) {
|
|
23
|
+
throw new Error(`Resource ${resource.name} does not have a url`);
|
|
24
|
+
}
|
|
25
|
+
const result = await fetch(`${url}/run`, {
|
|
26
|
+
method: 'POST',
|
|
27
|
+
body: query,
|
|
28
|
+
});
|
|
29
|
+
if (!result.ok) {
|
|
30
|
+
throw new Error(`Failed to invoke ${resource.name}.${functionName}: ${result.statusText}`);
|
|
31
|
+
}
|
|
32
|
+
const data = await result.json();
|
|
33
|
+
return data.returnValue;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const fn = resource.functions.find(f => f.name === functionName);
|
|
37
|
+
if (!fn) {
|
|
38
|
+
throw new Error(`Function ${functionName} not found in resource ${resource.name}`);
|
|
39
|
+
}
|
|
40
|
+
return await fn.exec(parameters);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Resource, ResourceResolver } from "requestscript";
|
|
2
|
+
import { ResourceRepository } from "./resource.js";
|
|
3
|
+
/**
|
|
4
|
+
* CombinationResourceResolver is a resource resolver that combines multiple resource resolvers.
|
|
5
|
+
* It will first try to resolve the resource from the resource repository.
|
|
6
|
+
* If the resource is not found, it will try to resolve the resource from the external resource resolvers.
|
|
7
|
+
* If the resource is not found, it will return undefined.
|
|
8
|
+
*/
|
|
9
|
+
export declare class CombinationResourceResolver implements ResourceResolver {
|
|
10
|
+
private readonly resourceRepository;
|
|
11
|
+
constructor(resourceRepository: ResourceRepository);
|
|
12
|
+
resolve(key: string): Promise<Resource | undefined>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/resource/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;;GAKG;AACH,qBAAa,2BAA4B,YAAW,gBAAgB;IACpD,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAA/C,YAA6B,kBAAkB,EAAE,kBAAkB,EAAI;IAEjE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAExD;CACJ"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CombinationResourceResolver is a resource resolver that combines multiple resource resolvers.
|
|
3
|
+
* It will first try to resolve the resource from the resource repository.
|
|
4
|
+
* If the resource is not found, it will try to resolve the resource from the external resource resolvers.
|
|
5
|
+
* If the resource is not found, it will return undefined.
|
|
6
|
+
*/
|
|
7
|
+
export class CombinationResourceResolver {
|
|
8
|
+
resourceRepository;
|
|
9
|
+
constructor(resourceRepository) {
|
|
10
|
+
this.resourceRepository = resourceRepository;
|
|
11
|
+
}
|
|
12
|
+
async resolve(key) {
|
|
13
|
+
return await this.resourceRepository.getResource(key);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Resource, ResourceFunctionParameter } from "requestscript";
|
|
2
|
+
import { Database } from "sqlite";
|
|
3
|
+
export interface ResourceWithBaseUrl extends Resource {
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class ResourceRepository {
|
|
7
|
+
private readonly db;
|
|
8
|
+
private resources;
|
|
9
|
+
constructor(db: Database, resources?: Resource[]);
|
|
10
|
+
create(resource: Resource, baseUrl: string): Promise<void>;
|
|
11
|
+
getResource(key: string): Promise<Resource | undefined>;
|
|
12
|
+
getExternalResources(): Promise<Resource[]>;
|
|
13
|
+
getResourceParameters(resourceFunctionId: number): Promise<ResourceFunctionParameter[]>;
|
|
14
|
+
getAllResources(): Promise<ResourceWithBaseUrl[]>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/resource/resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,MAAM,WAAW,mBAAoB,SAAQ,QAAQ;IACjD,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,kBAAkB;IACf,OAAO,CAAC,QAAQ,CAAC,EAAE;IAAY,OAAO,CAAC,SAAS;IAA5D,YAA6B,EAAE,EAAE,QAAQ,EAAU,SAAS,GAAE,QAAQ,EAAO,EAAI;IAE3E,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/D;IAEK,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAyC5D;IAEK,oBAAoB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAqBhD;IAEK,qBAAqB,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,EAAE,CAAC,CAK5F;IAEK,eAAe,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAWtD;CACJ"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export class ResourceRepository {
|
|
2
|
+
db;
|
|
3
|
+
resources;
|
|
4
|
+
constructor(db, resources = []) {
|
|
5
|
+
this.db = db;
|
|
6
|
+
this.resources = resources;
|
|
7
|
+
}
|
|
8
|
+
async create(resource, baseUrl) {
|
|
9
|
+
const createdAt = new Date().toISOString();
|
|
10
|
+
await this.db.run('INSERT INTO resources (path, name, base_url, created_at, updated_at) VALUES (?, ?, ?, ?, ?)', [resource.path, resource.name, baseUrl, createdAt, createdAt]);
|
|
11
|
+
}
|
|
12
|
+
async getResource(key) {
|
|
13
|
+
const resource = this.resources.find(r => `${r.path}.${r.name}` === key);
|
|
14
|
+
if (resource) {
|
|
15
|
+
return resource;
|
|
16
|
+
}
|
|
17
|
+
// Split the key with format path.path.path.*.Name
|
|
18
|
+
const pathName = key.split('.');
|
|
19
|
+
const name = pathName.pop();
|
|
20
|
+
const path = pathName.join('.');
|
|
21
|
+
const result = await this.db.get('SELECT * FROM resources WHERE path = ? AND name = ?', [path, name]);
|
|
22
|
+
if (!result) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
const resourceFunctions = await this.db.all('SELECT * FROM resource_functions WHERE resource_id = ?', [result.id]);
|
|
26
|
+
return {
|
|
27
|
+
path: result.path,
|
|
28
|
+
name: result.name,
|
|
29
|
+
functions: await Promise.all(resourceFunctions.map(async (f) => ({
|
|
30
|
+
name: f.name,
|
|
31
|
+
returnType: f.return_type,
|
|
32
|
+
parameters: await this.getResourceParameters(f.id),
|
|
33
|
+
// The ExternalResourceInvoker will handle the execution of the function
|
|
34
|
+
exec: async () => {
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
}))),
|
|
38
|
+
metadata: {
|
|
39
|
+
baseUrl: result.base_url,
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async getExternalResources() {
|
|
44
|
+
const results = await this.db.get('SELECT * FROM resources');
|
|
45
|
+
if (!results) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
return Promise.all(results.map(async (r) => ({
|
|
49
|
+
path: r.path,
|
|
50
|
+
name: r.name,
|
|
51
|
+
functions: await Promise.all(r.resource_functions.map(async (f) => ({
|
|
52
|
+
name: f.name,
|
|
53
|
+
returnType: f.return_type,
|
|
54
|
+
parameters: await this.getResourceParameters(f.id),
|
|
55
|
+
}))),
|
|
56
|
+
metadata: {
|
|
57
|
+
baseUrl: r.base_url,
|
|
58
|
+
}
|
|
59
|
+
})));
|
|
60
|
+
}
|
|
61
|
+
async getResourceParameters(resourceFunctionId) {
|
|
62
|
+
return (await this.db.all('SELECT * FROM resource_function_parameters WHERE resource_function_id = ?', [resourceFunctionId])).map(p => ({
|
|
63
|
+
name: p.name,
|
|
64
|
+
type: p.parameter_type,
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
async getAllResources() {
|
|
68
|
+
const externalResources = await this.getExternalResources();
|
|
69
|
+
let resources = [];
|
|
70
|
+
for (const resource of Object.values(this.resources)) {
|
|
71
|
+
resources.push({ ...resource, baseUrl: process.env.BASE_URL });
|
|
72
|
+
}
|
|
73
|
+
for (const resource of externalResources) {
|
|
74
|
+
resources.push({ ...resource, baseUrl: resource.metadata.baseUrl });
|
|
75
|
+
}
|
|
76
|
+
return resources;
|
|
77
|
+
}
|
|
78
|
+
}
|
package/dist/routes.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FastifyPluginAsync } from 'fastify';
|
|
2
|
+
import type { Service } from './service.js';
|
|
3
|
+
interface RouteOptions {
|
|
4
|
+
service: Service;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Encapsulates the routes
|
|
8
|
+
* @param fastify Encapsulated Fastify Instance
|
|
9
|
+
* @param options plugin options, refer to https://fastify.dev/docs/latest/Reference/Plugins/#plugin-options
|
|
10
|
+
*/
|
|
11
|
+
declare const routes: FastifyPluginAsync<RouteOptions>;
|
|
12
|
+
export default routes;
|
|
13
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAI5C,UAAU,YAAY;IAClB,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,QAAA,MAAM,MAAM,EAAE,kBAAkB,CAAC,YAAY,CA2D5C,CAAA;eAGc,MAAM"}
|
package/dist/routes.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { interpretParsed, parseScript } from 'requestscript';
|
|
2
|
+
/**
|
|
3
|
+
* Encapsulates the routes
|
|
4
|
+
* @param fastify Encapsulated Fastify Instance
|
|
5
|
+
* @param options plugin options, refer to https://fastify.dev/docs/latest/Reference/Plugins/#plugin-options
|
|
6
|
+
*/
|
|
7
|
+
const routes = async function (fastify, options) {
|
|
8
|
+
// Start Meta Routes
|
|
9
|
+
fastify.get('/', async (request, reply) => {
|
|
10
|
+
return { hello: 'world' };
|
|
11
|
+
});
|
|
12
|
+
fastify.get('/peers', async (request, reply) => {
|
|
13
|
+
const peers = await options.service.peerRepository.getPeerList();
|
|
14
|
+
return { peers };
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Returns the list of resources that are available on the server.
|
|
18
|
+
* Does not return resources that are external to the server.
|
|
19
|
+
*/
|
|
20
|
+
fastify.get('/resources', async (request, reply) => {
|
|
21
|
+
const resources = await options.service.resourceRepository.getAllResources();
|
|
22
|
+
return {
|
|
23
|
+
resources: resources.map((resource) => ({
|
|
24
|
+
path: resource.path,
|
|
25
|
+
name: resource.name,
|
|
26
|
+
functions: resource.functions.map((fn) => ({
|
|
27
|
+
name: fn.name,
|
|
28
|
+
returnType: fn.returnType,
|
|
29
|
+
parameters: fn.parameters,
|
|
30
|
+
})),
|
|
31
|
+
baseUrl: resource.baseUrl,
|
|
32
|
+
})),
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
// End Meta Routes
|
|
36
|
+
// Start Run Routes
|
|
37
|
+
fastify.post('/run', async (request, reply) => {
|
|
38
|
+
const source = request.body;
|
|
39
|
+
try {
|
|
40
|
+
const script = parseScript(source);
|
|
41
|
+
if (script.declaration.kind !== 'request') {
|
|
42
|
+
return reply.status(400).send({ error: 'Invalid script' });
|
|
43
|
+
}
|
|
44
|
+
const result = await interpretParsed(script, {
|
|
45
|
+
resourceResolver: options.service.resourceResolver,
|
|
46
|
+
resourceInvoker: options.service.resourceInvoker
|
|
47
|
+
});
|
|
48
|
+
reply.status(200).send({ returnValue: result.returnValue ?? null });
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
reply.status(500).send({ error: 'Internal server error' });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
// End Run Routes
|
|
55
|
+
};
|
|
56
|
+
// ESM
|
|
57
|
+
export default routes;
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import { FastifyInstance } from 'fastify';
|
|
3
|
+
import { Resource } from 'requestscript';
|
|
4
|
+
export interface StellariumNodeOptions {
|
|
5
|
+
port?: number;
|
|
6
|
+
startingPeer?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class StellariumNode {
|
|
9
|
+
private resources;
|
|
10
|
+
register(resource: Resource): Promise<void>;
|
|
11
|
+
start(fastify: FastifyInstance, options: StellariumNodeOptions): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AACvB,OAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAInD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,MAAM,WAAW,qBAAqB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,cAAc;IACvB,OAAO,CAAC,SAAS,CAAkB;IAE7B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhD;IAEK,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBnF;CACJ"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import routes from './routes.js';
|
|
3
|
+
import { createService } from './service.js';
|
|
4
|
+
import { StartupService } from './startup.js';
|
|
5
|
+
import { createTables } from './db/db.js';
|
|
6
|
+
export class StellariumNode {
|
|
7
|
+
resources = [];
|
|
8
|
+
async register(resource) {
|
|
9
|
+
this.resources.push(resource);
|
|
10
|
+
}
|
|
11
|
+
async start(fastify, options) {
|
|
12
|
+
;
|
|
13
|
+
const service = createService(this.resources);
|
|
14
|
+
await createTables();
|
|
15
|
+
fastify.register(routes, { prefix: '/v1', service });
|
|
16
|
+
// Run the server!
|
|
17
|
+
fastify.listen({ port: options.port ?? 3000 }, function (err, address) {
|
|
18
|
+
if (err) {
|
|
19
|
+
fastify.log.error(err);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
if (options.startingPeer) {
|
|
23
|
+
const startupService = new StartupService(service, options.startingPeer);
|
|
24
|
+
Promise.resolve(startupService.loadFromPeer()).catch(err => {
|
|
25
|
+
fastify.log.error(err);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
fastify.log.info(`server listening on ${address}`);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Resource, ResourceInvoker, ResourceResolver } from "requestscript";
|
|
2
|
+
import { PeerRepository } from "./peer/repository.js";
|
|
3
|
+
import { ResourceRepository } from "./resource/resource.js";
|
|
4
|
+
export interface Service {
|
|
5
|
+
peerRepository: PeerRepository;
|
|
6
|
+
resourceRepository: ResourceRepository;
|
|
7
|
+
resourceResolver: ResourceResolver;
|
|
8
|
+
resourceInvoker: ResourceInvoker;
|
|
9
|
+
}
|
|
10
|
+
export declare function createService(resources: Resource[]): Service;
|
|
11
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE5E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAG5D,MAAM,WAAW,OAAO;IACpB,cAAc,EAAE,cAAc,CAAC;IAC/B,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,eAAe,EAAE,eAAe,CAAC;CACpC;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAW5D"}
|
package/dist/service.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import db from "./db/db.js";
|
|
2
|
+
import { PeerRepository } from "./peer/repository.js";
|
|
3
|
+
import { CombinationResourceResolver } from "./resource/resolver.js";
|
|
4
|
+
import { ResourceRepository } from "./resource/resource.js";
|
|
5
|
+
import { CombinationResourceInvoker } from "./resource/invoker.js";
|
|
6
|
+
export function createService(resources) {
|
|
7
|
+
const resourceRepository = new ResourceRepository(db, resources);
|
|
8
|
+
const resourceResolver = new CombinationResourceResolver(resourceRepository);
|
|
9
|
+
const resourceInvoker = new CombinationResourceInvoker();
|
|
10
|
+
return {
|
|
11
|
+
peerRepository: new PeerRepository(db),
|
|
12
|
+
resourceRepository,
|
|
13
|
+
resourceResolver,
|
|
14
|
+
resourceInvoker,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Service } from "./service.js";
|
|
2
|
+
export declare class StartupService {
|
|
3
|
+
private readonly service;
|
|
4
|
+
private readonly startingPeer;
|
|
5
|
+
constructor(service: Service, startingPeer: string);
|
|
6
|
+
loadFromPeer(): Promise<void>;
|
|
7
|
+
populatePeers(): Promise<void>;
|
|
8
|
+
populateResources(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=startup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startup.d.ts","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,qBAAa,cAAc;IACX,OAAO,CAAC,QAAQ,CAAC,OAAO;IAAW,OAAO,CAAC,QAAQ,CAAC,YAAY;IAA5E,YAA6B,OAAO,EAAE,OAAO,EAAmB,YAAY,EAAE,MAAM,EAAI;IAGlF,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAGlC;IAEK,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAiBnC;IAEK,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAYvC;CACJ"}
|
package/dist/startup.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export class StartupService {
|
|
2
|
+
service;
|
|
3
|
+
startingPeer;
|
|
4
|
+
constructor(service, startingPeer) {
|
|
5
|
+
this.service = service;
|
|
6
|
+
this.startingPeer = startingPeer;
|
|
7
|
+
}
|
|
8
|
+
// If the peer list is empty, populate it using the peer start parameter.
|
|
9
|
+
async loadFromPeer() {
|
|
10
|
+
await this.populatePeers();
|
|
11
|
+
await this.populateResources();
|
|
12
|
+
}
|
|
13
|
+
async populatePeers() {
|
|
14
|
+
const peerList = await this.service.peerRepository.getPeerList();
|
|
15
|
+
if (peerList.length > 0) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const response = await fetch(`${this.startingPeer}/v1/peers`);
|
|
19
|
+
const data = await response.json();
|
|
20
|
+
if (!data.peers) {
|
|
21
|
+
throw new Error('Invalid response from peer');
|
|
22
|
+
}
|
|
23
|
+
if (data.peers) {
|
|
24
|
+
for (const peer of data.peers) {
|
|
25
|
+
await this.service.peerRepository.create(peer);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async populateResources() {
|
|
30
|
+
const response = await fetch(`${this.startingPeer}/v1/resources`);
|
|
31
|
+
const data = await response.json();
|
|
32
|
+
if (!data.resources) {
|
|
33
|
+
throw new Error('Invalid response from peer');
|
|
34
|
+
}
|
|
35
|
+
if (data.resources) {
|
|
36
|
+
for (const resource of data.resources) {
|
|
37
|
+
await this.service.resourceRepository.create(resource, resource.baseUrl);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stellarium-ts",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A Stellarium Node in TypeScript.",
|
|
5
|
+
"homepage": "https://github.com/qualletio/stellarium-ts#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/qualletio/stellarium-ts/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/qualletio/stellarium-ts.git"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"decentralized",
|
|
31
|
+
"stellarium",
|
|
32
|
+
"requestscript"
|
|
33
|
+
],
|
|
34
|
+
"author": "Christopher Poulsen <christopher.poulsen@quallet.io>",
|
|
35
|
+
"license": "ISC",
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^26.6.4",
|
|
38
|
+
"typescript": "^7.0.2"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"dotenv": "^18.0.5",
|
|
42
|
+
"fastify": "^5.12.5",
|
|
43
|
+
"requestscript": "^1.0.5",
|
|
44
|
+
"sqlite": "^5.1.1",
|
|
45
|
+
"sqlite3": "^6.0.1"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "rm -rf dist && tsc",
|
|
49
|
+
"start": "node dist/server.js",
|
|
50
|
+
"dev": "node --watch src/server.ts",
|
|
51
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
52
|
+
}
|
|
53
|
+
}
|