From c9a1c459304c79c317bc0b145698c5a0347b2100 Mon Sep 17 00:00:00 2001 From: BluJ Date: Thu, 13 Apr 2023 14:44:17 -0600 Subject: [PATCH] chore: Add the wrapperData, bound effects, and sdk --- lib/health/checkFns/checkWebUrl.ts | 2 +- lib/mainFn/Daemons.ts | 1 - lib/mainFn/LocalPort.ts | 2 +- lib/mainFn/NetworkBuilder.ts | 4 +-- lib/mainFn/TorHostname.ts | 5 +++- lib/test/makeOutput.ts | 42 ++++++++++++++++++---------- lib/types.ts | 17 +++++++++-- lib/util/getWrapperData.ts | 45 ++++++++++++++++++++++++++++++ lib/util/index.ts | 35 +++++++++++++++++++++++ package-lock.json | 4 +-- package.json | 2 +- 11 files changed, 134 insertions(+), 25 deletions(-) create mode 100644 lib/util/getWrapperData.ts diff --git a/lib/health/checkFns/checkWebUrl.ts b/lib/health/checkFns/checkWebUrl.ts index 57cd357..a8ebf45 100644 --- a/lib/health/checkFns/checkWebUrl.ts +++ b/lib/health/checkFns/checkWebUrl.ts @@ -9,8 +9,8 @@ import { timeoutPromise } from "./index"; * @returns */ export const checkWebUrl = async ( - url: string, effects: Effects, + url: string, { timeout = 1000, successMessage = `Reached ${url}`, diff --git a/lib/mainFn/Daemons.ts b/lib/mainFn/Daemons.ts index b18cbb6..163db49 100644 --- a/lib/mainFn/Daemons.ts +++ b/lib/mainFn/Daemons.ts @@ -74,7 +74,6 @@ export class Daemons { const daemonsStarted = {} as Record>; const { effects } = this; const daemons = this.daemons ?? []; - const _config = await effects.getServiceConfig(); for (const daemon of daemons) { const requiredPromise = Promise.all( daemon.requires?.map((id) => daemonsStarted[id]) ?? [] diff --git a/lib/mainFn/LocalPort.ts b/lib/mainFn/LocalPort.ts index 0ae4da1..9a761ae 100644 --- a/lib/mainFn/LocalPort.ts +++ b/lib/mainFn/LocalPort.ts @@ -2,7 +2,7 @@ import { Effects } from "../types"; import { LocalBinding } from "./LocalBinding"; export class LocalPort { - constructor(readonly id: string, readonly effects: Effects) {} + constructor(readonly effects: Effects, readonly id: string) {} async bindLan(internalPort: number) { const [localAddress, ipAddress] = await this.effects.bindLan({ internalPort, diff --git a/lib/mainFn/NetworkBuilder.ts b/lib/mainFn/NetworkBuilder.ts index 6e052d0..4edbdac 100644 --- a/lib/mainFn/NetworkBuilder.ts +++ b/lib/mainFn/NetworkBuilder.ts @@ -9,9 +9,9 @@ export class NetworkBuilder { private constructor(private effects: Effects) {} getTorHostName(id: string) { - return new TorHostname(id, this.effects); + return new TorHostname(this.effects, id); } getPort(id: string) { - return new LocalPort(id, this.effects); + return new LocalPort(this.effects, id); } } diff --git a/lib/mainFn/TorHostname.ts b/lib/mainFn/TorHostname.ts index 0652659..9a3f5ce 100644 --- a/lib/mainFn/TorHostname.ts +++ b/lib/mainFn/TorHostname.ts @@ -2,7 +2,10 @@ import { Effects } from "../types"; import { TorBinding } from "./TorBinding"; export class TorHostname { - constructor(readonly id: string, readonly effects: Effects) {} + constructor(readonly effects: Effects, readonly id: string) {} + static of(effects: Effects, id: string) { + return new TorHostname(effects, id); + } async bindTor(internalPort: number, externalPort: number) { const address = await this.effects.bindTor({ internalPort, diff --git a/lib/test/makeOutput.ts b/lib/test/makeOutput.ts index d2ba17e..1d62d25 100644 --- a/lib/test/makeOutput.ts +++ b/lib/test/makeOutput.ts @@ -19,7 +19,8 @@ writeConvertedFile( tag: { id: "type", name: "Type", - description: "- LND: Lightning Network Daemon from Lightning Labs\n- CLN: Core Lightning from Blockstream\n", + description: + "- LND: Lightning Network Daemon from Lightning Labs\n- CLN: Core Lightning from Blockstream\n", "variant-names": { lnd: "Lightning Network Daemon (LND)", "c-lightning": "Core Lightning (CLN)", @@ -58,7 +59,8 @@ writeConvertedFile( default: "bitcoin", masked: true, pattern: "^[a-zA-Z0-9_]+$", - "pattern-description": "Must be alphanumeric (can contain underscore).", + "pattern-description": + "Must be alphanumeric (can contain underscore).", }, password: { type: "string", @@ -70,7 +72,8 @@ writeConvertedFile( len: 20, }, pattern: '^[^\\n"]*$', - "pattern-description": "Must not contain newline or quote characters.", + "pattern-description": + "Must not contain newline or quote characters.", copyable: true, masked: true, }, @@ -82,7 +85,8 @@ writeConvertedFile( default: "bitcoin", masked: true, pattern: "^[a-zA-Z0-9_]+$", - "pattern-description": "Must be alphanumeric (can contain underscore).", + "pattern-description": + "Must be alphanumeric (can contain underscore).", textarea: true, }, advanced: { @@ -98,15 +102,18 @@ writeConvertedFile( subtype: "string", default: [], spec: { - pattern: "^[a-zA-Z0-9_-]+:([0-9a-fA-F]{2})+\\$([0-9a-fA-F]{2})+$", - "pattern-description": 'Each item must be of the form ":$".', + pattern: + "^[a-zA-Z0-9_-]+:([0-9a-fA-F]{2})+\\$([0-9a-fA-F]{2})+$", + "pattern-description": + 'Each item must be of the form ":$".', masked: false, }, range: "[0,*)", }, serialversion: { name: "Serialization Version", - description: "Return raw transaction or block hex with Segwit or non-SegWit serialization.", + description: + "Return raw transaction or block hex with Segwit or non-SegWit serialization.", type: "enum", values: ["non-segwit", "segwit"], "value-names": {}, @@ -114,7 +121,8 @@ writeConvertedFile( }, servertimeout: { name: "Rpc Server Timeout", - description: "Number of seconds after which an uncompleted RPC call will time out.", + description: + "Number of seconds after which an uncompleted RPC call will time out.", type: "number", nullable: false, range: "[5,300]", @@ -217,7 +225,8 @@ writeConvertedFile( type: "number", nullable: false, name: "Max Mempool Size", - description: "Keep the transaction memory pool below megabytes.", + description: + "Keep the transaction memory pool below megabytes.", range: "[1,*)", integral: true, units: "MiB", @@ -227,7 +236,8 @@ writeConvertedFile( type: "number", nullable: false, name: "Mempool Expiration", - description: "Do not keep transactions in the mempool longer than hours.", + description: + "Do not keep transactions in the mempool longer than hours.", range: "[1,*)", integral: true, units: "Hr", @@ -243,7 +253,8 @@ writeConvertedFile( listen: { type: "boolean", name: "Make Public", - description: "Allow other nodes to find your server on the network.", + description: + "Allow other nodes to find your server on the network.", default: true, }, onlyconnect: { @@ -283,7 +294,8 @@ writeConvertedFile( type: "number", nullable: true, name: "Port", - description: "Port that peer is listening on for inbound p2p connections", + description: + "Port that peer is listening on for inbound p2p connections", range: "[0,65535]", integral: true, }, @@ -307,7 +319,8 @@ writeConvertedFile( pruning: { type: "union", name: "Pruning Settings", - description: "Blockchain Pruning Options\nReduce the blockchain size on disk\n", + description: + "Blockchain Pruning Options\nReduce the blockchain size on disk\n", warning: "If you set pruning to Manual and your disk is smaller than the total size of the blockchain, you MUST have something running that prunes these blocks or you may overfill your disk!\nDisabling pruning will convert your node into a full archival node. This requires a resync of the entire blockchain, a process that may take several days. Make sure you have enough free disk space or you may fill up your disk.\n", tag: { @@ -329,7 +342,8 @@ writeConvertedFile( nullable: false, name: "Max Chain Size", description: "Limit of blockchain size on disk.", - warning: "Increasing this value will require re-syncing your node.", + warning: + "Increasing this value will require re-syncing your node.", default: 550, range: "[550,1000000)", integral: true, diff --git a/lib/types.ts b/lib/types.ts index 74690fa..5f2703e 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -231,12 +231,22 @@ export type Effects = { progress: () => Promise; }; - getServiceConfig(options?: { + /** Get a value in a json like data, can be observed and subscribed */ + getWrapperData(options?: { + /** If there is no packageId it is assumed the current package */ packageId?: string; + /** The path defaults to root level, using the [JsonPath](https://jsonpath.com/) */ path?: string; - callback?: (config: unknown, previousConfig: unknown) => void; + callback: (config: unknown, previousConfig: unknown) => void; }): Promise; + /** Used to store values that can be accessed and subscribed to */ + setWrapperData(options?: { + /** Sets the value for the wrapper at the path, it will override, using the [JsonPath](https://jsonpath.com/) */ + path?: string; + value: unknown; + }): Promise; + getLocalHostname(): Promise; getIPHostname(): Promise; /** Get the address for another service for tor interfaces */ @@ -334,6 +344,9 @@ export type Effects = { status: HealthStatus; message?: string; }): Promise; + + restart(): void; + shutdown(): void; }; /* rsync options: https://linux.die.net/man/1/rsync diff --git a/lib/util/getWrapperData.ts b/lib/util/getWrapperData.ts new file mode 100644 index 0000000..9592c37 --- /dev/null +++ b/lib/util/getWrapperData.ts @@ -0,0 +1,45 @@ +import { Parser } from "ts-matches"; +import { Effects } from "../types"; + +export function getWrapperData( + effects: Effects, + validator: Parser, + options: { + /** Defaults to what ever the package currently in */ + packageId?: string | undefined; + /** JsonPath */ + path?: string | undefined; + } = {} +) { + return { + const: () => + effects + .getWrapperData({ + ...options, + callback: effects.restart, + }) + .then(validator.unsafeCast), + first: () => + effects + .getWrapperData({ + ...options, + callback: () => {}, + }) + .then(validator.unsafeCast), + overTime: async function* () { + while (true) { + let callback: () => void; + const waitForNext = new Promise((resolve) => { + callback = resolve; + }); + yield await effects + .getWrapperData({ + ...options, + callback: () => callback(), + }) + .then(validator.unsafeCast); + await waitForNext; + } + }, + }; +} diff --git a/lib/util/index.ts b/lib/util/index.ts index 7ecfe55..4d4df9d 100644 --- a/lib/util/index.ts +++ b/lib/util/index.ts @@ -1,8 +1,15 @@ +import { Parser, string } from "ts-matches"; import * as T from "../types"; +import FileHelper from "./fileHelper"; +import nullIfEmpty from "./nullIfEmpty"; +import { getWrapperData } from "./getWrapperData"; +import { checkPortListening, checkWebUrl } from "../health/checkFns"; +import { LocalPort, NetworkBuilder, TorHostname } from "../mainFn"; export { guardAll, typeFromProps } from "./propertiesMatcher"; export { default as nullIfEmpty } from "./nullIfEmpty"; export { FileHelper } from "./fileHelper"; +export { getWrapperData } from "./getWrapperData"; /** Used to check if the file exists before hand */ export const exists = ( @@ -16,3 +23,31 @@ export const exists = ( export const isKnownError = (e: unknown): e is T.KnownError => e instanceof Object && ("error" in e || "error-code" in e); + +type Cdr = A extends [unknown, ...infer Cdr] ? Cdr : []; + +export const utils = (effects: T.Effects) => ({ + readFile: (fileHelper: FileHelper) => fileHelper.read(effects), + writeFile: (fileHelper: FileHelper, data: A) => + fileHelper.write(data, effects), + exists: (props: { path: string; volumeId: string }) => exists(effects, props), + nullIfEmpty, + getWrapperData: ( + validator: Parser, + options: { + /** Defaults to what ever the package currently in */ + packageId?: string | undefined; + /** JsonPath */ + path?: string | undefined; + } = {} + ) => getWrapperData(effects, validator, options), + setWrapperData: ( + value: A, + options: { packageId?: string | undefined; path?: string | undefined } = {} + ) => effects.setWrapperData({ ...options, value }), + checkPortListening: checkPortListening.bind(null, effects), + checkWebUrl: checkWebUrl.bind(null, effects), + localPort: LocalPort.bind(null, effects), + networkBuilder: NetworkBuilder.of.bind(null, effects), + torHostName: TorHostname.of.bind(null, effects), +}); diff --git a/package-lock.json b/package-lock.json index 88f53ea..872f2ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "start-sdk", - "version": "0.4.0-lib0.charlie16", + "version": "0.4.0-lib0.charlie18", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "start-sdk", - "version": "0.4.0-lib0.charlie16", + "version": "0.4.0-lib0.charlie18", "license": "MIT", "dependencies": { "@iarna/toml": "^2.2.5", diff --git a/package.json b/package.json index 4d2d4d2..0ba4683 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "start-sdk", - "version": "0.4.0-lib0.charlie16", + "version": "0.4.0-lib0.charlie18", "description": "For making the patterns that are wanted in making services for the startOS.", "main": "./lib/index.js", "types": "./lib/index.d.ts",