mirror of
https://github.com/HeyPuter/puter.git
synced 2026-10-18 09:40:20 +00:00
refactor: flatten the monorepo
This commit is contained in:
1 parent
f88c4a5c9c
commit
fa7bec3854
38 files changed
+218
-340
No files matched your search
Generated
+29
-1
@@ -7,12 +7,12 @@
|
||||
"": {
|
||||
"name": "puter.com",
|
||||
"version": "2.3.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "AGPL-3.0-only",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"dependencies": {
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"json-colorizer": "^3.0.1",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
@@ -5456,6 +5456,10 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/contextlink": {
|
||||
"resolved": "packages/contextlink",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/convert-source-map": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||
@@ -5789,6 +5793,10 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/dev-pty": {
|
||||
"resolved": "packages/pty",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
|
||||
@@ -10712,6 +10720,10 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/strataparse": {
|
||||
"resolved": "packages/strataparse",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/streamsearch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||
@@ -12061,6 +12073,13 @@
|
||||
"typescript": "^5.1.6"
|
||||
}
|
||||
},
|
||||
"packages/contextlink": {
|
||||
"version": "0.0.0",
|
||||
"license": "AGPL-3.0-only",
|
||||
"devDependencies": {
|
||||
"mocha": "^10.2.0"
|
||||
}
|
||||
},
|
||||
"packages/git": {
|
||||
"version": "1.0.0",
|
||||
"license": "AGPL-3.0-only",
|
||||
@@ -12312,6 +12331,11 @@
|
||||
"extraneous": true,
|
||||
"license": "AGPL-3.0-only"
|
||||
},
|
||||
"packages/pty": {
|
||||
"name": "dev-pty",
|
||||
"version": "0.0.0",
|
||||
"license": "AGPL-3.0-only"
|
||||
},
|
||||
"packages/puter-js": {
|
||||
"name": "@heyputer/puterjs",
|
||||
"version": "1.0.0",
|
||||
@@ -12326,6 +12350,10 @@
|
||||
"version": "1.0.0",
|
||||
"license": "UNLICENSED"
|
||||
},
|
||||
"packages/strataparse": {
|
||||
"version": "0.0.0",
|
||||
"license": "AGPL-3.0-only"
|
||||
},
|
||||
"packages/terminal": {
|
||||
"name": "@heyputer/terminal",
|
||||
"version": "0.0.0",
|
||||
|
||||
+1
-2
@@ -29,8 +29,7 @@
|
||||
"start=gui": "nodemon --exec \"node dev-server.js\" ",
|
||||
"start": "node run-selfhosted.js",
|
||||
"build": "node ./build.js",
|
||||
"check-translations": "node tools/check-translations.js",
|
||||
"postinstall": "cd packages/phoenix && cd packages/contextlink && npm install && cd - && cd packages/strataparse && npm install && cd - && cd packages/pty && npm install"
|
||||
"check-translations": "node tools/check-translations.js"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter.
|
||||
*
|
||||
* Puter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
const { AdvancedBase } = require('./src/AdvancedBase');
|
||||
|
||||
module.exports = {
|
||||
AdvancedBase,
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "@heyputer/puter-js-common",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Puter Technologies Inc.",
|
||||
"license": "UNLICENSED"
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter.
|
||||
*
|
||||
* Puter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// This doesn't go in ./bases because it logically depends on
|
||||
// both ./bases and ./traits, and ./traits depends on ./bases.
|
||||
|
||||
const { TraitBase } = require("./bases/TraitBase");
|
||||
|
||||
class AdvancedBase extends TraitBase {
|
||||
static TRAITS = [
|
||||
require('./traits/NodeModuleDITrait'),
|
||||
require('./traits/PropertiesTrait'),
|
||||
]
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
AdvancedBase,
|
||||
};
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter.
|
||||
*
|
||||
* Puter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
class BasicBase {
|
||||
_get_inheritance_chain () {
|
||||
const chain = [];
|
||||
let cls = this.constructor;
|
||||
while ( cls && cls !== BasicBase ) {
|
||||
chain.push(cls);
|
||||
cls = cls.__proto__;
|
||||
}
|
||||
return chain.reverse();
|
||||
}
|
||||
|
||||
_get_merged_static_array (key) {
|
||||
const chain = this._get_inheritance_chain();
|
||||
const values = [];
|
||||
for ( const cls of chain ) {
|
||||
if ( cls[key] ) {
|
||||
values.push(...cls[key]);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
_get_merged_static_object (key) {
|
||||
const chain = this._get_inheritance_chain();
|
||||
const values = {};
|
||||
for ( const cls of chain ) {
|
||||
if ( cls[key] ) {
|
||||
Object.assign(values, cls[key]);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
BasicBase,
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter.
|
||||
*
|
||||
* Puter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
const { BasicBase } = require("./BasicBase");
|
||||
|
||||
class TraitBase extends BasicBase {
|
||||
constructor (parameters, ...a) {
|
||||
super(parameters, ...a);
|
||||
for ( const trait of this.traits ) {
|
||||
trait.install_in_instance(
|
||||
this,
|
||||
{
|
||||
parameters: parameters || {},
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
get traits () {
|
||||
return this._get_merged_static_array('TRAITS');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
TraitBase,
|
||||
};
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter.
|
||||
*
|
||||
* Puter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* This trait allows dependency injection of node modules.
|
||||
* This is incredibly useful for passing mock implementations
|
||||
* of modules for unit testing.
|
||||
*
|
||||
* @example
|
||||
* class MyClass extends AdvancedBase {
|
||||
* static MODULES = {
|
||||
* axios,
|
||||
* };
|
||||
* }
|
||||
*
|
||||
* const my_class = new MyClass({
|
||||
* modules: {
|
||||
* axios: MY_AXIOS_MOCK,
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
module.exports = {
|
||||
install_in_instance: (instance, { parameters }) => {
|
||||
const modules = instance._get_merged_static_object('MODULES');
|
||||
|
||||
if ( parameters.modules ) {
|
||||
for ( const k in parameters.modules ) {
|
||||
modules[k] = parameters.modules[k];
|
||||
}
|
||||
}
|
||||
|
||||
instance.modules = modules;
|
||||
|
||||
// This "require" function can shadow the real one so
|
||||
// that editor tools are aware of the modules that
|
||||
// are being used.
|
||||
instance.require = (name) => {
|
||||
if ( modules[name] ) {
|
||||
return modules[name];
|
||||
}
|
||||
return require(name);
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter.
|
||||
*
|
||||
* Puter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
module.exports = {
|
||||
install_in_instance: (instance) => {
|
||||
const properties = instance._get_merged_static_object('PROPERTIES');
|
||||
|
||||
for ( const k in properties ) {
|
||||
if ( typeof properties[k] === 'function' ) {
|
||||
instance[k] = properties[k]();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( typeof properties[k] === 'object' ) {
|
||||
// This will be supported in the future.
|
||||
throw new Error(`Property ${k} in ${instance.constructor.name} ` +
|
||||
`is not a supported property specification.`);
|
||||
}
|
||||
|
||||
instance[k] = properties[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter.
|
||||
*
|
||||
* Puter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
const { expect } = require('chai');
|
||||
const { BasicBase } = require('../src/bases/BasicBase');
|
||||
const { AdvancedBase } = require('../src/AdvancedBase');
|
||||
|
||||
class ClassA extends BasicBase {
|
||||
static STATIC_OBJ = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
};
|
||||
static STATIC_ARR = ['a', 'b'];
|
||||
}
|
||||
|
||||
class ClassB extends ClassA {
|
||||
static STATIC_OBJ = {
|
||||
c: 3,
|
||||
d: 4,
|
||||
};
|
||||
static STATIC_ARR = ['c', 'd'];
|
||||
}
|
||||
|
||||
describe('testing', () => {
|
||||
it('does a thing', () => {
|
||||
const b = new ClassB();
|
||||
|
||||
console.log(b._get_inheritance_chain());
|
||||
console.log([ClassA, ClassB]);
|
||||
expect(b._get_inheritance_chain()).deep.equal([ClassA, ClassB]);
|
||||
expect(b._get_merged_static_array('STATIC_ARR'))
|
||||
.deep.equal(['a', 'b', 'c', 'd']);
|
||||
expect(b._get_merged_static_object('STATIC_OBJ'))
|
||||
.deep.equal({ a: 1, b: 2, c: 3, d: 4 });
|
||||
});
|
||||
});
|
||||
|
||||
class ClassWithModule extends AdvancedBase {
|
||||
static MODULES = {
|
||||
axios: 'axios',
|
||||
};
|
||||
}
|
||||
|
||||
describe('AdvancedBase', () => {
|
||||
it('passes DI modules to instance', () => {
|
||||
const c1 = new ClassWithModule();
|
||||
expect(c1.modules.axios).to.equal('axios');
|
||||
|
||||
const c2 = new ClassWithModule({
|
||||
modules: {
|
||||
axios: 'my-axios',
|
||||
},
|
||||
});
|
||||
expect(c2.modules.axios).to.equal('my-axios');
|
||||
});
|
||||
});
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
Generated
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -20,6 +20,7 @@ import { nodeResolve } from '@rollup/plugin-node-resolve'
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import copy from 'rollup-plugin-copy';
|
||||
import process from 'node:process';
|
||||
import path from 'node:path';
|
||||
|
||||
const configFile = process.env.CONFIG_FILE ?? 'config/dev.js';
|
||||
await import(`./${configFile}`);
|
||||
@@ -34,6 +35,7 @@ export default {
|
||||
nodeResolve({
|
||||
browser: true,
|
||||
preferBuiltins: false,
|
||||
rootDir: path.join(process.cwd(), '..'),
|
||||
}),
|
||||
commonjs(),
|
||||
copy({
|
||||
|
||||
@@ -20,6 +20,7 @@ import { nodeResolve } from '@rollup/plugin-node-resolve'
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import copy from 'rollup-plugin-copy';
|
||||
import process from 'node:process';
|
||||
import path from 'node:path';
|
||||
|
||||
const configFile = process.env.CONFIG_FILE ?? 'config/dev.js';
|
||||
await import(`./${configFile}`);
|
||||
@@ -31,7 +32,9 @@ export default {
|
||||
format: "iife"
|
||||
},
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
nodeResolve({
|
||||
rootDir: path.join(process.cwd(), '..'),
|
||||
}),
|
||||
commonjs(),
|
||||
copy({
|
||||
targets: [
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { TeePromise, raceCase } from '../../src/promise.js';
|
||||
import { libs } from '@heyputer/puter-js-common';
|
||||
const { TeePromise, raceCase } = libs.promise;
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
|
||||
@@ -187,7 +188,7 @@ export class BetterReader {
|
||||
}
|
||||
if ( which === 'cancel' ) {
|
||||
this.channel_.pushback(...chunks);
|
||||
return
|
||||
return
|
||||
}
|
||||
if ( n_read + chunk.length > opt_buffer.length ) {
|
||||
const diff = opt_buffer.length - n_read;
|
||||
@@ -320,7 +321,7 @@ export class PTT {
|
||||
|
||||
/**
|
||||
* PTY: pseudo-terminal
|
||||
*
|
||||
*
|
||||
* This implements the PTY device driver.
|
||||
*/
|
||||
export class PTY {
|
||||
File renamed without changes.
File renamed without changes.
@@ -2,4 +2,7 @@ const { AdvancedBase } = require('./src/AdvancedBase');
|
||||
|
||||
module.exports = {
|
||||
AdvancedBase,
|
||||
libs: {
|
||||
promise: require('./src/libs/promise'),
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter.
|
||||
*
|
||||
* Puter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
class TeePromise {
|
||||
static STATUS_PENDING = Symbol('pending');
|
||||
static STATUS_RUNNING = {};
|
||||
static STATUS_DONE = Symbol('done');
|
||||
constructor () {
|
||||
this.status_ = this.constructor.STATUS_PENDING;
|
||||
this.donePromise = new Promise((resolve, reject) => {
|
||||
this.doneResolve = resolve;
|
||||
this.doneReject = reject;
|
||||
});
|
||||
}
|
||||
get status () {
|
||||
return this.status_;
|
||||
}
|
||||
set status (status) {
|
||||
this.status_ = status;
|
||||
if ( status === this.constructor.STATUS_DONE ) {
|
||||
this.doneResolve();
|
||||
}
|
||||
}
|
||||
resolve (value) {
|
||||
this.status_ = this.constructor.STATUS_DONE;
|
||||
this.doneResolve(value);
|
||||
}
|
||||
awaitDone () {
|
||||
return this.donePromise;
|
||||
}
|
||||
then (fn, ...a) {
|
||||
return this.donePromise.then(fn, ...a);
|
||||
}
|
||||
|
||||
reject (err) {
|
||||
this.status_ = this.constructor.STATUS_DONE;
|
||||
this.doneReject(err);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use then() instead
|
||||
*/
|
||||
onComplete(fn) {
|
||||
return this.then(fn);
|
||||
}
|
||||
}
|
||||
|
||||
class Lock {
|
||||
constructor() {
|
||||
this._locked = false;
|
||||
this._waiting = [];
|
||||
}
|
||||
|
||||
async acquire(callback) {
|
||||
await new Promise(resolve => {
|
||||
if ( ! this._locked ) {
|
||||
this._locked = true;
|
||||
resolve();
|
||||
} else {
|
||||
this._waiting.push({
|
||||
resolve,
|
||||
});
|
||||
}
|
||||
})
|
||||
if ( callback ) {
|
||||
let retval;
|
||||
try {
|
||||
retval = await callback();
|
||||
} finally {
|
||||
this.release();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
release() {
|
||||
if (this._waiting.length > 0) {
|
||||
const { resolve } = this._waiting.shift();
|
||||
resolve();
|
||||
} else {
|
||||
this._locked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @callback behindScheduleCallback
|
||||
* @param {number} drift - The number of milliseconds that the callback was
|
||||
* called behind schedule.
|
||||
* @returns {boolean} - If the callback returns true, the timer will be
|
||||
* cancelled.
|
||||
*/
|
||||
|
||||
/**
|
||||
* When passing an async callback to setInterval, it's possible for the
|
||||
* callback to be called again before the previous invocation has finished.
|
||||
*
|
||||
* This function wraps setInterval and ensures that the callback is not
|
||||
* called again until the previous invocation has finished.
|
||||
*
|
||||
* @param {Function} callback - The function to call when the timer elapses.
|
||||
* @param {number} delay - The minimum number of milliseconds between invocations.
|
||||
* @param {?Array<any>} args - Additional arguments to pass to setInterval.
|
||||
* @param {?Object} options - Additional options.
|
||||
* @param {behindScheduleCallback} options.onBehindSchedule - A callback to call when the callback is called behind schedule.
|
||||
*/
|
||||
const asyncSafeSetInterval = async (callback, delay, args, options) => {
|
||||
args = args ?? [];
|
||||
options = options ?? {};
|
||||
const { onBehindSchedule } = options;
|
||||
|
||||
const sleep = (ms) => new Promise(rslv => setTimeout(rslv, ms));
|
||||
|
||||
for ( ;; ) {
|
||||
await sleep(delay);
|
||||
|
||||
const ts_start = Date.now();
|
||||
await callback(...args);
|
||||
const ts_end = Date.now();
|
||||
|
||||
const runtime = ts_end - ts_start;
|
||||
const sleep_time = delay - runtime;
|
||||
|
||||
if ( sleep_time < 0 ) {
|
||||
if ( onBehindSchedule ) {
|
||||
const cancel = await onBehindSchedule(-sleep_time);
|
||||
if ( cancel ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
await sleep(sleep_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* raceCase is like Promise.race except it takes an object instead of
|
||||
* an array, and returns the key of the promise that resolves first
|
||||
* as well as the value that it resolved to.
|
||||
*
|
||||
* @param {Object.<string, Promise>} promise_map
|
||||
*
|
||||
* @returns {Promise.<[string, any]>}
|
||||
*/
|
||||
const raceCase = async (promise_map) => {
|
||||
return Promise.race(Object.entries(promise_map).map(
|
||||
([key, promise]) => promise.then(value => [key, value])));
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
TeePromise,
|
||||
Lock,
|
||||
asyncSafeSetInterval,
|
||||
raceCase,
|
||||
};
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -20,6 +20,7 @@ import { nodeResolve } from '@rollup/plugin-node-resolve'
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import copy from 'rollup-plugin-copy';
|
||||
import process from 'node:process';
|
||||
import path from 'node:path';
|
||||
|
||||
const configFile = process.env.CONFIG_FILE ?? 'config/dev.js';
|
||||
await import(`./${configFile}`);
|
||||
@@ -31,7 +32,9 @@ export default {
|
||||
format: "iife"
|
||||
},
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
nodeResolve({
|
||||
rootDir: path.join(process.cwd(), '..'),
|
||||
}),
|
||||
commonjs(),
|
||||
copy({
|
||||
targets: [
|
||||
|
||||
Reference in new issue
Block a user