stellarium-ts 0.13.0 → 0.14.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.
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAE7C,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAS1D,wGAAwG;AACxG,wBAAsB,YAAY,CAAC,QAAQ,GAAE,MAA8B,GAAG,OAAO,CAAC,QAAQ,CAAC,CAI9F;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,QAAQ,iBAsI9C"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAE7C,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAU1D,wGAAwG;AACxG,wBAAsB,YAAY,CAAC,QAAQ,GAAE,MAA8B,GAAG,OAAO,CAAC,QAAQ,CAAC,CAI9F;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,QAAQ,iBA0I9C"}
package/dist/db/db.js CHANGED
@@ -5,8 +5,9 @@ export const DEFAULT_DATABASE_PATH = './requestscript.db';
5
5
  * Bumped whenever the schema changes in a way `CREATE TABLE IF NOT EXISTS` can't apply.
6
6
  * Version 1 dropped `UNIQUE (base_url)` from `resource` and added uniqueness to the function tables.
7
7
  * Version 2 added `resource_function.restricted`.
8
+ * Version 3 added `resource.website` and the `description` columns of the resource tables.
8
9
  */
9
- const SCHEMA_VERSION = 2;
10
+ const SCHEMA_VERSION = 3;
10
11
  /** Opens (or creates) the node database and brings its schema up to date. Pass ':memory:' for tests. */
11
12
  export async function openDatabase(filename = DEFAULT_DATABASE_PATH) {
12
13
  const db = await open({ filename, driver: sqlite3.Database });
@@ -45,6 +46,8 @@ export async function createTables(db) {
45
46
  path TEXT NOT NULL,
46
47
  name TEXT NOT NULL,
47
48
  base_url TEXT NOT NULL,
49
+ website TEXT,
50
+ description TEXT,
48
51
  created_at TEXT NOT NULL,
49
52
  updated_at TEXT NOT NULL,
50
53
 
@@ -58,6 +61,7 @@ export async function createTables(db) {
58
61
  resource_id INTEGER NOT NULL,
59
62
  name TEXT NOT NULL,
60
63
  return_type TEXT NOT NULL,
64
+ description TEXT,
61
65
  restricted INTEGER NOT NULL DEFAULT 0,
62
66
  created_at TEXT NOT NULL,
63
67
  updated_at TEXT NOT NULL,
@@ -72,6 +76,7 @@ export async function createTables(db) {
72
76
  resource_function_id INTEGER NOT NULL,
73
77
  name TEXT NOT NULL,
74
78
  parameter_type TEXT NOT NULL,
79
+ description TEXT,
75
80
  created_at TEXT NOT NULL,
76
81
  updated_at TEXT NOT NULL,
77
82
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { StellariumNode, resolveConfig, type StellariumNodeOptions } from './server.js';
2
2
  export type { NodeConfig } from './service.js';
3
- export type { StellariumResource, StellariumResourceFunction, StellariumResourceFunctionPaymentManifest } from './resource/repository.js';
3
+ export type { StellariumResource, StellariumResourceFunction, StellariumResourceFunctionParameter, StellariumResourceFunctionPaymentManifest } from './resource/repository.js';
4
4
  export { CombinationResourceInvoker, invocationHash, paymentVoucherPayload, type PaymentVoucher } from './resource/invoker.js';
5
5
  export { grantHash, grantPayload, grantRenewalPayload, grantRequestPayload, grantsHash, CLOCK_SKEW_TOLERANCE_MS, invocationAuthorizationPayload, MAX_AUTHORIZATION_LIFETIME_MS, MAX_GRANT_CHAIN_LENGTH, MAX_GRANT_LIFETIME_MS, type Capability, type Grant, type GrantRenewalRequest, type GrantRequest, type InvocationAuthorization, } from './grant/grant.js';
6
6
  export type { ApproveGrant, GrantApproval, GrantOptions } from './grant/service.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxF,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,yCAAyC,EAAE,MAAM,0BAA0B,CAAC;AAE1I,OAAO,EAAE,0BAA0B,EAAE,cAAc,EAAE,qBAAqB,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE/H,OAAO,EACH,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,UAAU,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,6BAA6B,EAC7B,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,uBAAuB,GAC/B,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACpF,YAAY,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxF,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,mCAAmC,EAAE,yCAAyC,EAAE,MAAM,0BAA0B,CAAC;AAE/K,OAAO,EAAE,0BAA0B,EAAE,cAAc,EAAE,qBAAqB,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE/H,OAAO,EACH,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,UAAU,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,6BAA6B,EAC7B,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,uBAAuB,GAC/B,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACpF,YAAY,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}
@@ -6,8 +6,13 @@ export interface StellariumResourceFunctionPaymentManifest {
6
6
  costLamports: number;
7
7
  recipientAddress: string;
8
8
  }
9
+ export interface StellariumResourceFunctionParameter extends ResourceFunctionParameter {
10
+ description?: string;
11
+ }
9
12
  export interface StellariumResourceFunction extends ResourceFunction {
10
13
  id?: number;
14
+ description?: string;
15
+ parameters: StellariumResourceFunctionParameter[];
11
16
  paymentManifest?: StellariumResourceFunctionPaymentManifest;
12
17
  /** Callers need a grant from the hosting node. Announced to peers so callers can tell. */
13
18
  restricted?: boolean;
@@ -15,6 +20,9 @@ export interface StellariumResourceFunction extends ResourceFunction {
15
20
  export interface StellariumResource extends Resource {
16
21
  id: number;
17
22
  baseUrl: string;
23
+ /** A URL where callers can learn more about the resource. */
24
+ website?: string;
25
+ description?: string;
18
26
  functions: StellariumResourceFunction[];
19
27
  }
20
28
  /**
@@ -63,7 +71,7 @@ export declare class ResourceRepository {
63
71
  getExternalResources(offset?: number, limit?: number): Promise<StellariumResource[]>;
64
72
  getResourceFunction(resourcePath: string, resourceName: string, functionName: string): Promise<StellariumResourceFunction | undefined>;
65
73
  getResourceFunctions(resourceId: number): Promise<StellariumResourceFunction[]>;
66
- getResourceParameters(resourceFunctionId: number): Promise<ResourceFunctionParameter[]>;
74
+ getResourceParameters(resourceFunctionId: number): Promise<StellariumResourceFunctionParameter[]>;
67
75
  getResourceFunctionPaymentManifest(resourceFunctionId: number): Promise<StellariumResourceFunctionPaymentManifest | undefined>;
68
76
  /**
69
77
  * One page of every resource this node knows: the ones it hosts first, then learned ones.
@@ -1 +1 @@
1
- {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/resource/repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/resource/repository.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,18 @@ import { isFreshExpiry, safeVerifyData } from "../crypto/utils.js";
6
6
  export function resourceAnnouncementPayload(resources, expiry) {
7
7
  return { resources, expiry };
8
8
  }
9
+ /** Peers' resources aren't validated on receipt, so a description that isn't a string is stored as absent. */
10
+ function optionalText(value) {
11
+ return typeof value === 'string' ? value : null;
12
+ }
13
+ /** Only http(s) URLs are kept, since clients may render a resource's website as a link. */
14
+ function optionalWebsite(value) {
15
+ if (typeof value !== 'string' || !URL.canParse(value)) {
16
+ return null;
17
+ }
18
+ const { protocol } = new URL(value);
19
+ return protocol === 'http:' || protocol === 'https:' ? value : null;
20
+ }
9
21
  const resourceKey = (resource) => `${resource.path}.${resource.name}`;
10
22
  export class ResourceRepository {
11
23
  db;
@@ -85,7 +97,7 @@ export class ResourceRepository {
85
97
  continue;
86
98
  }
87
99
  await this.deleteFunctions(existing.id);
88
- await this.db.run('UPDATE resource SET base_url = ?, peer_id = ?, updated_at = ? WHERE id = ?', [resource.baseUrl, peer.id, new Date().toISOString(), existing.id]);
100
+ await this.db.run('UPDATE resource SET base_url = ?, website = ?, description = ?, peer_id = ?, updated_at = ? WHERE id = ?', [resource.baseUrl, optionalWebsite(resource.website), optionalText(resource.description), peer.id, new Date().toISOString(), existing.id]);
89
101
  await this.insertFunctions(existing.id, resource.functions);
90
102
  }
91
103
  });
@@ -93,7 +105,7 @@ export class ResourceRepository {
93
105
  }
94
106
  async insert(resource, peerId) {
95
107
  const createdAt = new Date().toISOString();
96
- const result = await this.db.run('INSERT INTO resource (path, name, base_url, peer_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)', [resource.path, resource.name, resource.baseUrl, peerId, createdAt, createdAt]);
108
+ const result = await this.db.run('INSERT INTO resource (path, name, base_url, website, description, peer_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [resource.path, resource.name, resource.baseUrl, optionalWebsite(resource.website), optionalText(resource.description), peerId, createdAt, createdAt]);
97
109
  if (!result.changes || result.lastID === undefined) {
98
110
  throw new Error('Failed to create resource');
99
111
  }
@@ -102,10 +114,10 @@ export class ResourceRepository {
102
114
  async insertFunctions(resourceId, functions) {
103
115
  const createdAt = new Date().toISOString();
104
116
  for (const fn of functions) {
105
- const functionResult = await this.db.run('INSERT INTO resource_function (resource_id, name, return_type, restricted, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)', [resourceId, fn.name, fn.returnType, fn.restricted === true ? 1 : 0, createdAt, createdAt]);
117
+ const functionResult = await this.db.run('INSERT INTO resource_function (resource_id, name, return_type, description, restricted, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)', [resourceId, fn.name, fn.returnType, optionalText(fn.description), fn.restricted === true ? 1 : 0, createdAt, createdAt]);
106
118
  const functionId = functionResult.lastID;
107
119
  for (const parameter of fn.parameters) {
108
- await this.db.run('INSERT INTO resource_function_parameter (resource_function_id, name, parameter_type, created_at, updated_at) VALUES (?, ?, ?, ?, ?)', [functionId, parameter.name, parameter.type, createdAt, createdAt]);
120
+ await this.db.run('INSERT INTO resource_function_parameter (resource_function_id, name, parameter_type, description, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)', [functionId, parameter.name, parameter.type, optionalText(parameter.description), createdAt, createdAt]);
109
121
  }
110
122
  if (fn.paymentManifest) {
111
123
  await this.db.run('INSERT INTO resource_function_payment_manifest (resource_function_id, cost_lamports, recipient_address, created_at, updated_at) VALUES (?, ?, ?, ?, ?)', [functionId, fn.paymentManifest.costLamports, fn.paymentManifest.recipientAddress, createdAt, createdAt]);
@@ -155,6 +167,8 @@ export class ResourceRepository {
155
167
  path: r.path,
156
168
  name: r.name,
157
169
  baseUrl: r.base_url,
170
+ website: r.website ?? undefined,
171
+ description: r.description ?? undefined,
158
172
  metadata: { baseUrl: r.base_url },
159
173
  functions: await this.getResourceFunctions(r.id),
160
174
  })));
@@ -172,6 +186,7 @@ export class ResourceRepository {
172
186
  id: fn.id,
173
187
  name: fn.name,
174
188
  returnType: fn.return_type,
189
+ description: fn.description ?? undefined,
175
190
  parameters: await this.getResourceParameters(fn.id),
176
191
  exec: async () => undefined,
177
192
  paymentManifest: await this.getResourceFunctionPaymentManifest(fn.id),
@@ -184,6 +199,7 @@ export class ResourceRepository {
184
199
  id: f.id,
185
200
  name: f.name,
186
201
  returnType: f.return_type,
202
+ description: f.description ?? undefined,
187
203
  parameters: await this.getResourceParameters(f.id),
188
204
  exec: async () => undefined,
189
205
  paymentManifest: await this.getResourceFunctionPaymentManifest(f.id),
@@ -194,6 +210,7 @@ export class ResourceRepository {
194
210
  return (await this.db.all('SELECT * FROM resource_function_parameter WHERE resource_function_id = ? ORDER BY id', [resourceFunctionId])).map(p => ({
195
211
  name: p.name,
196
212
  type: p.parameter_type,
213
+ description: p.description ?? undefined,
197
214
  }));
198
215
  }
199
216
  async getResourceFunctionPaymentManifest(resourceFunctionId) {
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AAKhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,MAAM,WAAW,eAAe;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;CAC/B;AAED,UAAU,YAAY;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC/B;AAiDD,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,aAAa,MAAM,CAAC;AAsHjC;;;;GAIG;AACH,QAAA,MAAM,MAAM,EAAE,kBAAkB,CAAC,YAAY,CA8R5C,CAAC;eAGa,MAAM"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AAKhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,MAAM,WAAW,eAAe;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;CAC/B;AAED,UAAU,YAAY;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC/B;AAiDD,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,aAAa,MAAM,CAAC;AAsHjC;;;;GAIG;AACH,QAAA,MAAM,MAAM,EAAE,kBAAkB,CAAC,YAAY,CAqS5C,CAAC;eAGa,MAAM"}
package/dist/routes.js CHANGED
@@ -176,10 +176,17 @@ const routes = async (fastify, options) => {
176
176
  resources: resources.map((resource) => ({
177
177
  path: resource.path,
178
178
  name: resource.name,
179
+ website: resource.website,
180
+ description: resource.description,
179
181
  functions: resource.functions.map((fn) => ({
180
182
  name: fn.name,
181
183
  returnType: fn.returnType,
182
- parameters: fn.parameters,
184
+ description: fn.description,
185
+ parameters: fn.parameters.map(parameter => ({
186
+ name: parameter.name,
187
+ type: parameter.type,
188
+ description: parameter.description,
189
+ })),
183
190
  paymentManifest: fn.paymentManifest ? ({
184
191
  costLamports: fn.paymentManifest.costLamports,
185
192
  recipientAddress: fn.paymentManifest.recipientAddress,
@@ -17,7 +17,7 @@ describe("openDatabase", () => {
17
17
  const filename = path.join(dir, "node.db");
18
18
  await (await openDatabase(filename)).close();
19
19
  const db = await openDatabase(filename);
20
- expect(await db.get("PRAGMA user_version")).toEqual({ user_version: 2 });
20
+ expect(await db.get("PRAGMA user_version")).toEqual({ user_version: 3 });
21
21
  await db.close();
22
22
  });
23
23
  test("rebuilds resource tables from the old schema and keeps peers", async () => {
@@ -33,6 +33,24 @@ describe("ResourceRepository", () => {
33
33
  expect(functions.map(fn => [fn.name, fn.restricted])).toEqual([["open", true], ["peek", undefined]]);
34
34
  expect((await repository.getResourceFunction("com.provider", "Vault", "open"))?.restricted).toBe(true);
35
35
  });
36
+ test("keeps the descriptions of resources, functions and parameters", async () => {
37
+ await repository.learn({
38
+ ...resource("Forecast", [
39
+ { name: "tomorrow", description: "Tomorrow's forecast", parameters: [{ name: "city", type: "string", description: "City name" }] },
40
+ { name: "today", parameters: [{ name: "city", type: "string" }] },
41
+ ]),
42
+ website: "https://forecast.example",
43
+ description: "Weather forecasts",
44
+ });
45
+ const [learned] = await repository.getExternalResources();
46
+ expect(learned.website).toBe("https://forecast.example");
47
+ expect(learned.description).toBe("Weather forecasts");
48
+ expect(learned.functions.map(fn => [fn.name, fn.description, fn.parameters[0].description])).toEqual([
49
+ ["today", undefined, undefined],
50
+ ["tomorrow", "Tomorrow's forecast", "City name"],
51
+ ]);
52
+ expect((await repository.getResourceFunction("com.provider", "Forecast", "tomorrow"))?.description).toBe("Tomorrow's forecast");
53
+ });
36
54
  test("is idempotent, so startup can run on every boot", async () => {
37
55
  const learned = resource("Forecast", [{ name: "tomorrow" }]);
38
56
  await repository.learn(learned);
@@ -110,6 +128,19 @@ describe("ResourceRepository", () => {
110
128
  expect(today?.paymentManifest).toMatchObject({ costLamports: 100 });
111
129
  expect(await repository.getResourceFunction("com.provider", "Forecast", "tomorrow")).toBeDefined();
112
130
  });
131
+ test("drops descriptions that aren't strings and websites that aren't http(s) URLs", async () => {
132
+ const sent = {
133
+ ...resource("Forecast", [{ name: "today", description: 42, parameters: [{ name: "city", type: "string", description: { text: "City" } }] }]),
134
+ website: "javascript:alert(1)",
135
+ description: ["Weather forecasts"],
136
+ };
137
+ await save([sent, { ...resource("Radar", []), website: "https://radar.example", description: "Rain radar" }]);
138
+ const [forecast, radar] = await repository.getExternalResources();
139
+ expect([forecast.website, forecast.description]).toEqual([undefined, undefined]);
140
+ expect(forecast.functions[0].description).toBeUndefined();
141
+ expect(forecast.functions[0].parameters[0].description).toBeUndefined();
142
+ expect([radar.website, radar.description]).toEqual(["https://radar.example", "Rain radar"]);
143
+ });
113
144
  test("removes functions and payment manifests the peer no longer advertises", async () => {
114
145
  await save([resource("Forecast", [{ name: "today", paymentManifest: { costLamports: 100, recipientAddress: RECIPIENT } }, { name: "old" }])]);
115
146
  await save([resource("Forecast", [{ name: "today" }])]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stellarium-ts",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "A Stellarium Node in TypeScript.",
5
5
  "homepage": "https://github.com/qualletio/stellarium-ts#readme",
6
6
  "bugs": {