diff --git a/package-lock.json b/package-lock.json
index eff2bf9f..73a7d72e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -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",
diff --git a/package.json b/package.json
index 2851e5f5..892c71c2 100644
--- a/package.json
+++ b/package.json
@@ -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/*"
diff --git a/packages/backend/packages/puter-js-common/index.js b/packages/backend/packages/puter-js-common/index.js
deleted file mode 100644
index b4e7b616..00000000
--- a/packages/backend/packages/puter-js-common/index.js
+++ /dev/null
@@ -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 .
- */
-const { AdvancedBase } = require('./src/AdvancedBase');
-
-module.exports = {
- AdvancedBase,
-};
diff --git a/packages/backend/packages/puter-js-common/package.json b/packages/backend/packages/puter-js-common/package.json
deleted file mode 100644
index f6de28c1..00000000
--- a/packages/backend/packages/puter-js-common/package.json
+++ /dev/null
@@ -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"
-}
diff --git a/packages/backend/packages/puter-js-common/src/AdvancedBase.js b/packages/backend/packages/puter-js-common/src/AdvancedBase.js
deleted file mode 100644
index 069e474a..00000000
--- a/packages/backend/packages/puter-js-common/src/AdvancedBase.js
+++ /dev/null
@@ -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 .
- */
-// 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,
-};
diff --git a/packages/backend/packages/puter-js-common/src/bases/BasicBase.js b/packages/backend/packages/puter-js-common/src/bases/BasicBase.js
deleted file mode 100644
index 78d121f9..00000000
--- a/packages/backend/packages/puter-js-common/src/bases/BasicBase.js
+++ /dev/null
@@ -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 .
- */
-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,
-};
\ No newline at end of file
diff --git a/packages/backend/packages/puter-js-common/src/bases/TraitBase.js b/packages/backend/packages/puter-js-common/src/bases/TraitBase.js
deleted file mode 100644
index 62d3cc1e..00000000
--- a/packages/backend/packages/puter-js-common/src/bases/TraitBase.js
+++ /dev/null
@@ -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 .
- */
-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,
-};
diff --git a/packages/backend/packages/puter-js-common/src/traits/NodeModuleDITrait.js b/packages/backend/packages/puter-js-common/src/traits/NodeModuleDITrait.js
deleted file mode 100644
index d7952704..00000000
--- a/packages/backend/packages/puter-js-common/src/traits/NodeModuleDITrait.js
+++ /dev/null
@@ -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 .
- */
-/**
- * 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);
- }
- },
-};
diff --git a/packages/backend/packages/puter-js-common/src/traits/PropertiesTrait.js b/packages/backend/packages/puter-js-common/src/traits/PropertiesTrait.js
deleted file mode 100644
index 9e2c4b72..00000000
--- a/packages/backend/packages/puter-js-common/src/traits/PropertiesTrait.js
+++ /dev/null
@@ -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 .
- */
-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];
- }
- }
-}
diff --git a/packages/backend/packages/puter-js-common/test/test.js b/packages/backend/packages/puter-js-common/test/test.js
deleted file mode 100644
index 34a36f4d..00000000
--- a/packages/backend/packages/puter-js-common/test/test.js
+++ /dev/null
@@ -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 .
- */
-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');
- });
-});
-
diff --git a/packages/phoenix/packages/contextlink/.gitignore b/packages/contextlink/.gitignore
similarity index 100%
rename from packages/phoenix/packages/contextlink/.gitignore
rename to packages/contextlink/.gitignore
diff --git a/packages/phoenix/packages/contextlink/context.js b/packages/contextlink/context.js
similarity index 100%
rename from packages/phoenix/packages/contextlink/context.js
rename to packages/contextlink/context.js
diff --git a/packages/phoenix/packages/contextlink/entry.js b/packages/contextlink/entry.js
similarity index 100%
rename from packages/phoenix/packages/contextlink/entry.js
rename to packages/contextlink/entry.js
diff --git a/packages/phoenix/packages/contextlink/package-lock.json b/packages/contextlink/package-lock.json
similarity index 100%
rename from packages/phoenix/packages/contextlink/package-lock.json
rename to packages/contextlink/package-lock.json
diff --git a/packages/phoenix/packages/contextlink/package.json b/packages/contextlink/package.json
similarity index 100%
rename from packages/phoenix/packages/contextlink/package.json
rename to packages/contextlink/package.json
diff --git a/packages/phoenix/packages/contextlink/test/testcontext.js b/packages/contextlink/test/testcontext.js
similarity index 100%
rename from packages/phoenix/packages/contextlink/test/testcontext.js
rename to packages/contextlink/test/testcontext.js
diff --git a/packages/git/rollup.config.js b/packages/git/rollup.config.js
index 9c0c6732..08eab6c3 100644
--- a/packages/git/rollup.config.js
+++ b/packages/git/rollup.config.js
@@ -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({
diff --git a/packages/phoenix/rollup.config.js b/packages/phoenix/rollup.config.js
index fd090bbb..69880de0 100644
--- a/packages/phoenix/rollup.config.js
+++ b/packages/phoenix/rollup.config.js
@@ -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: [
diff --git a/packages/phoenix/packages/pty/exports.js b/packages/pty/exports.js
similarity index 98%
rename from packages/phoenix/packages/pty/exports.js
rename to packages/pty/exports.js
index 3f45abf0..1e36b768 100644
--- a/packages/phoenix/packages/pty/exports.js
+++ b/packages/pty/exports.js
@@ -16,7 +16,8 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
-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 {
diff --git a/packages/phoenix/packages/pty/package.json b/packages/pty/package.json
similarity index 100%
rename from packages/phoenix/packages/pty/package.json
rename to packages/pty/package.json
diff --git a/packages/backend/packages/puter-js-common/README.md b/packages/puter-js-common/README.md
similarity index 100%
rename from packages/backend/packages/puter-js-common/README.md
rename to packages/puter-js-common/README.md
diff --git a/packages/puter-js-common/index.js b/packages/puter-js-common/index.js
index d71fb116..384cdc8f 100644
--- a/packages/puter-js-common/index.js
+++ b/packages/puter-js-common/index.js
@@ -2,4 +2,7 @@ const { AdvancedBase } = require('./src/AdvancedBase');
module.exports = {
AdvancedBase,
+ libs: {
+ promise: require('./src/libs/promise'),
+ },
};
diff --git a/packages/puter-js-common/src/libs/promise.js b/packages/puter-js-common/src/libs/promise.js
new file mode 100644
index 00000000..dc22ed85
--- /dev/null
+++ b/packages/puter-js-common/src/libs/promise.js
@@ -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 .
+ */
+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} 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.} 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,
+};
diff --git a/packages/phoenix/packages/strataparse/dsl/ParserBuilder.js b/packages/strataparse/dsl/ParserBuilder.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/dsl/ParserBuilder.js
rename to packages/strataparse/dsl/ParserBuilder.js
diff --git a/packages/phoenix/packages/strataparse/dsl/ParserRegistry.js b/packages/strataparse/dsl/ParserRegistry.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/dsl/ParserRegistry.js
rename to packages/strataparse/dsl/ParserRegistry.js
diff --git a/packages/phoenix/packages/strataparse/exports.js b/packages/strataparse/exports.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/exports.js
rename to packages/strataparse/exports.js
diff --git a/packages/phoenix/packages/strataparse/package.json b/packages/strataparse/package.json
similarity index 100%
rename from packages/phoenix/packages/strataparse/package.json
rename to packages/strataparse/package.json
diff --git a/packages/phoenix/packages/strataparse/parse.js b/packages/strataparse/parse.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/parse.js
rename to packages/strataparse/parse.js
diff --git a/packages/phoenix/packages/strataparse/parse_impls/StrUntilParserImpl.js b/packages/strataparse/parse_impls/StrUntilParserImpl.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/parse_impls/StrUntilParserImpl.js
rename to packages/strataparse/parse_impls/StrUntilParserImpl.js
diff --git a/packages/phoenix/packages/strataparse/parse_impls/combinators.js b/packages/strataparse/parse_impls/combinators.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/parse_impls/combinators.js
rename to packages/strataparse/parse_impls/combinators.js
diff --git a/packages/phoenix/packages/strataparse/parse_impls/literal.js b/packages/strataparse/parse_impls/literal.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/parse_impls/literal.js
rename to packages/strataparse/parse_impls/literal.js
diff --git a/packages/phoenix/packages/strataparse/parse_impls/whitespace.js b/packages/strataparse/parse_impls/whitespace.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/parse_impls/whitespace.js
rename to packages/strataparse/parse_impls/whitespace.js
diff --git a/packages/phoenix/packages/strataparse/strata.js b/packages/strataparse/strata.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/strata.js
rename to packages/strataparse/strata.js
diff --git a/packages/phoenix/packages/strataparse/strata_impls/ContextSwitchingPStratumImpl.js b/packages/strataparse/strata_impls/ContextSwitchingPStratumImpl.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/strata_impls/ContextSwitchingPStratumImpl.js
rename to packages/strataparse/strata_impls/ContextSwitchingPStratumImpl.js
diff --git a/packages/phoenix/packages/strataparse/strata_impls/FirstRecognizedPStratumImpl.js b/packages/strataparse/strata_impls/FirstRecognizedPStratumImpl.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/strata_impls/FirstRecognizedPStratumImpl.js
rename to packages/strataparse/strata_impls/FirstRecognizedPStratumImpl.js
diff --git a/packages/phoenix/packages/strataparse/strata_impls/MergeWhitespacePStratumImpl.js b/packages/strataparse/strata_impls/MergeWhitespacePStratumImpl.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/strata_impls/MergeWhitespacePStratumImpl.js
rename to packages/strataparse/strata_impls/MergeWhitespacePStratumImpl.js
diff --git a/packages/phoenix/packages/strataparse/strata_impls/terminals.js b/packages/strataparse/strata_impls/terminals.js
similarity index 100%
rename from packages/phoenix/packages/strataparse/strata_impls/terminals.js
rename to packages/strataparse/strata_impls/terminals.js
diff --git a/packages/terminal/rollup.config.js b/packages/terminal/rollup.config.js
index 1ea7ebcf..7c0920b6 100644
--- a/packages/terminal/rollup.config.js
+++ b/packages/terminal/rollup.config.js
@@ -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: [