@rvoh/psychic 1.1.3 → 1.1.5
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/CHANGELOG.md +10 -0
- package/dist/cjs/src/cli/index.js +2 -2
- package/dist/cjs/src/generate/helpers/reduxBindings/promptForOptions.js +1 -1
- package/dist/cjs/src/generate/helpers/reduxBindings/writeOpenapiJsonFile.js +6 -3
- package/dist/cjs/src/generate/resource.js +5 -0
- package/dist/cjs/src/psychic-app/index.js +4 -5
- package/dist/esm/src/cli/index.js +2 -2
- package/dist/esm/src/generate/helpers/reduxBindings/promptForOptions.js +1 -1
- package/dist/esm/src/generate/helpers/reduxBindings/writeOpenapiJsonFile.js +6 -3
- package/dist/esm/src/generate/resource.js +5 -0
- package/dist/esm/src/psychic-app/index.js +5 -5
- package/dist/types/src/psychic-app/index.d.ts +2 -4
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -48,3 +48,13 @@ Fix route printing regression causing route printouts to show the path instead o
|
|
|
48
48
|
## 1.1.3
|
|
49
49
|
|
|
50
50
|
- fix more minor issues with redux openapi bindings
|
|
51
|
+
|
|
52
|
+
## 1.1.4
|
|
53
|
+
|
|
54
|
+
- fix regressions to redux bindings caused by default openapi path location changes
|
|
55
|
+
- resource generator can handle prefixing slashes
|
|
56
|
+
|
|
57
|
+
## 1.1.5
|
|
58
|
+
|
|
59
|
+
- pass packageManager through to dream, now that it accepts a packageManager setting.
|
|
60
|
+
- update dream shadowing within psychic application initialization to take place after initializers and plugins are processed, so that those initializers and plugins have an opportunity to adjust the settings.
|
|
@@ -99,7 +99,7 @@ class PsychicCLI {
|
|
|
99
99
|
program
|
|
100
100
|
.command('setup:sync:openapi-redux')
|
|
101
101
|
.description('generates openapi redux bindings to connect one of your openapi files to one of your clients')
|
|
102
|
-
.option('--schema-file', 'the path from your api root to the openapi file you wish to use to generate your schema, i.e. ./openapi/openapi.json')
|
|
102
|
+
.option('--schema-file', 'the path from your api root to the openapi file you wish to use to generate your schema, i.e. ./src/openapi/openapi.json')
|
|
103
103
|
.option('--api-file', 'the path to the boilerplate api file that will be used to scaffold your backend endpoints together with, i.e. ../client/app/api.ts')
|
|
104
104
|
.option('--api-import', 'the camelCased name of the export from your api module, i.e. emptyBackendApi')
|
|
105
105
|
.option('--output-file', 'the path to the file that will contain your typescript openapi redux bindings, i.e. ../client/app/myBackendApi.ts')
|
|
@@ -118,7 +118,7 @@ class PsychicCLI {
|
|
|
118
118
|
program
|
|
119
119
|
.command('setup:sync:openapi-typescript')
|
|
120
120
|
.description('generates an initializer in your app for converting one of your openapi files to typescript')
|
|
121
|
-
.argument('<openapiFilepath>', 'the path from your backend directory to the openapi file you wish to scan, i.e. "./openapi/openapi.json"')
|
|
121
|
+
.argument('<openapiFilepath>', 'the path from your backend directory to the openapi file you wish to scan, i.e. "./src/openapi/openapi.json"')
|
|
122
122
|
.argument('<outfile>', 'the path from your backend directory to the location which you want the openapi types written to. Must end with .d.ts, i.e. "./src/conf/openapi/openapi.types.d.ts"')
|
|
123
123
|
.option('--initializer-filename', 'the name you want the file to be in your initializers folder. defaults to `sync-openapi-typescript.ts`')
|
|
124
124
|
.action(async (openapiFilepath, outfile, { initializerName, }) => {
|
|
@@ -9,7 +9,7 @@ const cli_prompt_js_1 = __importDefault(require("../../../cli/helpers/cli-prompt
|
|
|
9
9
|
const index_js_1 = __importDefault(require("../../../psychic-app/index.js"));
|
|
10
10
|
async function promptForOptions(options) {
|
|
11
11
|
if (!options.schemaFile) {
|
|
12
|
-
const defaultVal = './openapi/openapi.json';
|
|
12
|
+
const defaultVal = './src/openapi/openapi.json';
|
|
13
13
|
const answer = await (0, cli_prompt_js_1.default)(`\
|
|
14
14
|
What would you like the schemaFile to be?
|
|
15
15
|
|
|
@@ -36,9 +36,9 @@ async function writeOpenapiJsonFile({ exportName, schemaFile, apiFile, apiImport
|
|
|
36
36
|
const destDir = path.join((0, psychicPath_js_1.default)('conf'), 'openapi');
|
|
37
37
|
const destPath = path.join(destDir, destFilename);
|
|
38
38
|
const jsonData = {
|
|
39
|
-
schemaFile:
|
|
40
|
-
apiFile:
|
|
41
|
-
outputFile:
|
|
39
|
+
schemaFile: path.join('..', '..', '..', replacePrefixingPathSegment(schemaFile)),
|
|
40
|
+
apiFile: path.join('..', '..', '..', replacePrefixingPathSegment(apiFile)),
|
|
41
|
+
outputFile: path.join('..', '..', '..', replacePrefixingPathSegment(outputFile)),
|
|
42
42
|
apiImport,
|
|
43
43
|
exportName,
|
|
44
44
|
hooks: true,
|
|
@@ -51,3 +51,6 @@ async function writeOpenapiJsonFile({ exportName, schemaFile, apiFile, apiImport
|
|
|
51
51
|
}
|
|
52
52
|
await fs.writeFile(destPath, JSON.stringify(jsonData, null, 2));
|
|
53
53
|
}
|
|
54
|
+
function replacePrefixingPathSegment(path) {
|
|
55
|
+
return path.replace(/^\.[/\\]/, '');
|
|
56
|
+
}
|
|
@@ -12,6 +12,11 @@ const addResourceToRoutes_js_1 = __importDefault(require("./helpers/addResourceT
|
|
|
12
12
|
exports.RESOURCE_ACTIONS = ['index', 'show', 'create', 'update', 'destroy'];
|
|
13
13
|
exports.SINGULAR_RESOURCE_ACTIONS = ['show', 'create', 'update', 'destroy'];
|
|
14
14
|
async function generateResource({ route, fullyQualifiedModelName, options, columnsWithTypes, }) {
|
|
15
|
+
// sanitize route here, making sure that the leading
|
|
16
|
+
// slash is not passed through to subsequent helpers,
|
|
17
|
+
// which will exhibit bad behavior when provided with
|
|
18
|
+
// a prefixing slash.
|
|
19
|
+
route = route.replace(/^\/+/, '');
|
|
15
20
|
const fullyQualifiedControllerName = (0, dream_1.standardizeFullyQualifiedModelName)(route);
|
|
16
21
|
const resourcefulActions = options.singular ? [...exports.SINGULAR_RESOURCE_ACTIONS] : [...exports.RESOURCE_ACTIONS];
|
|
17
22
|
const onlyActions = options.only?.split(',');
|
|
@@ -26,7 +26,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.PsychicAppAllowedPackageManagersEnumValues = void 0;
|
|
30
29
|
const dream_1 = require("@rvoh/dream");
|
|
31
30
|
const PackageManager_js_1 = __importDefault(require("../cli/helpers/PackageManager.js"));
|
|
32
31
|
const init_missing_api_root_js_1 = __importDefault(require("../error/psychic-app/init-missing-api-root.js"));
|
|
@@ -53,13 +52,11 @@ class PsychicApp {
|
|
|
53
52
|
throw new init_missing_api_root_js_1.default();
|
|
54
53
|
if (!psychicApp.routesCb)
|
|
55
54
|
throw new init_missing_routes_callback_js_1.default();
|
|
56
|
-
if (!
|
|
55
|
+
if (!dream_1.DreamAppAllowedPackageManagersEnumValues.includes(psychicApp.packageManager))
|
|
57
56
|
throw new init_missing_package_manager_js_1.default();
|
|
58
57
|
if (psychicApp.encryption?.cookies?.current)
|
|
59
58
|
this.checkKey('cookies', psychicApp.encryption.cookies.current.key, psychicApp.encryption.cookies.current.algorithm);
|
|
60
59
|
await psychicApp.inflections?.();
|
|
61
|
-
dreamApp.set('projectRoot', psychicApp.apiRoot);
|
|
62
|
-
dreamApp.set('logger', psychicApp.logger);
|
|
63
60
|
dreamApp.on('repl:start', context => {
|
|
64
61
|
const psychicApp = PsychicApp.getOrFail();
|
|
65
62
|
for (const globalName of Object.keys(psychicApp.services)) {
|
|
@@ -77,6 +74,9 @@ class PsychicApp {
|
|
|
77
74
|
for (const plugin of psychicApp.plugins) {
|
|
78
75
|
await plugin(psychicApp);
|
|
79
76
|
}
|
|
77
|
+
dreamApp.set('projectRoot', psychicApp.apiRoot);
|
|
78
|
+
dreamApp.set('logger', psychicApp.logger);
|
|
79
|
+
dreamApp.set('packageManager', psychicApp.packageManager);
|
|
80
80
|
(0, cache_js_1.cachePsychicApp)(psychicApp);
|
|
81
81
|
});
|
|
82
82
|
return psychicApp;
|
|
@@ -439,4 +439,3 @@ Try setting it to something valid, like:
|
|
|
439
439
|
}
|
|
440
440
|
}
|
|
441
441
|
exports.default = PsychicApp;
|
|
442
|
-
exports.PsychicAppAllowedPackageManagersEnumValues = ['yarn', 'npm', 'pnpm'];
|
|
@@ -94,7 +94,7 @@ export default class PsychicCLI {
|
|
|
94
94
|
program
|
|
95
95
|
.command('setup:sync:openapi-redux')
|
|
96
96
|
.description('generates openapi redux bindings to connect one of your openapi files to one of your clients')
|
|
97
|
-
.option('--schema-file', 'the path from your api root to the openapi file you wish to use to generate your schema, i.e. ./openapi/openapi.json')
|
|
97
|
+
.option('--schema-file', 'the path from your api root to the openapi file you wish to use to generate your schema, i.e. ./src/openapi/openapi.json')
|
|
98
98
|
.option('--api-file', 'the path to the boilerplate api file that will be used to scaffold your backend endpoints together with, i.e. ../client/app/api.ts')
|
|
99
99
|
.option('--api-import', 'the camelCased name of the export from your api module, i.e. emptyBackendApi')
|
|
100
100
|
.option('--output-file', 'the path to the file that will contain your typescript openapi redux bindings, i.e. ../client/app/myBackendApi.ts')
|
|
@@ -113,7 +113,7 @@ export default class PsychicCLI {
|
|
|
113
113
|
program
|
|
114
114
|
.command('setup:sync:openapi-typescript')
|
|
115
115
|
.description('generates an initializer in your app for converting one of your openapi files to typescript')
|
|
116
|
-
.argument('<openapiFilepath>', 'the path from your backend directory to the openapi file you wish to scan, i.e. "./openapi/openapi.json"')
|
|
116
|
+
.argument('<openapiFilepath>', 'the path from your backend directory to the openapi file you wish to scan, i.e. "./src/openapi/openapi.json"')
|
|
117
117
|
.argument('<outfile>', 'the path from your backend directory to the location which you want the openapi types written to. Must end with .d.ts, i.e. "./src/conf/openapi/openapi.types.d.ts"')
|
|
118
118
|
.option('--initializer-filename', 'the name you want the file to be in your initializers folder. defaults to `sync-openapi-typescript.ts`')
|
|
119
119
|
.action(async (openapiFilepath, outfile, { initializerName, }) => {
|
|
@@ -3,7 +3,7 @@ import cliPrompt from '../../../cli/helpers/cli-prompt.js';
|
|
|
3
3
|
import PsychicApp from '../../../psychic-app/index.js';
|
|
4
4
|
export default async function promptForOptions(options) {
|
|
5
5
|
if (!options.schemaFile) {
|
|
6
|
-
const defaultVal = './openapi/openapi.json';
|
|
6
|
+
const defaultVal = './src/openapi/openapi.json';
|
|
7
7
|
const answer = await cliPrompt(`\
|
|
8
8
|
What would you like the schemaFile to be?
|
|
9
9
|
|
|
@@ -7,9 +7,9 @@ export default async function writeOpenapiJsonFile({ exportName, schemaFile, api
|
|
|
7
7
|
const destDir = path.join(psychicPath('conf'), 'openapi');
|
|
8
8
|
const destPath = path.join(destDir, destFilename);
|
|
9
9
|
const jsonData = {
|
|
10
|
-
schemaFile:
|
|
11
|
-
apiFile:
|
|
12
|
-
outputFile:
|
|
10
|
+
schemaFile: path.join('..', '..', '..', replacePrefixingPathSegment(schemaFile)),
|
|
11
|
+
apiFile: path.join('..', '..', '..', replacePrefixingPathSegment(apiFile)),
|
|
12
|
+
outputFile: path.join('..', '..', '..', replacePrefixingPathSegment(outputFile)),
|
|
13
13
|
apiImport,
|
|
14
14
|
exportName,
|
|
15
15
|
hooks: true,
|
|
@@ -22,3 +22,6 @@ export default async function writeOpenapiJsonFile({ exportName, schemaFile, api
|
|
|
22
22
|
}
|
|
23
23
|
await fs.writeFile(destPath, JSON.stringify(jsonData, null, 2));
|
|
24
24
|
}
|
|
25
|
+
function replacePrefixingPathSegment(path) {
|
|
26
|
+
return path.replace(/^\.[/\\]/, '');
|
|
27
|
+
}
|
|
@@ -5,6 +5,11 @@ import addResourceToRoutes from './helpers/addResourceToRoutes.js';
|
|
|
5
5
|
export const RESOURCE_ACTIONS = ['index', 'show', 'create', 'update', 'destroy'];
|
|
6
6
|
export const SINGULAR_RESOURCE_ACTIONS = ['show', 'create', 'update', 'destroy'];
|
|
7
7
|
export default async function generateResource({ route, fullyQualifiedModelName, options, columnsWithTypes, }) {
|
|
8
|
+
// sanitize route here, making sure that the leading
|
|
9
|
+
// slash is not passed through to subsequent helpers,
|
|
10
|
+
// which will exhibit bad behavior when provided with
|
|
11
|
+
// a prefixing slash.
|
|
12
|
+
route = route.replace(/^\/+/, '');
|
|
8
13
|
const fullyQualifiedControllerName = standardizeFullyQualifiedModelName(route);
|
|
9
14
|
const resourcefulActions = options.singular ? [...SINGULAR_RESOURCE_ACTIONS] : [...RESOURCE_ACTIONS];
|
|
10
15
|
const onlyActions = options.only?.split(',');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DreamApp, Encrypt, } from '@rvoh/dream';
|
|
1
|
+
import { DreamApp, DreamAppAllowedPackageManagersEnumValues, Encrypt, } from '@rvoh/dream';
|
|
2
2
|
import PackageManager from '../cli/helpers/PackageManager.js';
|
|
3
3
|
import PsychicAppInitMissingApiRoot from '../error/psychic-app/init-missing-api-root.js';
|
|
4
4
|
import PsychicAppInitMissingCallToLoadControllers from '../error/psychic-app/init-missing-call-to-load-controllers.js';
|
|
@@ -24,13 +24,11 @@ export default class PsychicApp {
|
|
|
24
24
|
throw new PsychicAppInitMissingApiRoot();
|
|
25
25
|
if (!psychicApp.routesCb)
|
|
26
26
|
throw new PsychicAppInitMissingRoutesCallback();
|
|
27
|
-
if (!
|
|
27
|
+
if (!DreamAppAllowedPackageManagersEnumValues.includes(psychicApp.packageManager))
|
|
28
28
|
throw new PsychicAppInitMissingPackageManager();
|
|
29
29
|
if (psychicApp.encryption?.cookies?.current)
|
|
30
30
|
this.checkKey('cookies', psychicApp.encryption.cookies.current.key, psychicApp.encryption.cookies.current.algorithm);
|
|
31
31
|
await psychicApp.inflections?.();
|
|
32
|
-
dreamApp.set('projectRoot', psychicApp.apiRoot);
|
|
33
|
-
dreamApp.set('logger', psychicApp.logger);
|
|
34
32
|
dreamApp.on('repl:start', context => {
|
|
35
33
|
const psychicApp = PsychicApp.getOrFail();
|
|
36
34
|
for (const globalName of Object.keys(psychicApp.services)) {
|
|
@@ -48,6 +46,9 @@ export default class PsychicApp {
|
|
|
48
46
|
for (const plugin of psychicApp.plugins) {
|
|
49
47
|
await plugin(psychicApp);
|
|
50
48
|
}
|
|
49
|
+
dreamApp.set('projectRoot', psychicApp.apiRoot);
|
|
50
|
+
dreamApp.set('logger', psychicApp.logger);
|
|
51
|
+
dreamApp.set('packageManager', psychicApp.packageManager);
|
|
51
52
|
cachePsychicApp(psychicApp);
|
|
52
53
|
});
|
|
53
54
|
return psychicApp;
|
|
@@ -409,4 +410,3 @@ Try setting it to something valid, like:
|
|
|
409
410
|
}
|
|
410
411
|
}
|
|
411
412
|
}
|
|
412
|
-
export const PsychicAppAllowedPackageManagersEnumValues = ['yarn', 'npm', 'pnpm'];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DreamApp, DreamAppInitOptions, DreamLogLevel, DreamLogger, EncryptOptions, OpenapiSchemaBody } from '@rvoh/dream';
|
|
1
|
+
import { DreamApp, DreamAppAllowedPackageManagersEnum, DreamAppInitOptions, DreamLogLevel, DreamLogger, EncryptOptions, OpenapiSchemaBody } from '@rvoh/dream';
|
|
2
2
|
import * as bodyParser from 'body-parser';
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { CorsOptions } from 'cors';
|
|
@@ -95,12 +95,10 @@ export default class PsychicApp {
|
|
|
95
95
|
plugin(cb: (app: PsychicApp) => void | Promise<void>): void;
|
|
96
96
|
on<T extends PsychicHookEventType>(hookEventType: T, cb: T extends 'server:error' ? (err: Error, req: Request, res: Response) => void | Promise<void> : T extends 'server:init:before-middleware' ? (psychicServer: PsychicServer) => void | Promise<void> : T extends 'server:init:after-middleware' ? (psychicServer: PsychicServer) => void | Promise<void> : T extends 'server:start' ? (psychicServer: PsychicServer) => void | Promise<void> : T extends 'server:shutdown' ? (psychicServer: PsychicServer) => void | Promise<void> : T extends 'server:init:after-routes' ? (psychicServer: PsychicServer) => void | Promise<void> : T extends 'cli:start' ? (program: Command) => void | Promise<void> : T extends 'cli:sync' ? () => any : (conf: PsychicApp) => void | Promise<void>): void;
|
|
97
97
|
set(option: 'openapi', name: string, value: NamedPsychicOpenapiOptions): void;
|
|
98
|
-
set<Opt extends PsychicAppOption>(option: Opt, value: Opt extends 'appName' ? string : Opt extends 'apiOnly' ? boolean : Opt extends 'defaultResponseHeaders' ? Record<string, string | null> : Opt extends 'encryption' ? PsychicAppEncryptionOptions : Opt extends 'cors' ? CorsOptions : Opt extends 'cookie' ? CustomCookieOptions : Opt extends 'apiRoot' ? string : Opt extends 'sessionCookieName' ? string : Opt extends 'clientRoot' ? string : Opt extends 'json' ? bodyParser.Options : Opt extends 'logger' ? PsychicLogger : Opt extends 'client' ? PsychicClientOptions : Opt extends 'ssl' ? PsychicSslCredentials : Opt extends 'openapi' ? DefaultPsychicOpenapiOptions : Opt extends 'paths' ? PsychicPathOptions : Opt extends 'port' ? number : Opt extends 'saltRounds' ? number : Opt extends 'packageManager' ?
|
|
98
|
+
set<Opt extends PsychicAppOption>(option: Opt, value: Opt extends 'appName' ? string : Opt extends 'apiOnly' ? boolean : Opt extends 'defaultResponseHeaders' ? Record<string, string | null> : Opt extends 'encryption' ? PsychicAppEncryptionOptions : Opt extends 'cors' ? CorsOptions : Opt extends 'cookie' ? CustomCookieOptions : Opt extends 'apiRoot' ? string : Opt extends 'sessionCookieName' ? string : Opt extends 'clientRoot' ? string : Opt extends 'json' ? bodyParser.Options : Opt extends 'logger' ? PsychicLogger : Opt extends 'client' ? PsychicClientOptions : Opt extends 'ssl' ? PsychicSslCredentials : Opt extends 'openapi' ? DefaultPsychicOpenapiOptions : Opt extends 'paths' ? PsychicPathOptions : Opt extends 'port' ? number : Opt extends 'saltRounds' ? number : Opt extends 'packageManager' ? DreamAppAllowedPackageManagersEnum : Opt extends 'inflections' ? () => void | Promise<void> : Opt extends 'routes' ? (r: PsychicRouter) => void | Promise<void> : never): void;
|
|
99
99
|
override<Override extends keyof PsychicAppOverrides>(override: Override, value: PsychicAppOverrides[Override]): void;
|
|
100
100
|
}
|
|
101
101
|
export type PsychicAppOption = 'appName' | 'apiOnly' | 'apiRoot' | 'encryption' | 'sessionCookieName' | 'client' | 'clientRoot' | 'cookie' | 'cors' | 'defaultResponseHeaders' | 'inflections' | 'json' | 'logger' | 'openapi' | 'packageManager' | 'paths' | 'port' | 'routes' | 'saltRounds' | 'ssl';
|
|
102
|
-
export declare const PsychicAppAllowedPackageManagersEnumValues: readonly ["yarn", "npm", "pnpm"];
|
|
103
|
-
export type PsychicAppAllowedPackageManagersEnum = (typeof PsychicAppAllowedPackageManagersEnumValues)[number];
|
|
104
102
|
export interface PsychicAppSpecialHooks {
|
|
105
103
|
cliSync: (() => any)[];
|
|
106
104
|
serverInitBeforeMiddleware: ((server: PsychicServer) => void | Promise<void>)[];
|
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": "1.1.
|
|
5
|
+
"version": "1.1.5",
|
|
6
6
|
"author": "RVOHealth",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@eslint/js": "^9.19.0",
|
|
61
61
|
"@jest-mock/express": "^3.0.0",
|
|
62
|
-
"@rvoh/dream": "^1.0.
|
|
62
|
+
"@rvoh/dream": "^1.0.2",
|
|
63
63
|
"@rvoh/dream-spec-helpers": "^1.0.0",
|
|
64
64
|
"@rvoh/psychic-spec-helpers": "^1.0.0",
|
|
65
65
|
"@types/express": "^5.0.1",
|