@rvoh/psychic 0.24.4 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/spec/helpers/sleep.js +10 -0
- package/dist/cjs/src/bin/helpers/printRoutes.js +2 -2
- package/dist/cjs/src/bin/index.js +8 -8
- package/dist/cjs/src/cli/index.js +0 -7
- package/dist/cjs/src/devtools/PsychicDevtools.js +15 -0
- package/dist/cjs/src/devtools/helpers/launchDevServer.js +106 -0
- package/dist/cjs/src/helpers/autogeneratedFileDisclaimer.js +2 -2
- package/dist/cjs/src/index.js +4 -2
- package/dist/cjs/src/server/helpers/startPsychicServer.js +10 -10
- package/dist/cjs/src/server/index.js +3 -13
- package/dist/esm/spec/helpers/sleep.js +7 -0
- package/dist/esm/src/bin/helpers/printRoutes.js +1 -1
- package/dist/esm/src/bin/index.js +9 -9
- package/dist/esm/src/cli/index.js +0 -7
- package/dist/esm/src/devtools/PsychicDevtools.js +12 -0
- package/dist/esm/src/devtools/helpers/launchDevServer.js +101 -0
- package/dist/esm/src/helpers/autogeneratedFileDisclaimer.js +2 -2
- package/dist/esm/src/index.js +1 -0
- package/dist/esm/src/server/helpers/startPsychicServer.js +9 -9
- package/dist/esm/src/server/index.js +4 -14
- package/dist/types/spec/helpers/sleep.d.ts +1 -0
- package/dist/types/src/devtools/PsychicDevtools.d.ts +6 -0
- package/dist/types/src/devtools/helpers/launchDevServer.d.ts +8 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/psychic-application/index.d.ts +0 -2
- package/dist/types/src/server/helpers/startPsychicServer.d.ts +1 -3
- package/dist/types/src/server/index.d.ts +1 -6
- package/package.json +10 -10
- package/dist/cjs/src/psychic-application/logo.js +0 -77
- package/dist/cjs/src/server/front-end-client.js +0 -15
- package/dist/esm/src/psychic-application/logo.js +0 -73
- package/dist/esm/src/server/front-end-client.js +0 -12
- package/dist/types/src/psychic-application/logo.d.ts +0 -2
- package/dist/types/src/server/front-end-client.d.ts +0 -5
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = printRoutes;
|
|
4
|
-
const
|
|
4
|
+
const yoctocolors_1 = require("yoctocolors");
|
|
5
5
|
const index_js_1 = require("../../server/index.js");
|
|
6
6
|
async function printRoutes() {
|
|
7
7
|
const server = new index_js_1.default();
|
|
@@ -16,7 +16,7 @@ async function printRoutes() {
|
|
|
16
16
|
const partialExpression = `${beginning}${makeSpaces(beginning, desiredFirstGapSpaceCount)}${end}`;
|
|
17
17
|
const closingSpaces = makeSpaces(partialExpression, desiredLastGapSpaceCount);
|
|
18
18
|
const expression = `${partialExpression}${closingSpaces}`;
|
|
19
|
-
const colorizedExpression = i % 2 ?
|
|
19
|
+
const colorizedExpression = i % 2 ? yoctocolors_1.default.bgWhite(yoctocolors_1.default.black(expression)) : expression;
|
|
20
20
|
console.log(colorizedExpression);
|
|
21
21
|
});
|
|
22
22
|
}
|
|
@@ -50,30 +50,30 @@ class PsychicBin {
|
|
|
50
50
|
}
|
|
51
51
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
52
|
static async syncTypes(customTypes = undefined) {
|
|
53
|
-
|
|
53
|
+
const spinner = dream_1.DreamCLI.logger.log(`syncing types/psychic.ts...`, { spinner: true });
|
|
54
54
|
await TypesBuilder_js_1.default.sync(customTypes);
|
|
55
|
-
|
|
55
|
+
spinner.stop();
|
|
56
56
|
}
|
|
57
57
|
static async syncOpenapiJson() {
|
|
58
|
-
|
|
58
|
+
const spinner = dream_1.DreamCLI.logger.log(`syncing openapi...`, { spinner: true });
|
|
59
59
|
await app_js_1.default.sync();
|
|
60
|
-
|
|
60
|
+
spinner.stop();
|
|
61
61
|
}
|
|
62
62
|
static async syncRoutes() {
|
|
63
|
-
|
|
63
|
+
const spinner = dream_1.DreamCLI.logger.log(`syncing routes...`, { spinner: true });
|
|
64
64
|
const server = new index_js_2.default();
|
|
65
65
|
await server.boot();
|
|
66
66
|
const routes = await server.routes();
|
|
67
67
|
await (0, generateRouteTypes_js_1.default)(routes);
|
|
68
|
-
|
|
68
|
+
spinner.stop();
|
|
69
69
|
}
|
|
70
70
|
static async syncClientEnums() {
|
|
71
|
-
|
|
71
|
+
const spinner = dream_1.DreamCLI.logger.log(`syncing client enums...`, { spinner: true });
|
|
72
72
|
const psychicApp = index_js_1.default.getOrFail();
|
|
73
73
|
const apiPath = path.join(psychicApp.clientRoot, psychicApp.client.apiPath);
|
|
74
74
|
const enumsStr = await (0, enumsFileStr_js_1.default)();
|
|
75
75
|
await fs.writeFile(`${apiPath}/enums.ts`, enumsStr);
|
|
76
|
-
|
|
76
|
+
spinner.stop();
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
exports.default = PsychicBin;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const dream_1 = require("@rvoh/dream");
|
|
4
4
|
const index_js_1 = require("../bin/index.js");
|
|
5
|
-
const EnvInternal_js_1 = require("../helpers/EnvInternal.js");
|
|
6
5
|
class PsychicCLI {
|
|
7
6
|
static provide(program, { initializePsychicApplication, seedDb, }) {
|
|
8
7
|
dream_1.DreamCLI.generateDreamCli(program, {
|
|
@@ -20,7 +19,6 @@ class PsychicCLI {
|
|
|
20
19
|
.argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
21
20
|
.argument('[columnsWithTypes...]', 'properties of the model property1:text/string/enum/etc. property2:text/string/enum/etc. ... propertyN:text/string/enum/etc.')
|
|
22
21
|
.action(async (route, modelName, columnsWithTypes) => {
|
|
23
|
-
EnvInternal_js_1.default.provideDefaultNodeEnv('test');
|
|
24
22
|
await initializePsychicApplication();
|
|
25
23
|
await index_js_1.default.generateResource(route, modelName, columnsWithTypes);
|
|
26
24
|
process.exit();
|
|
@@ -32,7 +30,6 @@ class PsychicCLI {
|
|
|
32
30
|
.argument('<controllerName>', 'the name of the controller to create, including namespaces, e.g. Posts or Api/V1/Posts')
|
|
33
31
|
.argument('[actions...]', 'the names of controller actions to create')
|
|
34
32
|
.action(async (controllerName, actions) => {
|
|
35
|
-
EnvInternal_js_1.default.provideDefaultNodeEnv('test');
|
|
36
33
|
await initializePsychicApplication();
|
|
37
34
|
await index_js_1.default.generateController(controllerName, actions);
|
|
38
35
|
process.exit();
|
|
@@ -41,7 +38,6 @@ class PsychicCLI {
|
|
|
41
38
|
.command('routes')
|
|
42
39
|
.description('examines your current models, building a type-map of the associations so that the ORM can understand your relational setup. This is commited to your repo, and synced to the dream repo for consumption within the underlying library.')
|
|
43
40
|
.action(async () => {
|
|
44
|
-
EnvInternal_js_1.default.provideDefaultNodeEnv('test');
|
|
45
41
|
await initializePsychicApplication();
|
|
46
42
|
await index_js_1.default.routes();
|
|
47
43
|
process.exit();
|
|
@@ -50,7 +46,6 @@ class PsychicCLI {
|
|
|
50
46
|
.command('sync')
|
|
51
47
|
.description('sync introspects your database, updating your schema to reflect, and then syncs the new schema with the installed dream node module, allowing it provide your schema to the underlying kysely integration')
|
|
52
48
|
.action(async () => {
|
|
53
|
-
EnvInternal_js_1.default.provideDefaultNodeEnv('test');
|
|
54
49
|
await initializePsychicApplication();
|
|
55
50
|
await index_js_1.default.sync();
|
|
56
51
|
process.exit();
|
|
@@ -59,14 +54,12 @@ class PsychicCLI {
|
|
|
59
54
|
.command('sync:routes')
|
|
60
55
|
.description('reads the routes generated by your app and generates a cache file, which is then used to give autocomplete support to the route helper, amoongst other things.')
|
|
61
56
|
.action(async () => {
|
|
62
|
-
EnvInternal_js_1.default.provideDefaultNodeEnv('test');
|
|
63
57
|
await index_js_1.default.syncRoutes();
|
|
64
58
|
});
|
|
65
59
|
program
|
|
66
60
|
.command('sync:openapi')
|
|
67
61
|
.description('syncs openapi.json file to current state of all psychic controllers within the app')
|
|
68
62
|
.action(async () => {
|
|
69
|
-
EnvInternal_js_1.default.provideDefaultNodeEnv('test');
|
|
70
63
|
await initializePsychicApplication();
|
|
71
64
|
await index_js_1.default.syncOpenapiJson();
|
|
72
65
|
process.exit();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const launchDevServer_js_1 = require("./helpers/launchDevServer.js");
|
|
4
|
+
class PsychicDevtools {
|
|
5
|
+
static async launchDevServer(key, opts) {
|
|
6
|
+
return await (0, launchDevServer_js_1.launchDevServer)(key, opts);
|
|
7
|
+
}
|
|
8
|
+
static stopDevServer(key) {
|
|
9
|
+
return (0, launchDevServer_js_1.stopDevServer)(key);
|
|
10
|
+
}
|
|
11
|
+
static stopDevServers() {
|
|
12
|
+
return (0, launchDevServer_js_1.stopDevServers)();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.default = PsychicDevtools;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.launchDevServer = launchDevServer;
|
|
4
|
+
exports.stopDevServer = stopDevServer;
|
|
5
|
+
exports.stopDevServers = stopDevServers;
|
|
6
|
+
const child_process_1 = require("child_process");
|
|
7
|
+
const net_1 = require("net");
|
|
8
|
+
const sleep_js_1 = require("../../../spec/helpers/sleep.js");
|
|
9
|
+
const devServerProcesses = {};
|
|
10
|
+
async function launchDevServer(key, { port = 3000, cmd = 'yarn client', timeout = 5000 } = {}) {
|
|
11
|
+
if (devServerProcesses[key])
|
|
12
|
+
return;
|
|
13
|
+
if (process.env.DEBUG === '1')
|
|
14
|
+
console.log('Starting server...');
|
|
15
|
+
const [_cmd, ...args] = cmd.split(' ');
|
|
16
|
+
const proc = (0, child_process_1.spawn)(_cmd, args, {
|
|
17
|
+
detached: true,
|
|
18
|
+
env: {
|
|
19
|
+
...process.env,
|
|
20
|
+
BROWSER: 'none',
|
|
21
|
+
VITE_PSYCHIC_ENV: 'test',
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
devServerProcesses[key] = proc;
|
|
25
|
+
await waitForPort(key, port, timeout);
|
|
26
|
+
proc.on('error', err => {
|
|
27
|
+
throw err;
|
|
28
|
+
});
|
|
29
|
+
proc.stdout.on('data', data => {
|
|
30
|
+
if (process.env.DEBUG === '1')
|
|
31
|
+
console.log(`Server output: ${data}`);
|
|
32
|
+
});
|
|
33
|
+
proc.stderr.on('data', data => {
|
|
34
|
+
if (process.env.DEBUG === '1')
|
|
35
|
+
console.error(`Server error: ${data}`);
|
|
36
|
+
});
|
|
37
|
+
proc.on('error', err => {
|
|
38
|
+
console.error(`Server process error: ${err}`);
|
|
39
|
+
});
|
|
40
|
+
proc.on('close', code => {
|
|
41
|
+
if (process.env.DEBUG === '1')
|
|
42
|
+
console.log(`Server process exited with code ${code}`);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function stopDevServer(key) {
|
|
46
|
+
const proc = devServerProcesses[key];
|
|
47
|
+
if (!proc) {
|
|
48
|
+
throw new Error(`Cannot find a dev server by the key: ${key}`);
|
|
49
|
+
}
|
|
50
|
+
if (proc?.pid) {
|
|
51
|
+
if (process.env.DEBUG === '1')
|
|
52
|
+
console.log('Stopping server...');
|
|
53
|
+
try {
|
|
54
|
+
// proc.kill('SIGINT')
|
|
55
|
+
process.kill(-proc.pid, 'SIGKILL');
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// noop
|
|
59
|
+
}
|
|
60
|
+
delete devServerProcesses[key];
|
|
61
|
+
if (process.env.DEBUG === '1')
|
|
62
|
+
console.log('server stopped');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function stopDevServers() {
|
|
66
|
+
Object.keys(devServerProcesses).forEach(key => {
|
|
67
|
+
stopDevServer(key);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async function isPortAvailable(port) {
|
|
71
|
+
return new Promise(resolve => {
|
|
72
|
+
const server = (0, net_1.createServer)()
|
|
73
|
+
.once('error', err => {
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
|
|
75
|
+
if (err.code === 'EADDRINUSE') {
|
|
76
|
+
resolve(false);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
resolve(true);
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
.once('listening', () => {
|
|
83
|
+
server.close();
|
|
84
|
+
resolve(true);
|
|
85
|
+
})
|
|
86
|
+
.listen(port, '127.0.0.1');
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
async function waitForPort(key, port, timeout = 5000) {
|
|
90
|
+
if (await isPortAvailable(port)) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
const startTime = Date.now();
|
|
94
|
+
async function recursiveWaitForPort() {
|
|
95
|
+
if (await isPortAvailable(port)) {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
if (Date.now() > startTime + timeout) {
|
|
99
|
+
stopDevServer(key);
|
|
100
|
+
throw new Error('waited too long for port: ' + port);
|
|
101
|
+
}
|
|
102
|
+
await (0, sleep_js_1.default)(50);
|
|
103
|
+
return await recursiveWaitForPort();
|
|
104
|
+
}
|
|
105
|
+
return await recursiveWaitForPort();
|
|
106
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = autogeneratedFileDisclaimer;
|
|
4
|
-
const
|
|
4
|
+
const dream_1 = require("@rvoh/dream");
|
|
5
5
|
function autogeneratedFileDisclaimer(startComment = '\n/*', endComment = '\n*/') {
|
|
6
6
|
return `\
|
|
7
7
|
${startComment}
|
|
@@ -16,7 +16,7 @@ ${startComment}
|
|
|
16
16
|
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
${
|
|
19
|
+
${dream_1.DreamGlam.whaaaaaaaaaaokBasic()}
|
|
20
20
|
|
|
21
21
|
This file was automatically generated by my cat, Aster.
|
|
22
22
|
He does not want you mucking about with his files,
|
package/dist/cjs/src/index.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.PsychicSession = void 0;
|
|
3
|
+
exports.Params = exports.PsychicServer = exports.getPsychicHttpInstance = exports.PsychicRouter = exports.PsychicApplication = exports.PsychicImporter = exports.MissingControllerActionPairingInRoutes = exports.pathifyNestedObject = exports.cookieMaxAgeFromCookieOpts = exports.generateResource = exports.generateController = exports.HttpStatusUnsupportedMediaType = exports.HttpStatusUnprocessableContent = exports.HttpStatusUnavailableForLegalReasons = exports.HttpStatusUnauthorized = exports.HttpStatusTooManyRequests = exports.HttpStatusServiceUnavailable = exports.HttpStatusRequestHeaderFieldsTooLarge = exports.HttpStatusProxyAuthenticationRequired = exports.HttpStatusPreconditionRequired = exports.HttpStatusPreconditionFailed = exports.HttpStatusPaymentRequired = exports.HttpStatusNotImplemented = exports.HttpStatusNotFound = exports.HttpStatusNotExtended = exports.HttpStatusNotAcceptable = exports.HttpStatusMisdirectedRequest = exports.HttpStatusMethodNotAllowed = exports.HttpStatusLocked = exports.HttpStatusInternalServerError = exports.HttpStatusInsufficientStorage = exports.HttpStatusImATeapot = exports.HttpStatusGone = exports.HttpStatusGatewayTimeout = exports.HttpStatusForbidden = exports.HttpStatusFailedDependency = exports.HttpStatusExpectationFailed = exports.HttpStatusContentTooLarge = exports.HttpStatusConflict = exports.HttpStatusBadRequest = exports.HttpStatusBadGateway = exports.I18nProvider = exports.envLoader = exports.PsychicController = exports.OpenAPI = exports.BeforeAction = exports.PsychicDevtools = exports.PsychicCLI = exports.PsychicBin = exports.pluralize = void 0;
|
|
4
|
+
exports.PsychicSession = exports.ParamValidationError = void 0;
|
|
5
5
|
const pluralize_esm_1 = require("pluralize-esm");
|
|
6
6
|
exports.pluralize = pluralize_esm_1.default;
|
|
7
7
|
var index_js_1 = require("./bin/index.js");
|
|
8
8
|
Object.defineProperty(exports, "PsychicBin", { enumerable: true, get: function () { return index_js_1.default; } });
|
|
9
9
|
var index_js_2 = require("./cli/index.js");
|
|
10
10
|
Object.defineProperty(exports, "PsychicCLI", { enumerable: true, get: function () { return index_js_2.default; } });
|
|
11
|
+
var PsychicDevtools_js_1 = require("./devtools/PsychicDevtools.js");
|
|
12
|
+
Object.defineProperty(exports, "PsychicDevtools", { enumerable: true, get: function () { return PsychicDevtools_js_1.default; } });
|
|
11
13
|
var decorators_js_1 = require("./controller/decorators.js");
|
|
12
14
|
Object.defineProperty(exports, "BeforeAction", { enumerable: true, get: function () { return decorators_js_1.BeforeAction; } });
|
|
13
15
|
Object.defineProperty(exports, "OpenAPI", { enumerable: true, get: function () { return decorators_js_1.OpenAPI; } });
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = startPsychicServer;
|
|
4
4
|
exports.createPsychicHttpInstance = createPsychicHttpInstance;
|
|
5
|
+
const dream_1 = require("@rvoh/dream");
|
|
5
6
|
const fs = require("fs");
|
|
6
7
|
const http = require("http");
|
|
7
8
|
const https = require("https");
|
|
8
9
|
const EnvInternal_js_1 = require("../../helpers/EnvInternal.js");
|
|
9
|
-
const index_js_1 = require("../../
|
|
10
|
-
|
|
11
|
-
async function startPsychicServer({ app, port, withFrontEndClient, frontEndPort, sslCredentials, }) {
|
|
10
|
+
const index_js_1 = require("../../server/index.js");
|
|
11
|
+
async function startPsychicServer({ app, port, sslCredentials, }) {
|
|
12
12
|
return await new Promise(accept => {
|
|
13
13
|
const httpOrHttps = createPsychicHttpInstance(app, sslCredentials);
|
|
14
14
|
const server = httpOrHttps.listen(port, () => {
|
|
15
|
-
welcomeMessage({ port
|
|
15
|
+
welcomeMessage({ port });
|
|
16
16
|
accept(server);
|
|
17
17
|
});
|
|
18
18
|
});
|
|
@@ -28,12 +28,12 @@ function createPsychicHttpInstance(app, sslCredentials) {
|
|
|
28
28
|
return http.createServer(app);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
function welcomeMessage({ port
|
|
31
|
+
function welcomeMessage({ port }) {
|
|
32
32
|
if (!EnvInternal_js_1.default.isTest) {
|
|
33
|
-
const psychicApp =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
// const psychicApp = PsychicApplication.getOrFail()
|
|
34
|
+
const spinner = dream_1.DreamCLI.logger.log('starting psychic server...', { spinner: true });
|
|
35
|
+
dream_1.DreamCLI.logger.log(index_js_1.default.asciiLogo(), { permanent: true, logPrefix: '' });
|
|
36
|
+
spinner.stop();
|
|
37
|
+
dream_1.DreamCLI.logger.log(`psychic dev server started at port ${port}`);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -9,9 +9,7 @@ const path = require("path");
|
|
|
9
9
|
const EnvInternal_js_1 = require("../helpers/EnvInternal.js");
|
|
10
10
|
const isOpenapiError_js_1 = require("../helpers/isOpenapiError.js");
|
|
11
11
|
const index_js_1 = require("../psychic-application/index.js");
|
|
12
|
-
const logo_js_1 = require("../psychic-application/logo.js");
|
|
13
12
|
const index_js_2 = require("../router/index.js");
|
|
14
|
-
const front_end_client_js_1 = require("./front-end-client.js");
|
|
15
13
|
const startPsychicServer_js_1 = require("./helpers/startPsychicServer.js");
|
|
16
14
|
class PsychicServer {
|
|
17
15
|
static async startPsychicServer(opts) {
|
|
@@ -21,10 +19,9 @@ class PsychicServer {
|
|
|
21
19
|
return (0, startPsychicServer_js_1.createPsychicHttpInstance)(app, sslCredentials);
|
|
22
20
|
}
|
|
23
21
|
static asciiLogo() {
|
|
24
|
-
return
|
|
22
|
+
return dream_1.DreamGlam.fluffstopherwalkin();
|
|
25
23
|
}
|
|
26
24
|
expressApp;
|
|
27
|
-
frontEndClient;
|
|
28
25
|
httpServer;
|
|
29
26
|
booted = false;
|
|
30
27
|
constructor() {
|
|
@@ -75,23 +72,17 @@ class PsychicServer {
|
|
|
75
72
|
return true;
|
|
76
73
|
}
|
|
77
74
|
// TODO: use config helper for fetching default port
|
|
78
|
-
async start(port
|
|
75
|
+
async start(port) {
|
|
79
76
|
await this.boot();
|
|
80
|
-
if (withFrontEndClient) {
|
|
81
|
-
this.frontEndClient = new front_end_client_js_1.default();
|
|
82
|
-
this.frontEndClient.start(frontEndPort);
|
|
83
|
-
}
|
|
84
77
|
const psychicApp = index_js_1.default.getOrFail();
|
|
85
78
|
const startOverride = psychicApp['overrides']['server:start'];
|
|
86
79
|
if (startOverride) {
|
|
87
|
-
this.httpServer = await startOverride(this, { port
|
|
80
|
+
this.httpServer = await startOverride(this, { port });
|
|
88
81
|
}
|
|
89
82
|
else {
|
|
90
83
|
const httpServer = await (0, startPsychicServer_js_1.default)({
|
|
91
84
|
app: this.expressApp,
|
|
92
85
|
port: port || psychicApp.port,
|
|
93
|
-
withFrontEndClient,
|
|
94
|
-
frontEndPort,
|
|
95
86
|
sslCredentials: this.config.sslCredentials,
|
|
96
87
|
});
|
|
97
88
|
this.httpServer = httpServer;
|
|
@@ -123,7 +114,6 @@ class PsychicServer {
|
|
|
123
114
|
for (const hook of psychicApp.specialHooks.serverShutdown) {
|
|
124
115
|
await hook(this);
|
|
125
116
|
}
|
|
126
|
-
this.frontEndClient?.stop();
|
|
127
117
|
this.httpServer?.close();
|
|
128
118
|
if (!bypassClosingDbConnections) {
|
|
129
119
|
await (0, dream_1.closeAllDbConnections)();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DreamBin } from '@rvoh/dream';
|
|
1
|
+
import { DreamBin, DreamCLI } from '@rvoh/dream';
|
|
2
2
|
import * as fs from 'fs/promises';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import TypesBuilder from '../cli/helpers/TypesBuilder.js';
|
|
@@ -48,29 +48,29 @@ export default class PsychicBin {
|
|
|
48
48
|
}
|
|
49
49
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
50
|
static async syncTypes(customTypes = undefined) {
|
|
51
|
-
|
|
51
|
+
const spinner = DreamCLI.logger.log(`syncing types/psychic.ts...`, { spinner: true });
|
|
52
52
|
await TypesBuilder.sync(customTypes);
|
|
53
|
-
|
|
53
|
+
spinner.stop();
|
|
54
54
|
}
|
|
55
55
|
static async syncOpenapiJson() {
|
|
56
|
-
|
|
56
|
+
const spinner = DreamCLI.logger.log(`syncing openapi...`, { spinner: true });
|
|
57
57
|
await OpenapiAppRenderer.sync();
|
|
58
|
-
|
|
58
|
+
spinner.stop();
|
|
59
59
|
}
|
|
60
60
|
static async syncRoutes() {
|
|
61
|
-
|
|
61
|
+
const spinner = DreamCLI.logger.log(`syncing routes...`, { spinner: true });
|
|
62
62
|
const server = new PsychicServer();
|
|
63
63
|
await server.boot();
|
|
64
64
|
const routes = await server.routes();
|
|
65
65
|
await generateRouteTypes(routes);
|
|
66
|
-
|
|
66
|
+
spinner.stop();
|
|
67
67
|
}
|
|
68
68
|
static async syncClientEnums() {
|
|
69
|
-
|
|
69
|
+
const spinner = DreamCLI.logger.log(`syncing client enums...`, { spinner: true });
|
|
70
70
|
const psychicApp = PsychicApplication.getOrFail();
|
|
71
71
|
const apiPath = path.join(psychicApp.clientRoot, psychicApp.client.apiPath);
|
|
72
72
|
const enumsStr = await enumsFileStr();
|
|
73
73
|
await fs.writeFile(`${apiPath}/enums.ts`, enumsStr);
|
|
74
|
-
|
|
74
|
+
spinner.stop();
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { DreamCLI } from '@rvoh/dream';
|
|
2
2
|
import PsychicBin from '../bin/index.js';
|
|
3
|
-
import EnvInternal from '../helpers/EnvInternal.js';
|
|
4
3
|
export default class PsychicCLI {
|
|
5
4
|
static provide(program, { initializePsychicApplication, seedDb, }) {
|
|
6
5
|
DreamCLI.generateDreamCli(program, {
|
|
@@ -18,7 +17,6 @@ export default class PsychicCLI {
|
|
|
18
17
|
.argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
19
18
|
.argument('[columnsWithTypes...]', 'properties of the model property1:text/string/enum/etc. property2:text/string/enum/etc. ... propertyN:text/string/enum/etc.')
|
|
20
19
|
.action(async (route, modelName, columnsWithTypes) => {
|
|
21
|
-
EnvInternal.provideDefaultNodeEnv('test');
|
|
22
20
|
await initializePsychicApplication();
|
|
23
21
|
await PsychicBin.generateResource(route, modelName, columnsWithTypes);
|
|
24
22
|
process.exit();
|
|
@@ -30,7 +28,6 @@ export default class PsychicCLI {
|
|
|
30
28
|
.argument('<controllerName>', 'the name of the controller to create, including namespaces, e.g. Posts or Api/V1/Posts')
|
|
31
29
|
.argument('[actions...]', 'the names of controller actions to create')
|
|
32
30
|
.action(async (controllerName, actions) => {
|
|
33
|
-
EnvInternal.provideDefaultNodeEnv('test');
|
|
34
31
|
await initializePsychicApplication();
|
|
35
32
|
await PsychicBin.generateController(controllerName, actions);
|
|
36
33
|
process.exit();
|
|
@@ -39,7 +36,6 @@ export default class PsychicCLI {
|
|
|
39
36
|
.command('routes')
|
|
40
37
|
.description('examines your current models, building a type-map of the associations so that the ORM can understand your relational setup. This is commited to your repo, and synced to the dream repo for consumption within the underlying library.')
|
|
41
38
|
.action(async () => {
|
|
42
|
-
EnvInternal.provideDefaultNodeEnv('test');
|
|
43
39
|
await initializePsychicApplication();
|
|
44
40
|
await PsychicBin.routes();
|
|
45
41
|
process.exit();
|
|
@@ -48,7 +44,6 @@ export default class PsychicCLI {
|
|
|
48
44
|
.command('sync')
|
|
49
45
|
.description('sync introspects your database, updating your schema to reflect, and then syncs the new schema with the installed dream node module, allowing it provide your schema to the underlying kysely integration')
|
|
50
46
|
.action(async () => {
|
|
51
|
-
EnvInternal.provideDefaultNodeEnv('test');
|
|
52
47
|
await initializePsychicApplication();
|
|
53
48
|
await PsychicBin.sync();
|
|
54
49
|
process.exit();
|
|
@@ -57,14 +52,12 @@ export default class PsychicCLI {
|
|
|
57
52
|
.command('sync:routes')
|
|
58
53
|
.description('reads the routes generated by your app and generates a cache file, which is then used to give autocomplete support to the route helper, amoongst other things.')
|
|
59
54
|
.action(async () => {
|
|
60
|
-
EnvInternal.provideDefaultNodeEnv('test');
|
|
61
55
|
await PsychicBin.syncRoutes();
|
|
62
56
|
});
|
|
63
57
|
program
|
|
64
58
|
.command('sync:openapi')
|
|
65
59
|
.description('syncs openapi.json file to current state of all psychic controllers within the app')
|
|
66
60
|
.action(async () => {
|
|
67
|
-
EnvInternal.provideDefaultNodeEnv('test');
|
|
68
61
|
await initializePsychicApplication();
|
|
69
62
|
await PsychicBin.syncOpenapiJson();
|
|
70
63
|
process.exit();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { launchDevServer, stopDevServer, stopDevServers, } from './helpers/launchDevServer.js';
|
|
2
|
+
export default class PsychicDevtools {
|
|
3
|
+
static async launchDevServer(key, opts) {
|
|
4
|
+
return await launchDevServer(key, opts);
|
|
5
|
+
}
|
|
6
|
+
static stopDevServer(key) {
|
|
7
|
+
return stopDevServer(key);
|
|
8
|
+
}
|
|
9
|
+
static stopDevServers() {
|
|
10
|
+
return stopDevServers();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { createServer } from 'net';
|
|
3
|
+
import sleep from '../../../spec/helpers/sleep.js';
|
|
4
|
+
const devServerProcesses = {};
|
|
5
|
+
export async function launchDevServer(key, { port = 3000, cmd = 'yarn client', timeout = 5000 } = {}) {
|
|
6
|
+
if (devServerProcesses[key])
|
|
7
|
+
return;
|
|
8
|
+
if (process.env.DEBUG === '1')
|
|
9
|
+
console.log('Starting server...');
|
|
10
|
+
const [_cmd, ...args] = cmd.split(' ');
|
|
11
|
+
const proc = spawn(_cmd, args, {
|
|
12
|
+
detached: true,
|
|
13
|
+
env: {
|
|
14
|
+
...process.env,
|
|
15
|
+
BROWSER: 'none',
|
|
16
|
+
VITE_PSYCHIC_ENV: 'test',
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
devServerProcesses[key] = proc;
|
|
20
|
+
await waitForPort(key, port, timeout);
|
|
21
|
+
proc.on('error', err => {
|
|
22
|
+
throw err;
|
|
23
|
+
});
|
|
24
|
+
proc.stdout.on('data', data => {
|
|
25
|
+
if (process.env.DEBUG === '1')
|
|
26
|
+
console.log(`Server output: ${data}`);
|
|
27
|
+
});
|
|
28
|
+
proc.stderr.on('data', data => {
|
|
29
|
+
if (process.env.DEBUG === '1')
|
|
30
|
+
console.error(`Server error: ${data}`);
|
|
31
|
+
});
|
|
32
|
+
proc.on('error', err => {
|
|
33
|
+
console.error(`Server process error: ${err}`);
|
|
34
|
+
});
|
|
35
|
+
proc.on('close', code => {
|
|
36
|
+
if (process.env.DEBUG === '1')
|
|
37
|
+
console.log(`Server process exited with code ${code}`);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export function stopDevServer(key) {
|
|
41
|
+
const proc = devServerProcesses[key];
|
|
42
|
+
if (!proc) {
|
|
43
|
+
throw new Error(`Cannot find a dev server by the key: ${key}`);
|
|
44
|
+
}
|
|
45
|
+
if (proc?.pid) {
|
|
46
|
+
if (process.env.DEBUG === '1')
|
|
47
|
+
console.log('Stopping server...');
|
|
48
|
+
try {
|
|
49
|
+
// proc.kill('SIGINT')
|
|
50
|
+
process.kill(-proc.pid, 'SIGKILL');
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// noop
|
|
54
|
+
}
|
|
55
|
+
delete devServerProcesses[key];
|
|
56
|
+
if (process.env.DEBUG === '1')
|
|
57
|
+
console.log('server stopped');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function stopDevServers() {
|
|
61
|
+
Object.keys(devServerProcesses).forEach(key => {
|
|
62
|
+
stopDevServer(key);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
async function isPortAvailable(port) {
|
|
66
|
+
return new Promise(resolve => {
|
|
67
|
+
const server = createServer()
|
|
68
|
+
.once('error', err => {
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
|
|
70
|
+
if (err.code === 'EADDRINUSE') {
|
|
71
|
+
resolve(false);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
resolve(true);
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
.once('listening', () => {
|
|
78
|
+
server.close();
|
|
79
|
+
resolve(true);
|
|
80
|
+
})
|
|
81
|
+
.listen(port, '127.0.0.1');
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
async function waitForPort(key, port, timeout = 5000) {
|
|
85
|
+
if (await isPortAvailable(port)) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
const startTime = Date.now();
|
|
89
|
+
async function recursiveWaitForPort() {
|
|
90
|
+
if (await isPortAvailable(port)) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
if (Date.now() > startTime + timeout) {
|
|
94
|
+
stopDevServer(key);
|
|
95
|
+
throw new Error('waited too long for port: ' + port);
|
|
96
|
+
}
|
|
97
|
+
await sleep(50);
|
|
98
|
+
return await recursiveWaitForPort();
|
|
99
|
+
}
|
|
100
|
+
return await recursiveWaitForPort();
|
|
101
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DreamGlam } from '@rvoh/dream';
|
|
2
2
|
export default function autogeneratedFileDisclaimer(startComment = '\n/*', endComment = '\n*/') {
|
|
3
3
|
return `\
|
|
4
4
|
${startComment}
|
|
@@ -13,7 +13,7 @@ ${startComment}
|
|
|
13
13
|
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
${
|
|
16
|
+
${DreamGlam.whaaaaaaaaaaokBasic()}
|
|
17
17
|
|
|
18
18
|
This file was automatically generated by my cat, Aster.
|
|
19
19
|
He does not want you mucking about with his files,
|
package/dist/esm/src/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import _pluralize from 'pluralize-esm';
|
|
|
2
2
|
export const pluralize = _pluralize;
|
|
3
3
|
export { default as PsychicBin } from './bin/index.js';
|
|
4
4
|
export { default as PsychicCLI } from './cli/index.js';
|
|
5
|
+
export { default as PsychicDevtools } from './devtools/PsychicDevtools.js';
|
|
5
6
|
export { BeforeAction, OpenAPI } from './controller/decorators.js';
|
|
6
7
|
export { default as PsychicController, } from './controller/index.js';
|
|
7
8
|
export { default as envLoader } from './env/Loader.js';
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import { DreamCLI } from '@rvoh/dream';
|
|
1
2
|
import * as fs from 'fs';
|
|
2
3
|
import * as http from 'http';
|
|
3
4
|
import * as https from 'https';
|
|
4
5
|
import EnvInternal from '../../helpers/EnvInternal.js';
|
|
5
|
-
import PsychicApplication from '../../psychic-application/index.js';
|
|
6
6
|
import PsychicServer from '../../server/index.js';
|
|
7
|
-
export default async function startPsychicServer({ app, port,
|
|
7
|
+
export default async function startPsychicServer({ app, port, sslCredentials, }) {
|
|
8
8
|
return await new Promise(accept => {
|
|
9
9
|
const httpOrHttps = createPsychicHttpInstance(app, sslCredentials);
|
|
10
10
|
const server = httpOrHttps.listen(port, () => {
|
|
11
|
-
welcomeMessage({ port
|
|
11
|
+
welcomeMessage({ port });
|
|
12
12
|
accept(server);
|
|
13
13
|
});
|
|
14
14
|
});
|
|
@@ -24,12 +24,12 @@ export function createPsychicHttpInstance(app, sslCredentials) {
|
|
|
24
24
|
return http.createServer(app);
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
function welcomeMessage({ port
|
|
27
|
+
function welcomeMessage({ port }) {
|
|
28
28
|
if (!EnvInternal.isTest) {
|
|
29
|
-
const psychicApp = PsychicApplication.getOrFail()
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
// const psychicApp = PsychicApplication.getOrFail()
|
|
30
|
+
const spinner = DreamCLI.logger.log('starting psychic server...', { spinner: true });
|
|
31
|
+
DreamCLI.logger.log(PsychicServer.asciiLogo(), { permanent: true, logPrefix: '' });
|
|
32
|
+
spinner.stop();
|
|
33
|
+
DreamCLI.logger.log(`psychic dev server started at port ${port}`);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { closeAllDbConnections } from '@rvoh/dream';
|
|
1
|
+
import { closeAllDbConnections, DreamGlam } from '@rvoh/dream';
|
|
2
2
|
import * as cookieParser from 'cookie-parser';
|
|
3
3
|
import * as cors from 'cors';
|
|
4
4
|
import * as express from 'express';
|
|
@@ -7,9 +7,7 @@ import * as path from 'path';
|
|
|
7
7
|
import EnvInternal from '../helpers/EnvInternal.js';
|
|
8
8
|
import isOpenapiError from '../helpers/isOpenapiError.js';
|
|
9
9
|
import PsychicApplication from '../psychic-application/index.js';
|
|
10
|
-
import logo from '../psychic-application/logo.js';
|
|
11
10
|
import PsychicRouter from '../router/index.js';
|
|
12
|
-
import FrontEndClientServer from './front-end-client.js';
|
|
13
11
|
import startPsychicServer, { createPsychicHttpInstance, } from './helpers/startPsychicServer.js';
|
|
14
12
|
export default class PsychicServer {
|
|
15
13
|
static async startPsychicServer(opts) {
|
|
@@ -19,10 +17,9 @@ export default class PsychicServer {
|
|
|
19
17
|
return createPsychicHttpInstance(app, sslCredentials);
|
|
20
18
|
}
|
|
21
19
|
static asciiLogo() {
|
|
22
|
-
return
|
|
20
|
+
return DreamGlam.fluffstopherwalkin();
|
|
23
21
|
}
|
|
24
22
|
expressApp;
|
|
25
|
-
frontEndClient;
|
|
26
23
|
httpServer;
|
|
27
24
|
booted = false;
|
|
28
25
|
constructor() {
|
|
@@ -73,23 +70,17 @@ export default class PsychicServer {
|
|
|
73
70
|
return true;
|
|
74
71
|
}
|
|
75
72
|
// TODO: use config helper for fetching default port
|
|
76
|
-
async start(port
|
|
73
|
+
async start(port) {
|
|
77
74
|
await this.boot();
|
|
78
|
-
if (withFrontEndClient) {
|
|
79
|
-
this.frontEndClient = new FrontEndClientServer();
|
|
80
|
-
this.frontEndClient.start(frontEndPort);
|
|
81
|
-
}
|
|
82
75
|
const psychicApp = PsychicApplication.getOrFail();
|
|
83
76
|
const startOverride = psychicApp['overrides']['server:start'];
|
|
84
77
|
if (startOverride) {
|
|
85
|
-
this.httpServer = await startOverride(this, { port
|
|
78
|
+
this.httpServer = await startOverride(this, { port });
|
|
86
79
|
}
|
|
87
80
|
else {
|
|
88
81
|
const httpServer = await startPsychicServer({
|
|
89
82
|
app: this.expressApp,
|
|
90
83
|
port: port || psychicApp.port,
|
|
91
|
-
withFrontEndClient,
|
|
92
|
-
frontEndPort,
|
|
93
84
|
sslCredentials: this.config.sslCredentials,
|
|
94
85
|
});
|
|
95
86
|
this.httpServer = httpServer;
|
|
@@ -121,7 +112,6 @@ export default class PsychicServer {
|
|
|
121
112
|
for (const hook of psychicApp.specialHooks.serverShutdown) {
|
|
122
113
|
await hook(this);
|
|
123
114
|
}
|
|
124
|
-
this.frontEndClient?.stop();
|
|
125
115
|
this.httpServer?.close();
|
|
126
116
|
if (!bypassClosingDbConnections) {
|
|
127
117
|
await closeAllDbConnections();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function sleep(ms: number): Promise<unknown>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { LaunchDevServerOpts } from './helpers/launchDevServer.js';
|
|
2
|
+
export default class PsychicDevtools {
|
|
3
|
+
static launchDevServer(key: string, opts?: LaunchDevServerOpts): Promise<void>;
|
|
4
|
+
static stopDevServer(key: string): void;
|
|
5
|
+
static stopDevServers(): void;
|
|
6
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function launchDevServer(key: string, { port, cmd, timeout }?: LaunchDevServerOpts): Promise<void>;
|
|
2
|
+
export declare function stopDevServer(key: string): void;
|
|
3
|
+
export declare function stopDevServers(): void;
|
|
4
|
+
export interface LaunchDevServerOpts {
|
|
5
|
+
port?: number;
|
|
6
|
+
cmd?: string;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
}
|
|
@@ -11,6 +11,7 @@ export declare const pluralize: {
|
|
|
11
11
|
};
|
|
12
12
|
export { default as PsychicBin } from './bin/index.js';
|
|
13
13
|
export { default as PsychicCLI } from './cli/index.js';
|
|
14
|
+
export { default as PsychicDevtools } from './devtools/PsychicDevtools.js';
|
|
14
15
|
export { BeforeAction, OpenAPI } from './controller/decorators.js';
|
|
15
16
|
export { default as PsychicController, type PsychicOpenapiControllerConfig, type PsychicOpenapiNames, type PsychicParamsDictionary, type PsychicParamsPrimitive, } from './controller/index.js';
|
|
16
17
|
export { default as envLoader } from './env/Loader.js';
|
|
@@ -96,8 +96,6 @@ export interface PsychicApplicationOverrides {
|
|
|
96
96
|
}
|
|
97
97
|
export interface PsychicServerStartProviderOptions {
|
|
98
98
|
port: number | undefined;
|
|
99
|
-
withFrontEndClient: boolean;
|
|
100
|
-
frontEndPort: number | undefined;
|
|
101
99
|
}
|
|
102
100
|
export interface CustomCookieOptions {
|
|
103
101
|
maxAge?: CustomCookieMaxAgeOptions;
|
|
@@ -6,9 +6,7 @@ import { PsychicSslCredentials } from '../../psychic-application/index.js';
|
|
|
6
6
|
export interface StartPsychicServerOptions {
|
|
7
7
|
app: Application;
|
|
8
8
|
port: number;
|
|
9
|
-
withFrontEndClient: boolean;
|
|
10
|
-
frontEndPort: number;
|
|
11
9
|
sslCredentials: PsychicSslCredentials | undefined;
|
|
12
10
|
}
|
|
13
|
-
export default function startPsychicServer({ app, port,
|
|
11
|
+
export default function startPsychicServer({ app, port, sslCredentials, }: StartPsychicServerOptions): Promise<Server>;
|
|
14
12
|
export declare function createPsychicHttpInstance(app: Application, sslCredentials: PsychicSslCredentials | undefined): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | https.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
@@ -1,24 +1,19 @@
|
|
|
1
1
|
import { Application } from 'express';
|
|
2
2
|
import { Server } from 'http';
|
|
3
3
|
import PsychicApplication, { PsychicSslCredentials } from '../psychic-application/index.js';
|
|
4
|
-
import FrontEndClientServer from './front-end-client.js';
|
|
5
4
|
import { StartPsychicServerOptions } from './helpers/startPsychicServer.js';
|
|
6
5
|
export default class PsychicServer {
|
|
7
6
|
static startPsychicServer(opts: StartPsychicServerOptions): Promise<Server>;
|
|
8
7
|
static createPsychicHttpInstance(app: Application, sslCredentials: PsychicSslCredentials | undefined): Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse> | import("https").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
|
|
9
8
|
static asciiLogo(): string;
|
|
10
9
|
expressApp: Application;
|
|
11
|
-
frontEndClient: FrontEndClientServer;
|
|
12
10
|
httpServer: Server;
|
|
13
11
|
private booted;
|
|
14
12
|
constructor();
|
|
15
13
|
get config(): PsychicApplication;
|
|
16
14
|
routes(): Promise<import("../router/route-manager.js").RouteConfig[]>;
|
|
17
15
|
boot(): Promise<true | undefined>;
|
|
18
|
-
start(port?: number
|
|
19
|
-
withFrontEndClient?: boolean;
|
|
20
|
-
frontEndPort?: number;
|
|
21
|
-
}): Promise<boolean>;
|
|
16
|
+
start(port?: number): Promise<boolean>;
|
|
22
17
|
attach(id: string, obj: any): void;
|
|
23
18
|
$attached: Record<string, any>;
|
|
24
19
|
private shutdownAndExit;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@rvoh/psychic",
|
|
4
4
|
"description": "Typescript web framework",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.25.0",
|
|
6
6
|
"author": "RVOHealth",
|
|
7
7
|
"repository": "https://github.com/rvohealth/psychic.git",
|
|
8
8
|
"license": "MIT",
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
"client": "yarn --cwd=./client start",
|
|
24
24
|
"psy": "yarn psyts",
|
|
25
25
|
"psyjs": "node ./dist/test-app/src/cli/index.js",
|
|
26
|
-
"psyts": "
|
|
26
|
+
"psyts": "NODE_ENV=${NODE_ENV:-test} tsx ./test-app/src/cli/index.ts",
|
|
27
27
|
"psycore": "PSYCHIC_CORE_DEVELOPMENT=1 yarn psyts",
|
|
28
|
-
"gpsycore": "PSYCHIC_CORE_DEVELOPMENT=1
|
|
28
|
+
"gpsycore": "PSYCHIC_CORE_DEVELOPMENT=1 tsx ./global-cli/main.ts",
|
|
29
29
|
"build": "echo \"building cjs...\" && rm -rf dist && npx tsc -p ./tsconfig.cjs.build.json && echo \"building esm...\" && npx tsc -p ./tsconfig.esm.build.json",
|
|
30
30
|
"build:core": "rm -rf dist && echo \"building core app to esm...\" && npx tsc -p ./tsconfig.esm.build.core.json && echo \"building core app to cjs...\" && npx tsc -p ./tsconfig.cjs.build.core.json",
|
|
31
|
-
"dev": "PSYCHIC_CORE_DEVELOPMENT=1 NODE_ENV=development
|
|
32
|
-
"console": "PSYCHIC_CORE_DEVELOPMENT=1
|
|
31
|
+
"dev": "PSYCHIC_CORE_DEVELOPMENT=1 NODE_ENV=development tsx ./test-app/main.ts",
|
|
32
|
+
"console": "PSYCHIC_CORE_DEVELOPMENT=1 tsx ./test-app/src/conf/repl.ts",
|
|
33
33
|
"uspec": "PSYCHIC_CORE_DEVELOPMENT=1 vitest --config ./spec/unit/vite.config.ts",
|
|
34
34
|
"fspec": "PSYCHIC_CORE_DEVELOPMENT=1 vitest run --config=./spec/features/vite.config.ts",
|
|
35
35
|
"format": "yarn run prettier . --write",
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
"@types/cookie-parser": "^1.4.7",
|
|
41
41
|
"@types/cors": "^2.8.17",
|
|
42
42
|
"@types/lodash.groupby": "^4.6.9",
|
|
43
|
-
"colorette": "^2.0.20",
|
|
44
43
|
"commander": "^12.1.0",
|
|
45
44
|
"cookie-parser": "^1.4.7",
|
|
46
45
|
"cors": "^2.8.5",
|
|
@@ -50,7 +49,8 @@
|
|
|
50
49
|
"lodash-es": "^4.17.21",
|
|
51
50
|
"lodash.clonedeep": "^4.5.0",
|
|
52
51
|
"lodash.groupby": "^4.6.0",
|
|
53
|
-
"pluralize-esm": "^9.0.5"
|
|
52
|
+
"pluralize-esm": "^9.0.5",
|
|
53
|
+
"yoctocolors": "^2.1.1"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"@rvoh/dream": "*",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@eslint/js": "^9.19.0",
|
|
63
63
|
"@jest-mock/express": "^3.0.0",
|
|
64
|
-
"@rvoh/dream": "^0.
|
|
64
|
+
"@rvoh/dream": "^0.30.3",
|
|
65
65
|
"@rvoh/dream-spec-helpers": "=0.1.0",
|
|
66
66
|
"@rvoh/psychic-spec-helpers": "=0.2.0",
|
|
67
67
|
"@types/express": "^4.17.21",
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"prettier": "^3.3.3",
|
|
85
85
|
"puppeteer": "^24.4.0",
|
|
86
86
|
"supertest": "^7.0.0",
|
|
87
|
-
"ts-node": "^10.9.2",
|
|
88
87
|
"tslib": "^2.7.0",
|
|
88
|
+
"tsx": "^4.19.3",
|
|
89
89
|
"typedoc": "^0.26.6",
|
|
90
90
|
"typescript": "^5.5.4",
|
|
91
91
|
"typescript-eslint": "=7.18.0",
|
|
@@ -93,4 +93,4 @@
|
|
|
93
93
|
"winston": "^3.14.2"
|
|
94
94
|
},
|
|
95
95
|
"packageManager": "yarn@4.4.1"
|
|
96
|
-
}
|
|
96
|
+
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = logo;
|
|
4
|
-
exports.basicLogo = basicLogo;
|
|
5
|
-
const colors = require("colorette");
|
|
6
|
-
function logo() {
|
|
7
|
-
return (colors.bgMagentaBright(colors.black(`
|
|
8
|
-
,▄█▄
|
|
9
|
-
]█▄▄ ╓█████▌
|
|
10
|
-
▐██████▄ ▄█████▓╣█
|
|
11
|
-
║████████▄, , ,,▄,▄▄▄▓██████╬╬╣╣▌
|
|
12
|
-
╚███╣██████████▓▓▓▓██████████╩╠╬▓
|
|
13
|
-
╙█╬╬╬▓███████████████████████▒▓▌ `)) +
|
|
14
|
-
colors.bgMagentaBright(colors.black(`
|
|
15
|
-
╙▓█▓██████████████████████████
|
|
16
|
-
╚██████▀███████████`) + colors.greenBright(`╩█▓▌`) + colors.black(`▐▓████▄
|
|
17
|
-
'║█████`) + colors.greenBright(`\`╣█Γ║`) + colors.black(`████████▄▄φ▓█████▌
|
|
18
|
-
║█████████████████████▓█████▌
|
|
19
|
-
█████████████▓▓████████████ `)) +
|
|
20
|
-
colors.bgMagentaBright(colors.black(`
|
|
21
|
-
║█████████████████████████
|
|
22
|
-
]█████████████████████████
|
|
23
|
-
,▓██████████████████████████
|
|
24
|
-
▓█████████████████████████████µ `)) +
|
|
25
|
-
colors.bgMagentaBright(colors.black(`
|
|
26
|
-
▐███████████████████████████████▄▄
|
|
27
|
-
║█████████████████████████████████╬╬╣▓
|
|
28
|
-
,╔╦║███████████████████████████████████▓╬╬╣
|
|
29
|
-
,≥≥⌠░░░╠▓████████████████████████████████████▓▓
|
|
30
|
-
,;=-',▄█████████████████████████████████████████▓ `)) +
|
|
31
|
-
colors.bgGreen(colors.magenta(`
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
██████╗ ███████╗██╗ ██╗ ██████╗██╗ ██╗██╗ ██████╗
|
|
36
|
-
██╔══██╗██╔════╝╚██╗ ██╔╝██╔════╝██║ ██║██║██╔════╝
|
|
37
|
-
██████╔╝███████╗ ╚████╔╝ ██║ ███████║██║██║
|
|
38
|
-
██╔═══╝ ╚════██║ ╚██╔╝ ██║ ██╔══██║██║██║
|
|
39
|
-
██║ ███████║ ██║ ╚██████╗██║ ██║██║╚██████╗
|
|
40
|
-
╚═╝ ╚══════╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═════╝
|
|
41
|
-
|
|
42
|
-
`)));
|
|
43
|
-
}
|
|
44
|
-
function basicLogo() {
|
|
45
|
-
return (`
|
|
46
|
-
,▄█▄
|
|
47
|
-
]█▄▄ ╓█████▌
|
|
48
|
-
▐██████▄ ▄█████▓╣█
|
|
49
|
-
║████████▄, , ,,▄,▄▄▄▓██████╬╬╣╣▌
|
|
50
|
-
╚███╣██████████▓▓▓▓██████████╩╠╬▓
|
|
51
|
-
╙█╬╬╬▓███████████████████████▒▓▌
|
|
52
|
-
╙▓█▓██████████████████████████
|
|
53
|
-
╚██████▀███████████╩█▓▌▐▓████▄
|
|
54
|
-
'║█████\`╣█Γ║████████▄▄φ▓█████▌
|
|
55
|
-
║█████████████████████▓█████▌
|
|
56
|
-
█████████████▓▓████████████
|
|
57
|
-
║█████████████████████████
|
|
58
|
-
]█████████████████████████
|
|
59
|
-
,▓██████████████████████████
|
|
60
|
-
▓█████████████████████████████µ
|
|
61
|
-
▐███████████████████████████████▄▄
|
|
62
|
-
║█████████████████████████████████╬╬╣▓
|
|
63
|
-
,╔╦║███████████████████████████████████▓╬╬╣
|
|
64
|
-
,≥≥⌠░░░╠▓████████████████████████████████████▓▓
|
|
65
|
-
,;=-',▄█████████████████████████████████████████▓
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
██████╗ ███████╗██╗ ██╗ ██████╗██╗ ██╗██╗ ██████╗
|
|
70
|
-
██╔══██╗██╔════╝╚██╗ ██╔╝██╔════╝██║ ██║██║██╔════╝
|
|
71
|
-
██████╔╝███████╗ ╚████╔╝ ██║ ███████║██║██║
|
|
72
|
-
██╔═══╝ ╚════██║ ╚██╔╝ ██║ ██╔══██║██║██║
|
|
73
|
-
██║ ███████║ ██║ ╚██████╗██║ ██║██║╚██████╗
|
|
74
|
-
╚═╝ ╚══════╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═════╝
|
|
75
|
-
|
|
76
|
-
`);
|
|
77
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const sspawn_js_1 = require("../helpers/sspawn.js");
|
|
4
|
-
class FrontEndClientServer {
|
|
5
|
-
child;
|
|
6
|
-
start(port = 3000) {
|
|
7
|
-
this.child = (0, sspawn_js_1.ssspawn)(`PORT=${port} yarn client`, { stdio: 'ignore' });
|
|
8
|
-
}
|
|
9
|
-
stop() {
|
|
10
|
-
if (!this.child)
|
|
11
|
-
return;
|
|
12
|
-
this.child.kill();
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
exports.default = FrontEndClientServer;
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import * as colors from 'colorette';
|
|
2
|
-
export default function logo() {
|
|
3
|
-
return (colors.bgMagentaBright(colors.black(`
|
|
4
|
-
,▄█▄
|
|
5
|
-
]█▄▄ ╓█████▌
|
|
6
|
-
▐██████▄ ▄█████▓╣█
|
|
7
|
-
║████████▄, , ,,▄,▄▄▄▓██████╬╬╣╣▌
|
|
8
|
-
╚███╣██████████▓▓▓▓██████████╩╠╬▓
|
|
9
|
-
╙█╬╬╬▓███████████████████████▒▓▌ `)) +
|
|
10
|
-
colors.bgMagentaBright(colors.black(`
|
|
11
|
-
╙▓█▓██████████████████████████
|
|
12
|
-
╚██████▀███████████`) + colors.greenBright(`╩█▓▌`) + colors.black(`▐▓████▄
|
|
13
|
-
'║█████`) + colors.greenBright(`\`╣█Γ║`) + colors.black(`████████▄▄φ▓█████▌
|
|
14
|
-
║█████████████████████▓█████▌
|
|
15
|
-
█████████████▓▓████████████ `)) +
|
|
16
|
-
colors.bgMagentaBright(colors.black(`
|
|
17
|
-
║█████████████████████████
|
|
18
|
-
]█████████████████████████
|
|
19
|
-
,▓██████████████████████████
|
|
20
|
-
▓█████████████████████████████µ `)) +
|
|
21
|
-
colors.bgMagentaBright(colors.black(`
|
|
22
|
-
▐███████████████████████████████▄▄
|
|
23
|
-
║█████████████████████████████████╬╬╣▓
|
|
24
|
-
,╔╦║███████████████████████████████████▓╬╬╣
|
|
25
|
-
,≥≥⌠░░░╠▓████████████████████████████████████▓▓
|
|
26
|
-
,;=-',▄█████████████████████████████████████████▓ `)) +
|
|
27
|
-
colors.bgGreen(colors.magenta(`
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
██████╗ ███████╗██╗ ██╗ ██████╗██╗ ██╗██╗ ██████╗
|
|
32
|
-
██╔══██╗██╔════╝╚██╗ ██╔╝██╔════╝██║ ██║██║██╔════╝
|
|
33
|
-
██████╔╝███████╗ ╚████╔╝ ██║ ███████║██║██║
|
|
34
|
-
██╔═══╝ ╚════██║ ╚██╔╝ ██║ ██╔══██║██║██║
|
|
35
|
-
██║ ███████║ ██║ ╚██████╗██║ ██║██║╚██████╗
|
|
36
|
-
╚═╝ ╚══════╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═════╝
|
|
37
|
-
|
|
38
|
-
`)));
|
|
39
|
-
}
|
|
40
|
-
export function basicLogo() {
|
|
41
|
-
return (`
|
|
42
|
-
,▄█▄
|
|
43
|
-
]█▄▄ ╓█████▌
|
|
44
|
-
▐██████▄ ▄█████▓╣█
|
|
45
|
-
║████████▄, , ,,▄,▄▄▄▓██████╬╬╣╣▌
|
|
46
|
-
╚███╣██████████▓▓▓▓██████████╩╠╬▓
|
|
47
|
-
╙█╬╬╬▓███████████████████████▒▓▌
|
|
48
|
-
╙▓█▓██████████████████████████
|
|
49
|
-
╚██████▀███████████╩█▓▌▐▓████▄
|
|
50
|
-
'║█████\`╣█Γ║████████▄▄φ▓█████▌
|
|
51
|
-
║█████████████████████▓█████▌
|
|
52
|
-
█████████████▓▓████████████
|
|
53
|
-
║█████████████████████████
|
|
54
|
-
]█████████████████████████
|
|
55
|
-
,▓██████████████████████████
|
|
56
|
-
▓█████████████████████████████µ
|
|
57
|
-
▐███████████████████████████████▄▄
|
|
58
|
-
║█████████████████████████████████╬╬╣▓
|
|
59
|
-
,╔╦║███████████████████████████████████▓╬╬╣
|
|
60
|
-
,≥≥⌠░░░╠▓████████████████████████████████████▓▓
|
|
61
|
-
,;=-',▄█████████████████████████████████████████▓
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
██████╗ ███████╗██╗ ██╗ ██████╗██╗ ██╗██╗ ██████╗
|
|
66
|
-
██╔══██╗██╔════╝╚██╗ ██╔╝██╔════╝██║ ██║██║██╔════╝
|
|
67
|
-
██████╔╝███████╗ ╚████╔╝ ██║ ███████║██║██║
|
|
68
|
-
██╔═══╝ ╚════██║ ╚██╔╝ ██║ ██╔══██║██║██║
|
|
69
|
-
██║ ███████║ ██║ ╚██████╗██║ ██║██║╚██████╗
|
|
70
|
-
╚═╝ ╚══════╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═════╝
|
|
71
|
-
|
|
72
|
-
`);
|
|
73
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { ssspawn } from '../helpers/sspawn.js';
|
|
2
|
-
export default class FrontEndClientServer {
|
|
3
|
-
child;
|
|
4
|
-
start(port = 3000) {
|
|
5
|
-
this.child = ssspawn(`PORT=${port} yarn client`, { stdio: 'ignore' });
|
|
6
|
-
}
|
|
7
|
-
stop() {
|
|
8
|
-
if (!this.child)
|
|
9
|
-
return;
|
|
10
|
-
this.child.kill();
|
|
11
|
-
}
|
|
12
|
-
}
|