[node] finished the great typescript rewrite
This commit is contained in:
parent
8107afbd90
commit
a1d6b03ec9
30 changed files with 1019 additions and 359 deletions
|
@ -34,7 +34,7 @@ async function runProcurement(contract: Contract, ships: Array<Ship>) {
|
||||||
// TODO check if contract is fulfilled!
|
// TODO check if contract is fulfilled!
|
||||||
const wantedCargo = contract.terms.deliver[0].tradeSymbol;
|
const wantedCargo = contract.terms.deliver[0].tradeSymbol;
|
||||||
const deliveryPoint = contract.terms.deliver[0].destinationSymbol;
|
const deliveryPoint = contract.terms.deliver[0].destinationSymbol;
|
||||||
const asteroids = await systems.type({symbol: ships[0].nav.systemSymbol, type: 'ENGINEERED_ASTEROID'});
|
const asteroids = await systems.type(ships[0].nav.systemSymbol, 'ENGINEERED_ASTEROID');
|
||||||
const asteroidSymbol = asteroids[0].symbol;
|
const asteroidSymbol = asteroids[0].symbol;
|
||||||
ships.forEach(async function(ship) {
|
ships.forEach(async function(ship) {
|
||||||
while (!contract.fulfilled) {
|
while (!contract.fulfilled) {
|
||||||
|
@ -46,12 +46,8 @@ async function runProcurement(contract: Contract, ships: Array<Ship>) {
|
||||||
// Then it depends on where we are
|
// Then it depends on where we are
|
||||||
switch (ship.nav.waypointSymbol) {
|
switch (ship.nav.waypointSymbol) {
|
||||||
case asteroidSymbol:
|
case asteroidSymbol:
|
||||||
await mining.mineUntilFullOf({
|
ship = await mining.mineUntilFullOf(wantedCargo, ship, asteroidSymbol);
|
||||||
asteroidSymbol: asteroidSymbol,
|
ship = await libShips.navigate(ship, deliveryPoint);
|
||||||
good: wantedCargo,
|
|
||||||
symbol: ship.symbol
|
|
||||||
});
|
|
||||||
await libShips.navigate(ship, deliveryPoint);
|
|
||||||
break;
|
break;
|
||||||
case deliveryPoint:
|
case deliveryPoint:
|
||||||
if (goodCargo !== undefined) { // we could be here if a client restart happens right after selling before we navigate away
|
if (goodCargo !== undefined) { // we could be here if a client restart happens right after selling before we navigate away
|
||||||
|
@ -59,12 +55,12 @@ async function runProcurement(contract: Contract, ships: Array<Ship>) {
|
||||||
contract = await contracts.deliver(contract, ship);
|
contract = await contracts.deliver(contract, ship);
|
||||||
if (contract.fulfilled) break;
|
if (contract.fulfilled) break;
|
||||||
}
|
}
|
||||||
await libShips.navigate(ship, asteroidSymbol);
|
ship = await libShips.navigate(ship, asteroidSymbol);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// we were either selling or started contracting
|
// we were either selling or started contracting
|
||||||
await selling.sell(ship, wantedCargo);
|
ship = await selling.sell(ship, wantedCargo);
|
||||||
await libShips.navigate(ship, asteroidSymbol);
|
ship = await libShips.navigate(ship, asteroidSymbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO repurpose the ship
|
// TODO repurpose the ship
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
import db from '../database/db.js';
|
|
||||||
import * as dbSystems from '../database/systems.js';
|
|
||||||
import * as api from '../lib/api.js';
|
|
||||||
|
|
||||||
export async function init() {
|
|
||||||
const response = await api.send({endpoint: `/systems`, page: Math.max(1, Math.floor(dbSystems.getSystemsCount()/20)), priority: 100});
|
|
||||||
if (response.error !== undefined) {
|
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
db.transaction(() => response.forEach(function(system) { try { dbSystems.addSystem(system); } catch {} }))();
|
|
||||||
}
|
|
9
nodejs/automation/exploration.ts
Normal file
9
nodejs/automation/exploration.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import db from '../database/db.ts';
|
||||||
|
import * as dbSystems from '../database/systems.ts';
|
||||||
|
import { System } from '../model/system.ts';
|
||||||
|
import * as api from '../lib/api.ts';
|
||||||
|
|
||||||
|
export async function init(): Promise<void> {
|
||||||
|
const response = await api.sendPaginated<System>({endpoint: `/systems`, page: Math.max(1, Math.floor(dbSystems.getSystemsCount()/20)), priority: 100});
|
||||||
|
db.transaction(() => response.forEach(function(system) { try { dbSystems.addSystem(system); } catch {} }))();
|
||||||
|
}
|
|
@ -1,15 +1,19 @@
|
||||||
import * as dbAgents from '../database/agents.js';
|
import * as dbAgents from '../database/agents.ts';
|
||||||
import * as db from '../database/db.js';
|
import * as db from '../database/db.ts';
|
||||||
import * as dbContracts from '../database/contracts.js';
|
import * as dbContracts from '../database/contracts.ts';
|
||||||
import * as dbShips from '../database/ships.js';
|
import * as dbShips from '../database/ships.ts';
|
||||||
import * as dbTokens from '../database/tokens.js';
|
import * as dbTokens from '../database/tokens.ts';
|
||||||
import * as api from '../lib/api.js';
|
import { Agent } from '../model/agent.ts';
|
||||||
import * as ships from '../lib/ships.js';
|
import { Response } from '../model/api.ts';
|
||||||
|
import { Contract } from '../model/contract.ts';
|
||||||
|
import { Ship } from '../model/ship.ts';
|
||||||
|
import * as api from '../lib/api.ts';
|
||||||
|
import * as ships from '../lib/ships.ts';
|
||||||
|
|
||||||
const symbol = process.env.NODE_ENV === 'test' ? 'ADYXAX-0' : 'ADYXAX-TS';
|
const symbol = process.env.NODE_ENV === 'test' ? 'ADYXAX-0' : 'ADYXAX-JS';
|
||||||
|
|
||||||
// This function registers then inits the database
|
// This function registers then inits the database
|
||||||
export async function init() {
|
export async function init(): Promise<void> {
|
||||||
const response = await fetch('https://api.spacetraders.io/v2/register', {
|
const response = await fetch('https://api.spacetraders.io/v2/register', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -20,7 +24,7 @@ export async function init() {
|
||||||
faction: "COSMIC",
|
faction: "COSMIC",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const json = await response.json();
|
const json = await response.json() as Response<{agent: Agent, contract: Contract, ship: Ship, token: string}>;
|
||||||
if (json.error !== undefined) {
|
if (json.error !== undefined) {
|
||||||
switch(json.error?.code) {
|
switch(json.error?.code) {
|
||||||
case 4111: // 4111 means the agent symbol has already been claimed so no server reset happened
|
case 4111: // 4111 means the agent symbol has already been claimed so no server reset happened
|
|
@ -1,33 +0,0 @@
|
||||||
import * as selling from './selling.js';
|
|
||||||
import * as dbShips from '../database/ships.js';
|
|
||||||
import * as api from '../lib/api.js';
|
|
||||||
import * as libShips from '../lib/ships.js';
|
|
||||||
import * as utils from '../lib/utils.js';
|
|
||||||
|
|
||||||
// example ctx { asteroidSymbol: XXXXX, good: 'SILVER_ORE', symbol: 'ADYXAX-2' }
|
|
||||||
// returns the number of units of the good the ship holds
|
|
||||||
export async function mineUntilFullOf(ctx) {
|
|
||||||
while(true) {
|
|
||||||
const ship = dbShips.getShip(ctx.symbol);
|
|
||||||
const cargo = utils.categorizeCargo(await mineUntilFull({symbol: ctx.symbol}), ctx.good);
|
|
||||||
const wantedUnits = Object.values(cargo.wanted).reduce((acc, e) => acc += e, 0);
|
|
||||||
// > 90% full of the valuable goods ?
|
|
||||||
if (wantedUnits >= ship.cargo.capacity * 0.9) return;
|
|
||||||
// we are full but need to sell junk
|
|
||||||
await selling.sell(ship, ctx.good);
|
|
||||||
await libShips.navigate({symbol: ship.symbol, waypoint: ctx.asteroidSymbol});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// example ctx { symbol: 'ADYXAX-2' }
|
|
||||||
// extract the ship's cargo contents when more than 80% full then returns the ships cargo object
|
|
||||||
async function mineUntilFull(ctx) {
|
|
||||||
while(true) {
|
|
||||||
const ship = dbShips.getShip(ctx.symbol);
|
|
||||||
if (ship.cargo.units >= ship.cargo.capacity * 0.9) return ship.cargo;
|
|
||||||
if (await libShips.extract({symbol: ctx.symbol}) === null)
|
|
||||||
await ship(ctx); // refresh the ships status from the server just in case
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO surveying the asteroid field
|
|
29
nodejs/automation/mining.ts
Normal file
29
nodejs/automation/mining.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import * as selling from './selling.js';
|
||||||
|
import * as dbShips from '../database/ships.js';
|
||||||
|
import * as api from '../lib/api.js';
|
||||||
|
import * as libShips from '../lib/ships.js';
|
||||||
|
import * as utils from '../lib/utils.js';
|
||||||
|
import { Ship } from '../model/ship.ts';
|
||||||
|
|
||||||
|
export async function mineUntilFullOf(good: string, ship: Ship, asteroidSymbol: string): Promise<Ship> {
|
||||||
|
// TODO find a good asteroid
|
||||||
|
while(true) {
|
||||||
|
ship = await mineUntilFull(ship);
|
||||||
|
const cargo = utils.categorizeCargo(ship.cargo, good);
|
||||||
|
const wantedUnits = Object.values(cargo.wanted).reduce((acc, e) => acc += e, 0);
|
||||||
|
// > 90% full of the valuable goods ?
|
||||||
|
if (wantedUnits >= ship.cargo.capacity * 0.9) return ship;
|
||||||
|
// we are full but need to sell junk
|
||||||
|
await selling.sell(ship, good);
|
||||||
|
await libShips.navigate(ship, asteroidSymbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// example ctx { symbol: 'ADYXAX-2' }
|
||||||
|
// extract the ship's cargo contents when more than 80% full then returns the ships cargo object
|
||||||
|
async function mineUntilFull(ship: Ship): Promise<Ship> {
|
||||||
|
for (;ship.cargo.units <= ship.cargo.capacity * 0.9; ship = await libShips.extract(ship)) {}
|
||||||
|
return ship;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO surveying the asteroid field
|
|
@ -1,37 +1,34 @@
|
||||||
import * as dbMarkets from '../database/markets.js';
|
import * as dbMarkets from '../database/markets.ts';
|
||||||
import * as dbShips from '../database/ships.js';
|
import * as dbShips from '../database/ships.ts';
|
||||||
import * as api from '../lib/api.js';
|
import * as api from '../lib/api.ts';
|
||||||
import * as libShips from '../lib/ships.js';
|
import * as libShips from '../lib/ships.ts';
|
||||||
import * as libSystems from '../lib/systems.js';
|
import * as libSystems from '../lib/systems.ts';
|
||||||
import * as utils from '../lib/utils.js';
|
import * as utils from '../lib/utils.ts';
|
||||||
|
import { CargoManifest } from '../model/cargo.ts';
|
||||||
|
import { CommonThing } from '../model/common.ts';
|
||||||
|
import { Ship } from '../model/ship.ts';
|
||||||
|
|
||||||
// example ctx { ship: {XXX}, keep: 'SILVER_ORE' }
|
// example ctx { ship: {XXX}, keep: 'SILVER_ORE' }
|
||||||
export async function sell(ship, keep) {
|
export async function sell(ship: Ship, good: string): Promise<Ship> {
|
||||||
outer: while(true) {
|
outer: while(true) {
|
||||||
// first lets see what we want to sell
|
// first lets see what we want to sell
|
||||||
let cargo = utils.categorizeCargo(ship.cargo, keep);
|
let cargo = utils.categorizeCargo(ship.cargo, good);
|
||||||
// get the marketdata from our location
|
// get the marketdata from our location
|
||||||
const market = await libSystems.market(ship.nav.waypointSymbol);
|
const market = await libSystems.market(ship.nav.waypointSymbol);
|
||||||
// can we sell anything here?
|
// can we sell anything here?
|
||||||
const goods = whatCanBeTradedAt(cargo.goods, market.imports.concat(market.exchange));
|
const goods = whatCanBeTradedAt(cargo.goods, market.imports.concat(market.exchange));
|
||||||
for (let i = 0; i < goods.length; i++) {
|
for (let i = 0; i < goods.length; i++) {
|
||||||
const symbol = goods[i].symbol;
|
const symbol = goods[i].symbol;
|
||||||
await libShips.sell({
|
ship = await libShips.sell(ship, good);
|
||||||
good: symbol,
|
|
||||||
symbol: ship.symbol,
|
|
||||||
units: cargo.goods[symbol],
|
|
||||||
});
|
|
||||||
delete cargo.goods[symbol];
|
|
||||||
};
|
};
|
||||||
// are we done selling everything we can?
|
// are we done selling everything we can?
|
||||||
ship = dbShips.getShip(ship.symbol);
|
cargo = utils.categorizeCargo(ship.cargo, good);
|
||||||
cargo = utils.categorizeCargo(ship.cargo, keep);
|
|
||||||
if (Object.keys(cargo.goods).length === 0) {
|
if (Object.keys(cargo.goods).length === 0) {
|
||||||
return;
|
return ship;
|
||||||
}
|
}
|
||||||
// we need to move somewhere else to sell our remaining goods
|
// we need to move somewhere else to sell our remaining goods
|
||||||
// first we look into markets in our system
|
// first we look into markets in our system
|
||||||
const rawMarkets = await libSystems.trait({symbol: ship.nav.systemSymbol, trait: 'MARKETPLACE'});
|
const rawMarkets = await libSystems.trait(ship.nav.systemSymbol, 'MARKETPLACE');
|
||||||
// sorted by distance from where we are
|
// sorted by distance from where we are
|
||||||
const markets = rawMarkets.map(function (m) { return {
|
const markets = rawMarkets.map(function (m) { return {
|
||||||
data: m,
|
data: m,
|
||||||
|
@ -52,7 +49,7 @@ export async function sell(ship, keep) {
|
||||||
// if we have no data on the market we need to go there and see
|
// if we have no data on the market we need to go there and see
|
||||||
// and if we have data and can sell there we need to go too
|
// and if we have data and can sell there we need to go too
|
||||||
if (market === null || whatCanBeTradedAt(cargo.goods, market.imports).length > 0) {
|
if (market === null || whatCanBeTradedAt(cargo.goods, market.imports).length > 0) {
|
||||||
await libShips.navigate({symbol: ship.symbol, waypoint: waypointSymbol});
|
ship = await libShips.navigate(ship, waypointSymbol);
|
||||||
continue outer;
|
continue outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +59,7 @@ export async function sell(ship, keep) {
|
||||||
const market = await libSystems.market(waypointSymbol);
|
const market = await libSystems.market(waypointSymbol);
|
||||||
// if we can sell there we need to go
|
// if we can sell there we need to go
|
||||||
if (whatCanBeTradedAt(cargo.goods, market.exchange).length > 0) {
|
if (whatCanBeTradedAt(cargo.goods, market.exchange).length > 0) {
|
||||||
await libShips.navigate({symbol: ship.symbol, waypoint: waypointSymbol});
|
ship = await libShips.navigate(ship, waypointSymbol);
|
||||||
continue outer;
|
continue outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,7 +67,6 @@ export async function sell(ship, keep) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function whatCanBeTradedAt(cargo, goods) {
|
function whatCanBeTradedAt(cargo: CargoManifest, goods: Array<CommonThing>): Array<CommonThing> {
|
||||||
if (goods === undefined) return [];
|
|
||||||
return goods.filter(g => cargo[g.symbol] !== undefined );
|
return goods.filter(g => cargo[g.symbol] !== undefined );
|
||||||
}
|
}
|
|
@ -1,20 +1,20 @@
|
||||||
import { Agent } from '../model/agent.ts';
|
import { Agent } from '../model/agent.ts';
|
||||||
import db from './db.js';
|
import { DbData, db } from './db.ts';
|
||||||
|
|
||||||
const addAgentStatement = db.prepare(`INSERT INTO agents(data) VALUES (json(?));`);
|
const addAgentStatement = db.prepare(`INSERT INTO agents(data) VALUES (json(?));`);
|
||||||
const getAgentStatement = db.prepare(`SELECT data FROM agents;`);
|
const getAgentStatement = db.prepare(`SELECT data FROM agents;`);
|
||||||
const setAgentStatement = db.prepare(`UPDATE agents SET data = json(?);`);
|
const setAgentStatement = db.prepare(`UPDATE agents SET data = json(?);`);
|
||||||
|
|
||||||
export function addAgent(agent: Agent) {
|
export function addAgent(agent: Agent): void {
|
||||||
addAgentStatement.run(JSON.stringify(agent));
|
addAgentStatement.run(JSON.stringify(agent));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAgent(): Agent|null {
|
export function getAgent(): Agent|null {
|
||||||
const data = getAgentStatement.get() as {data: string}|undefined;
|
const data = getAgentStatement.get() as DbData|undefined;
|
||||||
if (!data) return null;
|
if (!data) return null;
|
||||||
return JSON.parse(data.data);
|
return JSON.parse(data.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setAgent(agent: Agent) {
|
export function setAgent(agent: Agent): void {
|
||||||
setAgentStatement.run(JSON.stringify(agent));
|
setAgentStatement.run(JSON.stringify(agent));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Contract } from '../model/contract.ts';
|
import { Contract } from '../model/contract.ts';
|
||||||
import db from './db.ts';
|
import { DbData, db } from './db.ts';
|
||||||
|
|
||||||
const addContractStatement = db.prepare(`INSERT INTO contracts(data) VALUES (json(?));`);
|
const addContractStatement = db.prepare(`INSERT INTO contracts(data) VALUES (json(?));`);
|
||||||
const getContractStatement = db.prepare(`SELECT data FROM contracts WHERE data->>'id' = ?;`);
|
const getContractStatement = db.prepare(`SELECT data FROM contracts WHERE data->>'id' = ?;`);
|
||||||
|
@ -7,17 +7,17 @@ const getContractsStatement = db.prepare(`SELECT data FROM contracts WHERE data-
|
||||||
const updateContractStatement = db.prepare(`UPDATE contracts SET data = json(:data) WHERE data->>'id' = :id;`);
|
const updateContractStatement = db.prepare(`UPDATE contracts SET data = json(:data) WHERE data->>'id' = :id;`);
|
||||||
|
|
||||||
export function getContract(id: string): Contract|null {
|
export function getContract(id: string): Contract|null {
|
||||||
const data = getContractStatement.get(id) as {data: string}|undefined;
|
const data = getContractStatement.get(id) as DbData|undefined;
|
||||||
if (!data) return null;
|
if (!data) return null;
|
||||||
return JSON.parse(data.data);
|
return JSON.parse(data.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getContracts(): Array<Contract> {
|
export function getContracts(): Array<Contract> {
|
||||||
const data = getContractsStatement.all() as Array<{data: string}>;
|
const data = getContractsStatement.all() as Array<DbData>;
|
||||||
return data.map(contractData => JSON.parse(contractData.data));
|
return data.map(contractData => JSON.parse(contractData.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setContract(data: Contract) {
|
export function setContract(data: Contract): void {
|
||||||
if (getContract(data.id) === null) {
|
if (getContract(data.id) === null) {
|
||||||
addContractStatement.run(JSON.stringify(data));
|
addContractStatement.run(JSON.stringify(data));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
import Database from 'better-sqlite3';
|
import Database from 'better-sqlite3';
|
||||||
|
|
||||||
const allMigrations = [
|
let allMigrations: Array<string> = [];
|
||||||
'database/000_init.sql',
|
fs.readdir('./database/', function(err, files) {
|
||||||
'database/001_systems.sql',
|
if (err) throw err;
|
||||||
'database/002_ships.sql',
|
allMigrations = files.filter(e => e.match(/\.sql$/)).map(e => path.join('./database', e));
|
||||||
'database/003_surveys.sql',
|
});
|
||||||
'database/004_markets.sql',
|
|
||||||
];
|
|
||||||
|
|
||||||
const db = new Database(
|
export type DbData = {data: string};
|
||||||
|
|
||||||
|
export const db = new Database(
|
||||||
process.env.NODE_ENV === 'test' ? 'test.db' : 'spacetraders.db',
|
process.env.NODE_ENV === 'test' ? 'test.db' : 'spacetraders.db',
|
||||||
process.env.NODE_ENV === 'development' ? { verbose: console.log } : undefined
|
process.env.NODE_ENV === 'development' ? { verbose: console.log } : undefined
|
||||||
);
|
);
|
||||||
db.pragma('foreign_keys = ON');
|
db.pragma('foreign_keys = ON');
|
||||||
db.pragma('journal_mode = WAL');
|
db.pragma('journal_mode = WAL');
|
||||||
|
|
||||||
function init() {
|
function init(): void {
|
||||||
db.transaction(function migrate() {
|
db.transaction(function migrate() {
|
||||||
let version;
|
let version;
|
||||||
try {
|
try {
|
||||||
|
@ -34,7 +35,7 @@ function init() {
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function reset() {
|
export function reset(): void {
|
||||||
const indices = db.prepare(`SELECT name FROM sqlite_master WHERE type = 'index';`).all() as Array<{name: string}>;
|
const indices = db.prepare(`SELECT name FROM sqlite_master WHERE type = 'index';`).all() as Array<{name: string}>;
|
||||||
const tables = db.prepare(`SELECT name FROM sqlite_master WHERE type = 'table';`).all() as Array<{name: string}>;
|
const tables = db.prepare(`SELECT name FROM sqlite_master WHERE type = 'table';`).all() as Array<{name: string}>;
|
||||||
const triggers = db.prepare(`SELECT name FROM sqlite_master WHERE type = 'trigger';`).all() as Array<{name: string}>;
|
const triggers = db.prepare(`SELECT name FROM sqlite_master WHERE type = 'trigger';`).all() as Array<{name: string}>;
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
import db from './db.js';
|
|
||||||
import * as utils from '../lib/utils.js';
|
|
||||||
|
|
||||||
const addMarketStatement = db.prepare(`INSERT INTO markets(system, data) VALUES (?, json(?));`);
|
|
||||||
const getMarketAtWaypointStatement = db.prepare(`SELECT data FROM markets WHERE data->>'symbol' = ?;`);
|
|
||||||
const getMarketsInSystemStatement = db.prepare(`SELECT data FROM markets WHERE system = ?;`);
|
|
||||||
const updateMarketStatement = db.prepare(`UPDATE markets SET data = json(:data) WHERE data->>'symbol' = :symbol;`);
|
|
||||||
|
|
||||||
export function getMarketAtWaypoint(symbol) {
|
|
||||||
const data = getMarketAtWaypointStatement.get(symbol);
|
|
||||||
if (data === undefined) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return JSON.parse(data.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getMarketsInSystem(symbol) {
|
|
||||||
const data = getMarketsInSystemStatement.get(symbol);
|
|
||||||
if (data === undefined) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return JSON.parse(data.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setMarket(data) {
|
|
||||||
if (getMarketAtWaypoint(data.symbol) === null) {
|
|
||||||
const system = utils.systemFromWaypoint(data.symbol);
|
|
||||||
return addMarketStatement.run(system, JSON.stringify(data)).lastInsertRowid;
|
|
||||||
}
|
|
||||||
return updateMarketStatement.run({
|
|
||||||
data: JSON.stringify(data),
|
|
||||||
symbol: data.symbol,
|
|
||||||
}).changes;
|
|
||||||
}
|
|
26
nodejs/database/markets.ts
Normal file
26
nodejs/database/markets.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { DbData, db } from './db.ts';
|
||||||
|
import { Market } from '../model/market.ts';
|
||||||
|
import { systemFromWaypoint } from '../lib/utils.ts';
|
||||||
|
|
||||||
|
const addMarketStatement = db.prepare(`INSERT INTO markets(system, data) VALUES (?, json(?));`);
|
||||||
|
const getMarketAtWaypointStatement = db.prepare(`SELECT data FROM markets WHERE data->>'symbol' = ?;`);
|
||||||
|
//const getMarketsInSystemStatement = db.prepare(`SELECT data FROM markets WHERE system = ?;`);
|
||||||
|
const updateMarketStatement = db.prepare(`UPDATE markets SET data = json(:data) WHERE data->>'symbol' = :symbol;`);
|
||||||
|
|
||||||
|
export function getMarketAtWaypoint(symbol: string): Market|null {
|
||||||
|
const data = getMarketAtWaypointStatement.get(symbol) as DbData;
|
||||||
|
if (!data) return null;
|
||||||
|
return JSON.parse(data.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setMarket(data: Market): void {
|
||||||
|
if (getMarketAtWaypoint(data.symbol) === null) {
|
||||||
|
const system = systemFromWaypoint(data.symbol);
|
||||||
|
addMarketStatement.run(system, JSON.stringify(data));
|
||||||
|
} else {
|
||||||
|
updateMarketStatement.run({
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
symbol: data.symbol,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import db from './db.ts';
|
import { DbData, db } from './db.ts';
|
||||||
import { Cargo } from '../model/cargo.ts';
|
import { Cargo } from '../model/cargo.ts';
|
||||||
import { Fuel, Nav, Ship } from '../model/ship.ts';
|
import { Fuel, Nav, Ship } from '../model/ship.ts';
|
||||||
|
|
||||||
|
@ -11,18 +11,18 @@ const setShipNavStatement = db.prepare(`UPDATE ships SET data = (SELECT json_set
|
||||||
const updateShipStatement = db.prepare(`UPDATE ships SET data = json(:data) WHERE data->>'symbol' = :symbol;`);
|
const updateShipStatement = db.prepare(`UPDATE ships SET data = json(:data) WHERE data->>'symbol' = :symbol;`);
|
||||||
|
|
||||||
export function getShip(symbol: string): Ship|null {
|
export function getShip(symbol: string): Ship|null {
|
||||||
const data = getShipStatement.get(symbol) as {data: string}|undefined;
|
const data = getShipStatement.get(symbol) as DbData|undefined;
|
||||||
if (!data) return null;
|
if (!data) return null;
|
||||||
return JSON.parse(data.data);
|
return JSON.parse(data.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getShipsAt(symbol: string) {
|
export function getShipsAt(symbol: string): Array<Ship> {
|
||||||
const data = getShipsAtStatement.all(symbol) as Array<{data: string}>;
|
const data = getShipsAtStatement.all(symbol) as Array<DbData>;
|
||||||
return data.map(elt => JSON.parse(elt.data));
|
return data.map(elt => JSON.parse(elt.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function setShip(data: Ship) {
|
export function setShip(data: Ship): void {
|
||||||
if (getShip(data.symbol) === null) {
|
if (getShip(data.symbol) === null) {
|
||||||
addShipStatement.run(JSON.stringify(data));
|
addShipStatement.run(JSON.stringify(data));
|
||||||
} else {
|
} else {
|
||||||
|
@ -33,21 +33,21 @@ export function setShip(data: Ship) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setShipCargo(symbol: string, cargo: Cargo) {
|
export function setShipCargo(symbol: string, cargo: Cargo): void {
|
||||||
setShipCargoStatement.run({
|
setShipCargoStatement.run({
|
||||||
cargo: JSON.stringify(cargo),
|
cargo: JSON.stringify(cargo),
|
||||||
symbol: symbol,
|
symbol: symbol,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setShipFuel(symbol: string, fuel: Fuel) {
|
export function setShipFuel(symbol: string, fuel: Fuel): void {
|
||||||
setShipFuelStatement.run({
|
setShipFuelStatement.run({
|
||||||
fuel: JSON.stringify(fuel),
|
fuel: JSON.stringify(fuel),
|
||||||
symbol: symbol,
|
symbol: symbol,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setShipNav(symbol: string, nav: Nav) {
|
export function setShipNav(symbol: string, nav: Nav): void {
|
||||||
setShipNavStatement.run({
|
setShipNavStatement.run({
|
||||||
nav: JSON.stringify(nav),
|
nav: JSON.stringify(nav),
|
||||||
symbol: symbol,
|
symbol: symbol,
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
import db from './db.js';
|
|
||||||
|
|
||||||
const deleteExpiredSurveysStatement = db.prepare(`DELETE FROM surveys WHERE data->>'expiration' < ?;`);
|
|
||||||
const getSurveysStatement = db.prepare(`SELECT data FROM surveys WHERE data->>'symbol' = ?;`);
|
|
||||||
const setSurveysStatement = db.prepare(`INSERT INTO surveys(data) VALUES (json(?));`);
|
|
||||||
|
|
||||||
export function deleteExpired() {
|
|
||||||
return deleteExpiredSurveysStatement.run(new Date().toISOString()).changes;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function get(symbol) {
|
|
||||||
deleteExpired();
|
|
||||||
const data = getSurveysStatement.all(symbol);
|
|
||||||
return data.map(elt => JSON.parse(elt.data));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function set(survey) {
|
|
||||||
deleteExpired();
|
|
||||||
return setSurveysStatement.run(JSON.stringify(survey));
|
|
||||||
}
|
|
20
nodejs/database/surveys.ts
Normal file
20
nodejs/database/surveys.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { DbData, db } from './db.ts';
|
||||||
|
|
||||||
|
//const deleteExpiredSurveysStatement = db.prepare(`DELETE FROM surveys WHERE data->>'expiration' < ?;`);
|
||||||
|
//const getSurveysStatement = db.prepare(`SELECT data FROM surveys WHERE data->>'symbol' = ?;`);
|
||||||
|
//const setSurveysStatement = db.prepare(`INSERT INTO surveys(data) VALUES (json(?));`);
|
||||||
|
//
|
||||||
|
//export function deleteExpired() {
|
||||||
|
// return deleteExpiredSurveysStatement.run(new Date().toISOString()).changes;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//export function get(symbol) {
|
||||||
|
// deleteExpired();
|
||||||
|
// const data = getSurveysStatement.all(symbol);
|
||||||
|
// return data.map(elt => JSON.parse(elt.data));
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//export function set(survey) {
|
||||||
|
// deleteExpired();
|
||||||
|
// return setSurveysStatement.run(JSON.stringify(survey));
|
||||||
|
//}
|
|
@ -1,4 +1,5 @@
|
||||||
import db from './db.js';
|
import { DbData, db } from './db.ts';
|
||||||
|
import { System, Waypoint } from '../model/system.ts';
|
||||||
|
|
||||||
const addSystemStatement = db.prepare(`INSERT INTO systems(data) VALUES (json(?));`);
|
const addSystemStatement = db.prepare(`INSERT INTO systems(data) VALUES (json(?));`);
|
||||||
const getSystemStatement = db.prepare(`SELECT data FROM systems WHERE data->>'symbol' = ?;`);
|
const getSystemStatement = db.prepare(`SELECT data FROM systems WHERE data->>'symbol' = ?;`);
|
||||||
|
@ -7,50 +8,44 @@ const getSystemsCountStatement = db.prepare(`SELECT COUNT(data) as data FROM sys
|
||||||
const setSystemStatement = db.prepare(`UPDATE systems SET data = json(:data), updated = :date WHERE data->>'symbol' = :symbol;`);
|
const setSystemStatement = db.prepare(`UPDATE systems SET data = json(:data), updated = :date WHERE data->>'symbol' = :symbol;`);
|
||||||
const setSystemWaypointsStatement = db.prepare(`UPDATE systems SET data = (SELECT json_set(data, '$.waypoints', json(:waypoints)) FROM systems WHERE data->>'symbol' = :symbol), updated = :date WHERE data->>'symbol' = :symbol;`);
|
const setSystemWaypointsStatement = db.prepare(`UPDATE systems SET data = (SELECT json_set(data, '$.waypoints', json(:waypoints)) FROM systems WHERE data->>'symbol' = :symbol), updated = :date WHERE data->>'symbol' = :symbol;`);
|
||||||
|
|
||||||
export function addSystem(data) {
|
export function addSystem(data: System): void {
|
||||||
return addSystemStatement.run(JSON.stringify(data)).lastInsertRowid;
|
addSystemStatement.run(JSON.stringify(data)).lastInsertRowid;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSystem(symbol) {
|
export function getSystem(symbol: string): System|null {
|
||||||
const data = getSystemStatement.get(symbol);
|
const data = getSystemStatement.get(symbol) as DbData|undefined;
|
||||||
if (data === undefined) {
|
if (!data) return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return JSON.parse(data.data);
|
return JSON.parse(data.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSystemsCount() {
|
export function getSystemsCount(): number {
|
||||||
const data = getSystemsCountStatement.get();
|
const data = getSystemsCountStatement.get() as number|undefined;
|
||||||
if (data === undefined) {
|
if (!data) return 0;
|
||||||
return null;
|
return data;
|
||||||
}
|
|
||||||
return data.data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSystemUpdated(symbol) {
|
export function getSystemUpdated(symbol: string): Date|null {
|
||||||
const updated = getSystemUpdatedStatement.get(symbol);
|
const data = getSystemUpdatedStatement.get(symbol) as {updated: Date}|undefined;
|
||||||
if (updated === undefined) {
|
if (!data) return null;
|
||||||
return null;
|
return data.updated;
|
||||||
}
|
|
||||||
return updated.updated;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setSystem(data) {
|
export function setSystem(data: System): void {
|
||||||
if (getSystem(data.symbol) === null) {
|
if (getSystem(data.symbol) === null) {
|
||||||
addSystem(data);
|
addSystem(data);
|
||||||
} else {
|
} else {
|
||||||
return setSystemStatement.run({
|
setSystemStatement.run({
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
symbol: data.symbol,
|
symbol: data.symbol,
|
||||||
}).changes;
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setSystemWaypoints(symbol, waypoints) {
|
export function setSystemWaypoints(symbol: string, waypoints: Array<Waypoint>): void {
|
||||||
return setSystemWaypointsStatement.run({
|
setSystemWaypointsStatement.run({
|
||||||
date: new Date().toISOString(),
|
date: new Date().toISOString(),
|
||||||
symbol: symbol,
|
symbol: symbol,
|
||||||
waypoints: JSON.stringify(waypoints),
|
waypoints: JSON.stringify(waypoints),
|
||||||
}).changes;
|
});
|
||||||
}
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
import db from './db.ts';
|
import { DbData, db } from './db.ts';
|
||||||
|
|
||||||
const addTokenStatement = db.prepare(`INSERT INTO tokens(data) VALUES (?);`);
|
const addTokenStatement = db.prepare(`INSERT INTO tokens(data) VALUES (?);`);
|
||||||
const getTokenStatement = db.prepare(`SELECT data FROM tokens;`);
|
const getTokenStatement = db.prepare(`SELECT data FROM tokens;`);
|
||||||
|
|
||||||
export function addToken(token: string) {
|
export function addToken(token: string): void {
|
||||||
addTokenStatement.run(token);
|
addTokenStatement.run(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getToken(): string|null {
|
export function getToken(): string|null {
|
||||||
const data = getTokenStatement.get() as {data: string}|undefined;
|
const data = getTokenStatement.get() as DbData|undefined;
|
||||||
if (data === undefined) return null;
|
if (data === undefined) return null;
|
||||||
return data.data;
|
return data.data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import * as fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as events from 'events';
|
import events from 'events';
|
||||||
|
|
||||||
import { APIError, Request, RequestPromise, Response } from '../model/api.ts';
|
|
||||||
import { getToken } from '../database/tokens.ts';
|
|
||||||
import { PriorityQueue } from './priority_queue.ts';
|
import { PriorityQueue } from './priority_queue.ts';
|
||||||
|
import { getToken } from '../database/tokens.ts';
|
||||||
|
import { APIError, Request, RequestPromise, Response } from '../model/api.ts';
|
||||||
|
import { RateLimitError } from '../model/errors.ts';
|
||||||
|
|
||||||
// queue processor module variables
|
// queue processor module variables
|
||||||
const bus = new events.EventEmitter(); // a bus to notify the queue processor to start processing messages
|
const bus = new events.EventEmitter(); // a bus to notify the queue processor to start processing messages
|
||||||
|
@ -14,7 +15,7 @@ let running = false;
|
||||||
let headers: {[key:string]:string}|null = null; // a file scoped variable so that we only evaluate these once.
|
let headers: {[key:string]:string}|null = null; // a file scoped variable so that we only evaluate these once.
|
||||||
let queue = new PriorityQueue(); // a priority queue to hold api calls we want to send, allows for throttling.
|
let queue = new PriorityQueue(); // a priority queue to hold api calls we want to send, allows for throttling.
|
||||||
|
|
||||||
async function queue_processor() {
|
async function queue_processor(): Promise<void> {
|
||||||
if (running) {
|
if (running) {
|
||||||
throw 'refusing to start a second queue processor';
|
throw 'refusing to start a second queue processor';
|
||||||
}
|
}
|
||||||
|
@ -45,29 +46,7 @@ async function queue_processor() {
|
||||||
}
|
}
|
||||||
queue_processor();
|
queue_processor();
|
||||||
|
|
||||||
export async function send<T>(request: Request): Promise<T|APIError> {
|
export async function send<T>(request: Request): Promise<Response<T>> {
|
||||||
const response = await send_one<T>(request);
|
|
||||||
if (response.error) return response.error;
|
|
||||||
return response.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function sendPaginated<T>(request: Request): Promise<Array<T>|APIError> {
|
|
||||||
if (request.page === undefined) request.page = 1;
|
|
||||||
let ret: Array<T> = [];
|
|
||||||
while (true) {
|
|
||||||
const response = await send_one<T>(request);
|
|
||||||
if (response.meta === undefined) {
|
|
||||||
throw {"message": "paginated request did not return a meta block", "request": request, "response": response};
|
|
||||||
}
|
|
||||||
ret = ret.concat(response.data);
|
|
||||||
if (response.meta.limit * response.meta.page >= response.meta.total) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
request.page++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function send_one<T>(request: Request): Promise<Response<T>> {
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const data: RequestPromise<T> = {
|
const data: RequestPromise<T> = {
|
||||||
reject: reject,
|
reject: reject,
|
||||||
|
@ -81,8 +60,26 @@ function send_one<T>(request: Request): Promise<Response<T>> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function sendPaginated<T>(request: Request): Promise<Array<T>> {
|
||||||
|
if (request.page === undefined) request.page = 1;
|
||||||
|
let ret: Array<T> = [];
|
||||||
|
while (true) {
|
||||||
|
const response = await send<T>(request);
|
||||||
|
if (response.meta === undefined) {
|
||||||
|
throw {"message": "paginated request did not return a meta block", "request": request, "response": response};
|
||||||
|
} else if (response.error) {
|
||||||
|
throw {"message": "paginated request returned an error", "request": request, "response": response};
|
||||||
|
}
|
||||||
|
ret = ret.concat(response.data);
|
||||||
|
if (response.meta.limit * response.meta.page >= response.meta.total) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
request.page++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// send_this take a data object as argument built in the send function above
|
// send_this take a data object as argument built in the send function above
|
||||||
async function send_this(data: RequestPromise<unknown>) {
|
async function send_this(data: RequestPromise<unknown>): Promise<void> {
|
||||||
if (headers === null) {
|
if (headers === null) {
|
||||||
const token = getToken();
|
const token = getToken();
|
||||||
if (token === null) {
|
if (token === null) {
|
||||||
|
@ -119,7 +116,8 @@ async function send_this(data: RequestPromise<unknown>) {
|
||||||
// spawnSync?
|
// spawnSync?
|
||||||
// break;
|
// break;
|
||||||
case 429: // 429 means rate limited, let's hold back as instructed
|
case 429: // 429 means rate limited, let's hold back as instructed
|
||||||
backoffSeconds = json.error.data.retryAfter;
|
const errorData = json.error.data as RateLimitError;
|
||||||
|
backoffSeconds = errorData.retryAfter;
|
||||||
queue.enqueue(data, 1);
|
queue.enqueue(data, 1);
|
||||||
break;
|
break;
|
||||||
case 503: // 503 means maintenance mode, let's hold back for 1 minute
|
case 503: // 503 means maintenance mode, let's hold back for 1 minute
|
||||||
|
@ -150,7 +148,7 @@ async function send_this(data: RequestPromise<unknown>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function debugLog(ctx: any) {
|
export function debugLog(ctx: any): void {
|
||||||
console.log(`--- ${Date()} -----------------------------------------------------------------------------`);
|
console.log(`--- ${Date()} -----------------------------------------------------------------------------`);
|
||||||
console.log(JSON.stringify(ctx, null, 2));
|
console.log(JSON.stringify(ctx, null, 2));
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,21 +12,17 @@ import * as libShips from '../lib/ships.ts';
|
||||||
export async function accept(contract: Contract): Promise<Contract> {
|
export async function accept(contract: Contract): Promise<Contract> {
|
||||||
if (contract.accepted) return contract;
|
if (contract.accepted) return contract;
|
||||||
const response = await api.send<{agent: Agent, contract: Contract, type: ''}>({endpoint: `/my/contracts/${contract.id}/accept`, method: 'POST'});
|
const response = await api.send<{agent: Agent, contract: Contract, type: ''}>({endpoint: `/my/contracts/${contract.id}/accept`, method: 'POST'});
|
||||||
if ('apiError' in response) {
|
if (response.error) {
|
||||||
api.debugLog(response);
|
api.debugLog(response);
|
||||||
throw response;
|
throw response;
|
||||||
}
|
}
|
||||||
dbAgents.setAgent(response.agent);
|
dbAgents.setAgent(response.data.agent);
|
||||||
dbContracts.setContract(response.contract);
|
dbContracts.setContract(response.data.contract);
|
||||||
return response.contract;
|
return response.data.contract;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function contracts(): Promise<Array<Contract>> {
|
export async function contracts(): Promise<Array<Contract>> {
|
||||||
const response = await api.sendPaginated<Contract>({endpoint: '/my/contracts', page: 1});
|
const response = await api.sendPaginated<Contract>({endpoint: '/my/contracts'});
|
||||||
if ('apiError' in response) {
|
|
||||||
api.debugLog(response);
|
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
response.forEach(contract => dbContracts.setContract(contract));
|
response.forEach(contract => dbContracts.setContract(contract));
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
@ -44,8 +40,8 @@ export async function deliver(contract: Contract, ship: Ship): Promise<Contract>
|
||||||
tradeSymbol: tradeSymbol,
|
tradeSymbol: tradeSymbol,
|
||||||
units: units,
|
units: units,
|
||||||
}});
|
}});
|
||||||
if ('apiError' in response) {
|
if (response.error) {
|
||||||
switch(response.code) {
|
switch(response.error.code) {
|
||||||
case 4509: // contract delivery terms have been met
|
case 4509: // contract delivery terms have been met
|
||||||
return await fulfill(contract);
|
return await fulfill(contract);
|
||||||
default: // yet unhandled error
|
default: // yet unhandled error
|
||||||
|
@ -53,22 +49,22 @@ export async function deliver(contract: Contract, ship: Ship): Promise<Contract>
|
||||||
throw response;
|
throw response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbContracts.setContract(response.contract);
|
dbContracts.setContract(response.data.contract);
|
||||||
dbShips.setShipCargo(ship.symbol, response.cargo);
|
dbShips.setShipCargo(ship.symbol, response.data.cargo);
|
||||||
if(response.contract.terms.deliver[0].unitsRequired >= response.contract.terms.deliver[0].unitsFulfilled) {
|
if(response.data.contract.terms.deliver[0].unitsRequired >= response.data.contract.terms.deliver[0].unitsFulfilled) {
|
||||||
return await fulfill(contract);
|
return await fulfill(response.data.contract);
|
||||||
}
|
}
|
||||||
return response.contract;
|
return response.data.contract;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fulfill(contract: Contract): Promise<Contract> {
|
export async function fulfill(contract: Contract): Promise<Contract> {
|
||||||
if (contract.fulfilled) return contract;
|
if (contract.fulfilled) return contract;
|
||||||
const response = await api.send<{agent: Agent, contract: Contract}>({ endpoint: `/my/contracts/${contract.id}/fulfill`, method: 'POST'});
|
const response = await api.send<{agent: Agent, contract: Contract}>({ endpoint: `/my/contracts/${contract.id}/fulfill`, method: 'POST'});
|
||||||
if ('apiError' in response) {
|
if (response.error) {
|
||||||
api.debugLog(response);
|
api.debugLog(response);
|
||||||
throw response;
|
throw response;
|
||||||
}
|
}
|
||||||
dbAgents.setAgent(response.agent);
|
dbAgents.setAgent(response.data.agent);
|
||||||
dbContracts.setContract(response.contract);
|
dbContracts.setContract(response.data.contract);
|
||||||
return response.contract;
|
return response.data.contract;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,20 @@ import { Response } from '../model/api.ts';
|
||||||
import { Agent } from '../model/agent.ts';
|
import { Agent } from '../model/agent.ts';
|
||||||
import { Cargo } from '../model/cargo.ts';
|
import { Cargo } from '../model/cargo.ts';
|
||||||
import { Cooldown, Fuel, Nav, Ship } from '../model/ship.ts';
|
import { Cooldown, Fuel, Nav, Ship } from '../model/ship.ts';
|
||||||
import * as api from './api.js';
|
import * as api from './api.ts';
|
||||||
import * as dbAgents from '../database/agents.ts';
|
import * as dbAgents from '../database/agents.ts';
|
||||||
import * as dbShips from '../database/ships.js';
|
import * as dbShips from '../database/ships.ts';
|
||||||
import * as dbSurveys from '../database/surveys.js';
|
//import * as dbSurveys from '../database/surveys.ts';
|
||||||
import * as systems from '../lib/systems.js';
|
import * as systems from '../lib/systems.ts';
|
||||||
|
|
||||||
export async function dock(ship: Ship): Promise<Ship> {
|
export async function dock(ship: Ship): Promise<Ship> {
|
||||||
if (ship.nav.status === 'DOCKED') return ship;
|
if (ship.nav.status === 'DOCKED') return ship;
|
||||||
const response = await api.send({endpoint: `/my/ships/${ship.symbol}/dock`, method: 'POST'}) as Response<{nav: Nav}>;
|
const response = await api.send<{nav: Nav}>({endpoint: `/my/ships/${ship.symbol}/dock`, method: 'POST'});
|
||||||
if (response.error !== undefined) {
|
if (response.error) {
|
||||||
switch(response.error.code) {
|
switch(response.error.code) {
|
||||||
case 4214: // ship is in transit
|
case 4214: // ship is in transit
|
||||||
await api.sleep(response.error.data.secondsToArrival * 1000);
|
const errorData = response.error.data as { secondsToArrival: number};
|
||||||
|
await api.sleep(errorData.secondsToArrival * 1000);
|
||||||
return await dock(ship);
|
return await dock(ship);
|
||||||
default: // yet unhandled error
|
default: // yet unhandled error
|
||||||
api.debugLog(response);
|
api.debugLog(response);
|
||||||
|
@ -33,11 +34,12 @@ export async function extract(ship: Ship): Promise<Ship> {
|
||||||
//await navigate({symbol: ctx.symbol, waypoint: asteroidFields[0].symbol});
|
//await navigate({symbol: ctx.symbol, waypoint: asteroidFields[0].symbol});
|
||||||
ship = await orbit(ship);
|
ship = await orbit(ship);
|
||||||
// TODO handle surveying?
|
// TODO handle surveying?
|
||||||
const response = await api.send({endpoint: `/my/ships/${ship.symbol}/extract`, method: 'POST'}) as Response<{cooldown: Cooldown, cargo: Cargo}>; // TODO extraction and events api response fields cf https://spacetraders.stoplight.io/docs/spacetraders/b3931d097608d-extract-resources
|
const response = await api.send<{cooldown: Cooldown, cargo: Cargo}>({endpoint: `/my/ships/${ship.symbol}/extract`, method: 'POST'}); // TODO extraction and events api response fields cf https://spacetraders.stoplight.io/docs/spacetraders/b3931d097608d-extract-resources
|
||||||
if (response.error !== undefined) {
|
if (response.error) {
|
||||||
switch(response.error.code) {
|
switch(response.error.code) {
|
||||||
case 4000: // ship is on cooldown
|
case 4000: // ship is on cooldown
|
||||||
await api.sleep(response.error.data.cooldown.remainingSeconds * 1000);
|
const errorData = response.error.data as {cooldown: Cooldown};
|
||||||
|
await api.sleep(errorData.cooldown.remainingSeconds * 1000);
|
||||||
return await extract(ship);
|
return await extract(ship);
|
||||||
case 4228: // ship is full
|
case 4228: // ship is full
|
||||||
return ship;
|
return ship;
|
||||||
|
@ -69,11 +71,12 @@ export async function navigate(ship: Ship, waypoint: string): Promise<Ship> {
|
||||||
if (ship.nav.waypointSymbol === waypoint) return ship;
|
if (ship.nav.waypointSymbol === waypoint) return ship;
|
||||||
ship = await orbit(ship);
|
ship = await orbit(ship);
|
||||||
// TODO if we do not have enough fuel, make a stop to refuel along the way or drift to the destination
|
// TODO if we do not have enough fuel, make a stop to refuel along the way or drift to the destination
|
||||||
const response = await api.send({endpoint: `/my/ships/${ship.symbol}/navigate`, method: 'POST', payload: { waypointSymbol: waypoint }}) as Response<{fuel: Fuel, nav: Nav}>; // TODO events field
|
const response = await api.send<{fuel: Fuel, nav: Nav}>({endpoint: `/my/ships/${ship.symbol}/navigate`, method: 'POST', payload: { waypointSymbol: waypoint }}); // TODO events field
|
||||||
if (response.error !== undefined) {
|
if (response.error) {
|
||||||
switch(response.error.code) {
|
switch(response.error.code) {
|
||||||
case 4214: // ship is in transit
|
case 4214: // ship is in transit
|
||||||
await api.sleep(response.error.data.secondsToArrival * 1000);
|
const errorData = response.error.data as { secondsToArrival: number};
|
||||||
|
await api.sleep(errorData.secondsToArrival * 1000);
|
||||||
return await navigate(ship, waypoint);
|
return await navigate(ship, waypoint);
|
||||||
default: // yet unhandled error
|
default: // yet unhandled error
|
||||||
api.debugLog(response);
|
api.debugLog(response);
|
||||||
|
@ -89,8 +92,8 @@ export async function navigate(ship: Ship, waypoint: string): Promise<Ship> {
|
||||||
response.data.nav.status = 'IN_ORBIT'; // we arrive in orbit
|
response.data.nav.status = 'IN_ORBIT'; // we arrive in orbit
|
||||||
dbShips.setShipNav(ship.symbol, response.data.nav);
|
dbShips.setShipNav(ship.symbol, response.data.nav);
|
||||||
ship.nav = response.data.nav
|
ship.nav = response.data.nav
|
||||||
ship = await refuel(ship);
|
// TODO only refuel at the start of a journey, if we do not have enough OR if the destination does not sell fuel?
|
||||||
return ship;
|
return await refuel(ship);
|
||||||
}
|
}
|
||||||
|
|
||||||
//export async function negotiate(ctx) {
|
//export async function negotiate(ctx) {
|
||||||
|
@ -100,11 +103,12 @@ export async function navigate(ship: Ship, waypoint: string): Promise<Ship> {
|
||||||
|
|
||||||
export async function orbit(ship: Ship): Promise<Ship> {
|
export async function orbit(ship: Ship): Promise<Ship> {
|
||||||
if (ship.nav.status === 'IN_ORBIT') return ship;
|
if (ship.nav.status === 'IN_ORBIT') return ship;
|
||||||
const response = await api.send({endpoint: `/my/ships/${ship.symbol}/orbit`, method: 'POST'}) as Response<{nav: Nav}>;
|
const response = await api.send<{nav: Nav}>({endpoint: `/my/ships/${ship.symbol}/orbit`, method: 'POST'});
|
||||||
if (response.error !== undefined) {
|
if (response.error) {
|
||||||
switch(response.error.code) {
|
switch(response.error.code) {
|
||||||
case 4214: // ship is in transit
|
case 4214: // ship is in transit
|
||||||
await api.sleep(response.error.data.secondsToArrival * 1000);
|
const errorData = response.error.data as { secondsToArrival: number};
|
||||||
|
await api.sleep(errorData.secondsToArrival * 1000);
|
||||||
return await orbit(ship);
|
return await orbit(ship);
|
||||||
default: // yet unhandled error
|
default: // yet unhandled error
|
||||||
throw response;
|
throw response;
|
||||||
|
@ -131,8 +135,8 @@ export async function refuel(ship: Ship): Promise<Ship> {
|
||||||
if (ship.fuel.current >= ship.fuel.capacity * 0.9) return ship;
|
if (ship.fuel.current >= ship.fuel.capacity * 0.9) return ship;
|
||||||
// TODO check if our current waypoint has a marketplace (and sells fuel)?
|
// TODO check if our current waypoint has a marketplace (and sells fuel)?
|
||||||
ship = await dock(ship);
|
ship = await dock(ship);
|
||||||
const response = await api.send({endpoint: `/my/ships/${ship.symbol}/refuel`, method: 'POST'}) as Response<{agent: Agent, fuel: Fuel}>; // TODO transaction field
|
const response = await api.send<{agent: Agent, fuel: Fuel}>({endpoint: `/my/ships/${ship.symbol}/refuel`, method: 'POST'}); // TODO transaction field
|
||||||
if (response.error !== undefined) {
|
if (response.error) {
|
||||||
api.debugLog(response);
|
api.debugLog(response);
|
||||||
throw response;
|
throw response;
|
||||||
}
|
}
|
||||||
|
@ -143,12 +147,12 @@ export async function refuel(ship: Ship): Promise<Ship> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function sell(ship: Ship, tradeSymbol: string): Promise<Ship> {
|
export async function sell(ship: Ship, tradeSymbol: string): Promise<Ship> {
|
||||||
// TODO check if our current waypoint has a marketplace?
|
// TODO check if our current waypoint has a marketplace and buys tradeSymbol?
|
||||||
ship = await dock(ship);
|
ship = await dock(ship);
|
||||||
let units = 0;
|
let units = 0;
|
||||||
ship.cargo.inventory.forEach(i => {if (i.symbol === tradeSymbol) units = i.units; });
|
ship.cargo.inventory.forEach(i => {if (i.symbol === tradeSymbol) units = i.units; });
|
||||||
const response = await api.send({endpoint: `/my/ships/${ship.symbol}/sell`, method: 'POST', payload: { symbol: tradeSymbol, units: units }}) as Response<{agent: Agent, cargo: Cargo}>; // TODO transaction field
|
const response = await api.send<{agent: Agent, cargo: Cargo}>({endpoint: `/my/ships/${ship.symbol}/sell`, method: 'POST', payload: { symbol: tradeSymbol, units: units }}); // TODO transaction field
|
||||||
if (response.error !== undefined) {
|
if (response.error) {
|
||||||
api.debugLog(response);
|
api.debugLog(response);
|
||||||
throw response;
|
throw response;
|
||||||
}
|
}
|
||||||
|
@ -159,8 +163,8 @@ export async function sell(ship: Ship, tradeSymbol: string): Promise<Ship> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function ships(): Promise<Array<Ship>> {
|
export async function ships(): Promise<Array<Ship>> {
|
||||||
const response = await api.send({endpoint: `/my/ships`, page: 1}) as Response<Array<Ship>>;
|
const response = await api.send<Array<Ship>>({endpoint: `/my/ships`, page: 1});
|
||||||
if (response.error !== undefined) {
|
if (response.error) {
|
||||||
api.debugLog(response);
|
api.debugLog(response);
|
||||||
throw response;
|
throw response;
|
||||||
}
|
}
|
||||||
|
@ -169,8 +173,8 @@ export async function ships(): Promise<Array<Ship>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function ship(ship: Ship): Promise<Ship> {
|
export async function ship(ship: Ship): Promise<Ship> {
|
||||||
const response = await api.send({endpoint: `/my/ships/${ship.symbol}`}) as Response<Ship>;
|
const response = await api.send<Ship>({endpoint: `/my/ships/${ship.symbol}`});
|
||||||
if (response.error !== undefined) {
|
if (response.error) {
|
||||||
api.debugLog(response);
|
api.debugLog(response);
|
||||||
throw response;
|
throw response;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,86 +1,60 @@
|
||||||
import * as api from './api.js';
|
import * as api from './api.ts';
|
||||||
import * as dbMarkets from '../database/markets.js';
|
import * as dbMarkets from '../database/markets.ts';
|
||||||
import * as dbShips from '../database/ships.js';
|
import * as dbShips from '../database/ships.ts';
|
||||||
import * as dbSystems from '../database/systems.js';
|
import * as dbSystems from '../database/systems.ts';
|
||||||
import * as utils from './utils.js';
|
import { Market } from '../model/market.ts'
|
||||||
|
import { System, Waypoint } from '../model/system.ts'
|
||||||
|
import * as utils from './utils.ts';
|
||||||
|
|
||||||
// Retrieves a marketplace's market data for waypointSymbol
|
export async function market(waypointSymbol: string): Promise<Market> {
|
||||||
export async function market(waypointSymbol: string) {
|
|
||||||
const data = dbMarkets.getMarketAtWaypoint(waypointSymbol);
|
const data = dbMarkets.getMarketAtWaypoint(waypointSymbol);
|
||||||
if (data === null) {
|
if (data) { return data; }
|
||||||
if (dbShips.getShipsAt(waypointSymbol) === null) {
|
const systemSymbol = utils.systemFromWaypoint(waypointSymbol);
|
||||||
return null;
|
let response = await api.send<Market>({endpoint: `/systems/${systemSymbol}/waypoints/${waypointSymbol}/market`});
|
||||||
}
|
if (response.error) {
|
||||||
const systemSymbol = utils.systemFromWaypoint(waypointSymbol);
|
api.debugLog(response);
|
||||||
let d = await api.send({endpoint: `/systems/${systemSymbol}/waypoints/${waypointSymbol}/market`});
|
throw response;
|
||||||
delete d.data.transactions;
|
|
||||||
dbMarkets.setMarket(d.data);
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieves a shipyard's information for ctx.symbol
|
|
||||||
export async function shipyard(ctx) {
|
|
||||||
const systemSymbol = utils.systemFromWaypoint(ctx.symbol);
|
|
||||||
return await api.send({endpoint: `/systems/${systemSymbol}/waypoints/${ctx.symbol}/shipyard`});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieves the system's information for ctx.symbol and caches it in the database
|
|
||||||
export async function system(ctx) {
|
|
||||||
let s = dbSystems.getSystem(ctx.symbol);
|
|
||||||
if (s === null) {
|
|
||||||
const response = await api.send({endpoint: `/systems/${ctx.symbol}`});
|
|
||||||
if (response.error !== undefined) {
|
|
||||||
switch(response.error.code) {
|
|
||||||
case 404:
|
|
||||||
throw `Error retrieving info for system ${ctx.symbol}: ${response.error.message}`;
|
|
||||||
default: // yet unhandled error
|
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s = response.data;
|
|
||||||
dbSystems.setSystem(s);
|
|
||||||
}
|
}
|
||||||
return s;
|
dbMarkets.setMarket(response.data);
|
||||||
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieves a list of waypoints that have a specific ctx.trait like a SHIPYARD or a MARKETPLACE in the system ctx.symbol
|
//export async function shipyard(waypoint: string): Promise<unknown> {
|
||||||
export async function trait(ctx) {
|
// // TODO database caching
|
||||||
const w = await waypoints(ctx);
|
// const systemSymbol = utils.systemFromWaypoint(waypoint);
|
||||||
return w.filter(s => s.traits.some(t => t.symbol === ctx.trait));
|
// return await api.send({endpoint: `/systems/${systemSymbol}/waypoints/${waypoint}/shipyard`});
|
||||||
|
//}
|
||||||
|
|
||||||
|
export async function system(symbol: string): Promise<System> {
|
||||||
|
let data = dbSystems.getSystem(symbol);
|
||||||
|
if (data) { return data; }
|
||||||
|
const response = await api.send<System>({endpoint: `/systems/${symbol}`});
|
||||||
|
if (response.error) {
|
||||||
|
api.debugLog(response);
|
||||||
|
throw response;
|
||||||
|
}
|
||||||
|
dbSystems.setSystem(response.data);
|
||||||
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieves a list of waypoints that have a specific ctx.type like ASTEROID_FIELD in the system ctx.symbol
|
// Retrieves a list of waypoints that have a specific trait like a SHIPYARD or a MARKETPLACE
|
||||||
export async function type(ctx, response) {
|
export async function trait(system: string, trait: string): Promise<Array<Waypoint>> {
|
||||||
const w = await waypoints(ctx);
|
const ws = await waypoints(system);
|
||||||
return w.filter(s => s.type === ctx.type);
|
return ws.filter(w => w.traits.some(t => t.symbol === trait));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieves the system's information for ctx.symbol and caches it in the database
|
// Retrieves a list of waypoints that have a specific type like ASTEROID_FIELD
|
||||||
export async function waypoints(ctx) {
|
export async function type(system: string, typeSymbol: string): Promise<Array<Waypoint>> {
|
||||||
await system(ctx);
|
const ws = await waypoints(system);
|
||||||
let updated = dbSystems.getSystemUpdated(ctx.symbol);
|
return ws.filter(s => s.type === typeSymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function waypoints(systemSymbol: string): Promise<Array<Waypoint>> {
|
||||||
|
const s = await system(systemSymbol);
|
||||||
|
const updated = dbSystems.getSystemUpdated(systemSymbol);
|
||||||
// TODO handle uncharted systems
|
// TODO handle uncharted systems
|
||||||
if (updated === null) {
|
if (updated) return s.waypoints;
|
||||||
let waypoints = [];
|
const waypoints = await api.sendPaginated<Waypoint>({endpoint: `/systems/${systemSymbol}/waypoints`});
|
||||||
for (let page=1; true; ++page) {
|
dbSystems.setSystemWaypoints(systemSymbol, waypoints);
|
||||||
const response = await api.send({endpoint: `/systems/${ctx.symbol}/waypoints?limit=20&page=${page}`, priority: 98});
|
return waypoints;
|
||||||
if (response.error !== undefined) {
|
|
||||||
switch(response.error.code) {
|
|
||||||
case 404:
|
|
||||||
throw `Error retrieving waypoints for system ${ctx.symbol}: ${response.error.message}`;
|
|
||||||
default: // yet unhandled error
|
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
waypoints = waypoints.concat(response.data);
|
|
||||||
if (response.meta.total <= response.meta.limit * page) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dbSystems.setSystemWaypoints(ctx.symbol, waypoints);
|
|
||||||
return waypoints;
|
|
||||||
}
|
|
||||||
return dbSystems.getSystem(ctx.symbol).waypoints;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import * as autoContracting from './automation/contracting.ts';
|
import * as autoContracting from './automation/contracting.ts';
|
||||||
//import * as autoExploring from './automation/exploration.js';
|
//import * as autoExploring from './automation/exploration.ts';
|
||||||
import * as autoInit from './automation/init.js';
|
import * as autoInit from './automation/init.ts';
|
||||||
//import * as api from './lib/api.js';
|
//import * as api from './lib/api.ts';
|
||||||
//import * as contracts from './lib/contracts.js';
|
//import * as contracts from './lib/contracts.ts';
|
||||||
|
|
||||||
await autoInit.init();
|
await autoInit.init();
|
||||||
autoContracting.init();
|
autoContracting.init();
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
export type APIError = {
|
export type APIError = {
|
||||||
apiError: 'APIError';
|
|
||||||
error: string;
|
error: string;
|
||||||
code: number;
|
code: number;
|
||||||
data: any; // TODO
|
data: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Meta = {
|
export type Meta = {
|
||||||
|
|
5
nodejs/model/common.ts
Normal file
5
nodejs/model/common.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export type CommonThing = {
|
||||||
|
description: string;
|
||||||
|
name: string;
|
||||||
|
symbol: string;
|
||||||
|
};
|
8
nodejs/model/errors.ts
Normal file
8
nodejs/model/errors.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
export type RateLimitError = {
|
||||||
|
type: string;
|
||||||
|
retryAfter: number;
|
||||||
|
limitBurst: number;
|
||||||
|
limitPerSecond: number;
|
||||||
|
remaining: number;
|
||||||
|
reset: Date;
|
||||||
|
};
|
19
nodejs/model/market.ts
Normal file
19
nodejs/model/market.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { CommonThing } from 'common.ts';
|
||||||
|
|
||||||
|
export type TradeGood = CommonThing & {
|
||||||
|
activity: string;
|
||||||
|
purchasePrice: number;
|
||||||
|
sellPrice: number;
|
||||||
|
supply: string;
|
||||||
|
tradeVolume: number;
|
||||||
|
type: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Market = {
|
||||||
|
symbol: string;
|
||||||
|
exchange: Array<CommonThing>;
|
||||||
|
exports: Array<CommonThing>;
|
||||||
|
imports: Array<CommonThing>;
|
||||||
|
//transactions: Array<Transaction>;
|
||||||
|
tradeGoods: Array<TradeGood>;
|
||||||
|
};
|
|
@ -25,6 +25,12 @@ export type Nav = {
|
||||||
waypointSymbol: string;
|
waypointSymbol: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Registration = {
|
||||||
|
factionSymbol: string;
|
||||||
|
name: string;
|
||||||
|
role: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type Route = {
|
export type Route = {
|
||||||
arrival: Date;
|
arrival: Date;
|
||||||
departureTime: Date;
|
departureTime: Date;
|
||||||
|
@ -51,6 +57,6 @@ export type Ship = {
|
||||||
// mounts
|
// mounts
|
||||||
nav: Nav;
|
nav: Nav;
|
||||||
// reactor
|
// reactor
|
||||||
// registration
|
registration: Registration;
|
||||||
symbol: string;
|
symbol: string;
|
||||||
};
|
};
|
||||||
|
|
30
nodejs/model/system.ts
Normal file
30
nodejs/model/system.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { CommonThing } from 'common.ts';
|
||||||
|
|
||||||
|
export type Chart = {
|
||||||
|
waypointSymbol: string;
|
||||||
|
submittedBy: string;
|
||||||
|
submittedOn: Date;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type System = {
|
||||||
|
symbol: string;
|
||||||
|
sectorSymbol: string;
|
||||||
|
type: string;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
waypoints: Array<Waypoint>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Waypoint = {
|
||||||
|
chart: Chart;
|
||||||
|
factions: Array<{symbol: string;}>;
|
||||||
|
isUnderConstruction: boolean;
|
||||||
|
modifiers: Array<CommonThing>;
|
||||||
|
orbitals: Array<{symbol: string;}>;
|
||||||
|
orbits: string;
|
||||||
|
symbol: string;
|
||||||
|
traits: Array<CommonThing>;
|
||||||
|
type: string;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
};
|
641
nodejs/package-lock.json
generated
641
nodejs/package-lock.json
generated
|
@ -5,10 +5,402 @@
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"better-sqlite3": "^9.3.0"
|
"@types/better-sqlite3": "^7.6.9",
|
||||||
|
"better-sqlite3": "^9.4.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"esrun": "^3.2.26",
|
||||||
|
"typescript": "^5.4.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.10.0"
|
"node": ">=21.6.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@digitak/grubber": {
|
||||||
|
"version": "3.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@digitak/grubber/-/grubber-3.1.4.tgz",
|
||||||
|
"integrity": "sha512-pqsnp2BUYlDoTXWG34HWgEJse/Eo1okRgNex8IG84wHrJp8h3SakeR5WhB4VxSA2+/D+frNYJ0ch3yXzsfNDoA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/android-arm": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/android-arm64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/android-x64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/darwin-arm64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/darwin-x64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/freebsd-arm64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/freebsd-x64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-arm": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-arm64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-ia32": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-loong64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==",
|
||||||
|
"cpu": [
|
||||||
|
"loong64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-mips64el": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==",
|
||||||
|
"cpu": [
|
||||||
|
"mips64el"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-ppc64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==",
|
||||||
|
"cpu": [
|
||||||
|
"ppc64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-riscv64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==",
|
||||||
|
"cpu": [
|
||||||
|
"riscv64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-s390x": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==",
|
||||||
|
"cpu": [
|
||||||
|
"s390x"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/linux-x64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/netbsd-x64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"netbsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/openbsd-x64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"openbsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/sunos-x64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"sunos"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/win32-arm64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/win32-ia32": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@esbuild/win32-x64": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/better-sqlite3": {
|
||||||
|
"version": "7.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.9.tgz",
|
||||||
|
"integrity": "sha512-FvktcujPDj9XKMJQWFcl2vVl7OdRIqsSRX9b0acWwTmwLK9CF2eqo/FRcmMLNpugKoX/avA6pb7TorDLmpgTnQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "20.11.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz",
|
||||||
|
"integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~5.26.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/anymatch": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"normalize-path": "^3.0.0",
|
||||||
|
"picomatch": "^2.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/base64-js": {
|
"node_modules/base64-js": {
|
||||||
|
@ -40,6 +432,18 @@
|
||||||
"prebuild-install": "^7.1.1"
|
"prebuild-install": "^7.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/binary-extensions": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bindings": {
|
"node_modules/bindings": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||||
|
@ -58,6 +462,18 @@
|
||||||
"readable-stream": "^3.4.0"
|
"readable-stream": "^3.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/braces": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fill-range": "^7.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/buffer": {
|
"node_modules/buffer": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
|
@ -81,6 +497,30 @@
|
||||||
"ieee754": "^1.1.13"
|
"ieee754": "^1.1.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chokidar": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"anymatch": "~3.1.2",
|
||||||
|
"braces": "~3.0.2",
|
||||||
|
"glob-parent": "~5.1.2",
|
||||||
|
"is-binary-path": "~2.1.0",
|
||||||
|
"is-glob": "~4.0.1",
|
||||||
|
"normalize-path": "~3.0.0",
|
||||||
|
"readdirp": "~3.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.10.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "~2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chownr": {
|
"node_modules/chownr": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||||
|
@ -124,6 +564,60 @@
|
||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/esbuild": {
|
||||||
|
"version": "0.17.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz",
|
||||||
|
"integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"esbuild": "bin/esbuild"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@esbuild/android-arm": "0.17.19",
|
||||||
|
"@esbuild/android-arm64": "0.17.19",
|
||||||
|
"@esbuild/android-x64": "0.17.19",
|
||||||
|
"@esbuild/darwin-arm64": "0.17.19",
|
||||||
|
"@esbuild/darwin-x64": "0.17.19",
|
||||||
|
"@esbuild/freebsd-arm64": "0.17.19",
|
||||||
|
"@esbuild/freebsd-x64": "0.17.19",
|
||||||
|
"@esbuild/linux-arm": "0.17.19",
|
||||||
|
"@esbuild/linux-arm64": "0.17.19",
|
||||||
|
"@esbuild/linux-ia32": "0.17.19",
|
||||||
|
"@esbuild/linux-loong64": "0.17.19",
|
||||||
|
"@esbuild/linux-mips64el": "0.17.19",
|
||||||
|
"@esbuild/linux-ppc64": "0.17.19",
|
||||||
|
"@esbuild/linux-riscv64": "0.17.19",
|
||||||
|
"@esbuild/linux-s390x": "0.17.19",
|
||||||
|
"@esbuild/linux-x64": "0.17.19",
|
||||||
|
"@esbuild/netbsd-x64": "0.17.19",
|
||||||
|
"@esbuild/openbsd-x64": "0.17.19",
|
||||||
|
"@esbuild/sunos-x64": "0.17.19",
|
||||||
|
"@esbuild/win32-arm64": "0.17.19",
|
||||||
|
"@esbuild/win32-ia32": "0.17.19",
|
||||||
|
"@esbuild/win32-x64": "0.17.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/esrun": {
|
||||||
|
"version": "3.2.26",
|
||||||
|
"resolved": "https://registry.npmjs.org/esrun/-/esrun-3.2.26.tgz",
|
||||||
|
"integrity": "sha512-gDjP87qj4RW0BryZXPY3/L161hPo9uG6luBTjLsuHG3cKnhSMrzB7eNzSzvDyBLg7OgugyvzSgB2ov7mZ/oa7Q==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@digitak/grubber": "^3.1.4",
|
||||||
|
"chokidar": "^3.5.1",
|
||||||
|
"esbuild": "^0.17.4"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"esrun": "bin.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expand-template": {
|
"node_modules/expand-template": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
||||||
|
@ -137,16 +631,54 @@
|
||||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
|
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/fill-range": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fs-constants": {
|
"node_modules/fs-constants": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
||||||
},
|
},
|
||||||
|
"node_modules/fsevents": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/github-from-package": {
|
"node_modules/github-from-package": {
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
||||||
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
|
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/glob-parent": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-glob": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ieee754": {
|
"node_modules/ieee754": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
@ -176,6 +708,48 @@
|
||||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
|
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
|
||||||
},
|
},
|
||||||
|
"node_modules/is-binary-path": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"binary-extensions": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-extglob": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-glob": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-extglob": "^2.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
|
@ -227,6 +801,15 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/normalize-path": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/once": {
|
"node_modules/once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
@ -235,6 +818,18 @@
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/picomatch": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prebuild-install": {
|
"node_modules/prebuild-install": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz",
|
||||||
|
@ -296,6 +891,18 @@
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/readdirp": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"picomatch": "^2.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/safe-buffer": {
|
"node_modules/safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
@ -414,6 +1021,18 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tunnel-agent": {
|
"node_modules/tunnel-agent": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||||
|
@ -425,6 +1044,24 @@
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/typescript": {
|
||||||
|
"version": "5.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz",
|
||||||
|
"integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"tsc": "bin/tsc",
|
||||||
|
"tsserver": "bin/tsserver"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undici-types": {
|
||||||
|
"version": "5.26.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
|
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
{
|
{
|
||||||
|
"module": "nodenext",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.10.0"
|
"node": ">=21.6.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"esrun": "^3.2.26",
|
||||||
|
"typescript": "^5.4.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"better-sqlite3": "^9.3.0"
|
"@types/better-sqlite3": "^7.6.9",
|
||||||
|
"better-sqlite3": "^9.4.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue