@rvoh/psychic 0.37.2 → 0.37.4
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/src/bin/helpers/syncTypescriptOpenapiFiles.js +8 -2
- package/dist/cjs/src/cli/index.js +9 -0
- package/dist/cjs/src/helpers/path/psychicPath.js +27 -0
- package/dist/cjs/src/watcher/Watcher.js +71 -0
- package/dist/esm/src/bin/helpers/syncTypescriptOpenapiFiles.js +9 -3
- package/dist/esm/src/cli/index.js +9 -0
- package/dist/esm/src/helpers/path/psychicPath.js +4 -0
- package/dist/esm/src/watcher/Watcher.js +42 -0
- package/dist/types/src/helpers/path/psychicPath.d.ts +1 -1
- package/dist/types/src/watcher/Watcher.d.ts +4 -0
- package/package.json +1 -1
|
@@ -41,11 +41,17 @@ async function syncTypescriptOpenapiFiles() {
|
|
|
41
41
|
const outpath = path.join((0, psychicPath_js_1.default)('types'), `${jsonPath.replace(/\.json$/, '')}.d.ts`);
|
|
42
42
|
return dream_1.DreamCLI.spawn(`npx openapi-typescript ${jsonPath} -o ${outpath}`).then(async () => {
|
|
43
43
|
const file = (await fs.readFile(outpath)).toString();
|
|
44
|
-
const exportName = (0, dream_1.camelize)(jsonPath
|
|
44
|
+
const exportName = dotToCamelCase((0, dream_1.camelize)(jsonPath
|
|
45
45
|
.split('/')
|
|
46
46
|
.at(-1)
|
|
47
|
-
?.replace(/\.json/, '')) + 'Paths';
|
|
47
|
+
?.replace(/\.json/, ''))) + 'Paths';
|
|
48
48
|
await fs.writeFile(outpath, file.replace(/export interface paths/, `export interface ${exportName}`));
|
|
49
49
|
});
|
|
50
50
|
}));
|
|
51
51
|
}
|
|
52
|
+
function dotToCamelCase(inputString) {
|
|
53
|
+
return inputString
|
|
54
|
+
.split('.')
|
|
55
|
+
.map((word, index) => (index === 0 ? word : (0, dream_1.capitalize)(word)))
|
|
56
|
+
.join('');
|
|
57
|
+
}
|
|
@@ -8,6 +8,7 @@ const index_js_1 = __importDefault(require("../bin/index.js"));
|
|
|
8
8
|
const syncEnums_js_1 = __importDefault(require("../generate/initializer/syncEnums.js"));
|
|
9
9
|
const syncOpenapiTypescript_js_1 = __importDefault(require("../generate/initializer/syncOpenapiTypescript.js"));
|
|
10
10
|
const reduxBindings_js_1 = __importDefault(require("../generate/openapi/reduxBindings.js"));
|
|
11
|
+
const Watcher_js_1 = __importDefault(require("../watcher/Watcher.js"));
|
|
11
12
|
class PsychicCLI {
|
|
12
13
|
static provide(program, { initializePsychicApp, seedDb, }) {
|
|
13
14
|
dream_1.DreamCLI.generateDreamCli(program, {
|
|
@@ -98,6 +99,14 @@ class PsychicCLI {
|
|
|
98
99
|
await index_js_1.default.sync();
|
|
99
100
|
process.exit();
|
|
100
101
|
});
|
|
102
|
+
program
|
|
103
|
+
.command('watch')
|
|
104
|
+
.description('watches your app for changes, and re-syncs any time they happen')
|
|
105
|
+
.argument('[dir]', 'the folder you want to watch, defaults to ./src')
|
|
106
|
+
.action(async (dir) => {
|
|
107
|
+
await initializePsychicApp();
|
|
108
|
+
Watcher_js_1.default.watch(dir);
|
|
109
|
+
});
|
|
101
110
|
program
|
|
102
111
|
.command('post-sync')
|
|
103
112
|
.description('an internal command that runs as the second stage of the `sync` command, since after types are rebuit, the application needs to be reloaded before autogenerating certain files, since those files will need to leverage the updated types')
|
|
@@ -1,9 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
29
|
exports.default = default_1;
|
|
30
|
+
const path = __importStar(require("path"));
|
|
7
31
|
const dream_1 = require("@rvoh/dream");
|
|
8
32
|
const index_js_1 = __importDefault(require("../../psychic-app/index.js"));
|
|
9
33
|
function default_1(dreamPathType) {
|
|
@@ -17,6 +41,9 @@ function default_1(dreamPathType) {
|
|
|
17
41
|
return psychicApp.paths.controllerSpecs;
|
|
18
42
|
case 'services':
|
|
19
43
|
return psychicApp.paths.services;
|
|
44
|
+
case 'src':
|
|
45
|
+
// TODO: make this customizable, but maybe not.
|
|
46
|
+
return path.join((0, dream_1.dreamPath)('db'), '..');
|
|
20
47
|
default:
|
|
21
48
|
return (0, dream_1.dreamPath)(dreamPathType);
|
|
22
49
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const dream_1 = require("@rvoh/dream");
|
|
30
|
+
const fs = __importStar(require("fs"));
|
|
31
|
+
const psychicPath_js_1 = __importDefault(require("../helpers/path/psychicPath.js"));
|
|
32
|
+
const index_js_1 = __importDefault(require("../psychic-app/index.js"));
|
|
33
|
+
// should we make this customizable?
|
|
34
|
+
const TIMEOUT_INTERVAL = 3_000;
|
|
35
|
+
class Watcher {
|
|
36
|
+
static syncing = false;
|
|
37
|
+
static watch(
|
|
38
|
+
// the path to the src folder in your psychic app
|
|
39
|
+
srcDir = (0, psychicPath_js_1.default)('src')) {
|
|
40
|
+
let timer;
|
|
41
|
+
fs.watch(srcDir, { recursive: true }, (_, filename) => {
|
|
42
|
+
// do not want to sync if we are already syncing.
|
|
43
|
+
if (this.syncing)
|
|
44
|
+
return;
|
|
45
|
+
if (filename && /\.ts$/.test(filename)) {
|
|
46
|
+
// create a manual debounce pattern by clearing
|
|
47
|
+
// the timeout and restarting it
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
const seconds = TIMEOUT_INTERVAL / 1000;
|
|
50
|
+
dream_1.DreamCLI.logger.log(`${filename} changed, douncing sync for ${seconds} seconds...`);
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
52
|
+
timer = setTimeout(async () => {
|
|
53
|
+
dream_1.DreamCLI.logger.log(`executing sync...`);
|
|
54
|
+
const psy = index_js_1.default.getOrFail();
|
|
55
|
+
this.syncing = true;
|
|
56
|
+
await dream_1.DreamCLI.spawn(psy.psyCmd('sync'));
|
|
57
|
+
// pause for an additional second, so that any file changes
|
|
58
|
+
// still being regestered from the end of the sync
|
|
59
|
+
// command don't accidentally trick it into running again,
|
|
60
|
+
// which could cause an infinite loop of reloading
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
this.syncing = false;
|
|
63
|
+
dream_1.DreamCLI.logger.log(`resuming watch...`);
|
|
64
|
+
}, 1000);
|
|
65
|
+
}, TIMEOUT_INTERVAL);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
dream_1.DreamCLI.logger.log(`watching ${srcDir}...`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.default = Watcher;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { camelize, DreamCLI } from '@rvoh/dream';
|
|
1
|
+
import { camelize, capitalize, DreamCLI } from '@rvoh/dream';
|
|
2
2
|
import * as fs from 'node:fs/promises';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import PsychicApp from '../../psychic-app/index.js';
|
|
@@ -12,11 +12,17 @@ export default async function syncTypescriptOpenapiFiles() {
|
|
|
12
12
|
const outpath = path.join(psychicPath('types'), `${jsonPath.replace(/\.json$/, '')}.d.ts`);
|
|
13
13
|
return DreamCLI.spawn(`npx openapi-typescript ${jsonPath} -o ${outpath}`).then(async () => {
|
|
14
14
|
const file = (await fs.readFile(outpath)).toString();
|
|
15
|
-
const exportName = camelize(jsonPath
|
|
15
|
+
const exportName = dotToCamelCase(camelize(jsonPath
|
|
16
16
|
.split('/')
|
|
17
17
|
.at(-1)
|
|
18
|
-
?.replace(/\.json/, '')) + 'Paths';
|
|
18
|
+
?.replace(/\.json/, ''))) + 'Paths';
|
|
19
19
|
await fs.writeFile(outpath, file.replace(/export interface paths/, `export interface ${exportName}`));
|
|
20
20
|
});
|
|
21
21
|
}));
|
|
22
22
|
}
|
|
23
|
+
function dotToCamelCase(inputString) {
|
|
24
|
+
return inputString
|
|
25
|
+
.split('.')
|
|
26
|
+
.map((word, index) => (index === 0 ? word : capitalize(word)))
|
|
27
|
+
.join('');
|
|
28
|
+
}
|
|
@@ -3,6 +3,7 @@ import PsychicBin from '../bin/index.js';
|
|
|
3
3
|
import generateSyncEnumsInitializer from '../generate/initializer/syncEnums.js';
|
|
4
4
|
import generateSyncOpenapiTypescriptInitializer from '../generate/initializer/syncOpenapiTypescript.js';
|
|
5
5
|
import generateOpenapiReduxBindings from '../generate/openapi/reduxBindings.js';
|
|
6
|
+
import Watcher from '../watcher/Watcher.js';
|
|
6
7
|
export default class PsychicCLI {
|
|
7
8
|
static provide(program, { initializePsychicApp, seedDb, }) {
|
|
8
9
|
DreamCLI.generateDreamCli(program, {
|
|
@@ -93,6 +94,14 @@ export default class PsychicCLI {
|
|
|
93
94
|
await PsychicBin.sync();
|
|
94
95
|
process.exit();
|
|
95
96
|
});
|
|
97
|
+
program
|
|
98
|
+
.command('watch')
|
|
99
|
+
.description('watches your app for changes, and re-syncs any time they happen')
|
|
100
|
+
.argument('[dir]', 'the folder you want to watch, defaults to ./src')
|
|
101
|
+
.action(async (dir) => {
|
|
102
|
+
await initializePsychicApp();
|
|
103
|
+
Watcher.watch(dir);
|
|
104
|
+
});
|
|
96
105
|
program
|
|
97
106
|
.command('post-sync')
|
|
98
107
|
.description('an internal command that runs as the second stage of the `sync` command, since after types are rebuit, the application needs to be reloaded before autogenerating certain files, since those files will need to leverage the updated types')
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
1
2
|
import { dreamPath } from '@rvoh/dream';
|
|
2
3
|
import PsychicApp from '../../psychic-app/index.js';
|
|
3
4
|
export default function (dreamPathType) {
|
|
@@ -11,6 +12,9 @@ export default function (dreamPathType) {
|
|
|
11
12
|
return psychicApp.paths.controllerSpecs;
|
|
12
13
|
case 'services':
|
|
13
14
|
return psychicApp.paths.services;
|
|
15
|
+
case 'src':
|
|
16
|
+
// TODO: make this customizable, but maybe not.
|
|
17
|
+
return path.join(dreamPath('db'), '..');
|
|
14
18
|
default:
|
|
15
19
|
return dreamPath(dreamPathType);
|
|
16
20
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DreamCLI } from '@rvoh/dream';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import psychicPath from '../helpers/path/psychicPath.js';
|
|
4
|
+
import PsychicApp from '../psychic-app/index.js';
|
|
5
|
+
// should we make this customizable?
|
|
6
|
+
const TIMEOUT_INTERVAL = 3_000;
|
|
7
|
+
export default class Watcher {
|
|
8
|
+
static syncing = false;
|
|
9
|
+
static watch(
|
|
10
|
+
// the path to the src folder in your psychic app
|
|
11
|
+
srcDir = psychicPath('src')) {
|
|
12
|
+
let timer;
|
|
13
|
+
fs.watch(srcDir, { recursive: true }, (_, filename) => {
|
|
14
|
+
// do not want to sync if we are already syncing.
|
|
15
|
+
if (this.syncing)
|
|
16
|
+
return;
|
|
17
|
+
if (filename && /\.ts$/.test(filename)) {
|
|
18
|
+
// create a manual debounce pattern by clearing
|
|
19
|
+
// the timeout and restarting it
|
|
20
|
+
clearTimeout(timer);
|
|
21
|
+
const seconds = TIMEOUT_INTERVAL / 1000;
|
|
22
|
+
DreamCLI.logger.log(`${filename} changed, douncing sync for ${seconds} seconds...`);
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
24
|
+
timer = setTimeout(async () => {
|
|
25
|
+
DreamCLI.logger.log(`executing sync...`);
|
|
26
|
+
const psy = PsychicApp.getOrFail();
|
|
27
|
+
this.syncing = true;
|
|
28
|
+
await DreamCLI.spawn(psy.psyCmd('sync'));
|
|
29
|
+
// pause for an additional second, so that any file changes
|
|
30
|
+
// still being regestered from the end of the sync
|
|
31
|
+
// command don't accidentally trick it into running again,
|
|
32
|
+
// which could cause an infinite loop of reloading
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
this.syncing = false;
|
|
35
|
+
DreamCLI.logger.log(`resuming watch...`);
|
|
36
|
+
}, 1000);
|
|
37
|
+
}, TIMEOUT_INTERVAL);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
DreamCLI.logger.log(`watching ${srcDir}...`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export default function (dreamPathType: PsychicPaths): string;
|
|
1
|
+
export default function (dreamPathType: PsychicPaths | 'src'): string;
|
|
2
2
|
type DreamPaths = 'models' | 'modelSpecs' | 'serializers' | 'db' | 'conf' | 'factories' | 'types';
|
|
3
3
|
export type PsychicPaths = DreamPaths | 'apiRoutes' | 'controllers' | 'controllerSpecs' | 'services';
|
|
4
4
|
export {};
|