@rvoh/psychic 0.26.3 → 0.27.2

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.
Files changed (42) hide show
  1. package/README.md +6 -4
  2. package/dist/cjs/src/bin/helpers/enumsAndTheirValues.js +3 -2
  3. package/dist/cjs/src/bin/helpers/enumsFileStr.js +1 -1
  4. package/dist/cjs/src/bin/index.js +14 -0
  5. package/dist/cjs/src/cli/index.js +8 -0
  6. package/dist/cjs/src/devtools/helpers/launchDevServer.js +3 -0
  7. package/dist/cjs/src/error/UnexpectedUndefined.js +14 -0
  8. package/dist/cjs/src/error/psychic-application/init-missing-package-manager.js +20 -0
  9. package/dist/cjs/src/generate/controller.js +12 -1
  10. package/dist/cjs/src/generate/helpers/addResourceToRoutes.js +3 -0
  11. package/dist/cjs/src/helpers/openapiJsonPath.js +5 -1
  12. package/dist/cjs/src/i18n/provider.js +4 -1
  13. package/dist/cjs/src/openapi-renderer/app.js +29 -17
  14. package/dist/cjs/src/openapi-renderer/body-segment.js +3 -2
  15. package/dist/cjs/src/openapi-renderer/endpoint.js +30 -15
  16. package/dist/cjs/src/openapi-renderer/serializer.js +25 -13
  17. package/dist/cjs/src/psychic-application/index.js +47 -2
  18. package/dist/esm/src/bin/helpers/enumsAndTheirValues.js +3 -2
  19. package/dist/esm/src/bin/helpers/enumsFileStr.js +1 -1
  20. package/dist/esm/src/bin/index.js +14 -0
  21. package/dist/esm/src/cli/index.js +8 -0
  22. package/dist/esm/src/devtools/helpers/launchDevServer.js +3 -0
  23. package/dist/esm/src/error/UnexpectedUndefined.js +11 -0
  24. package/dist/esm/src/error/psychic-application/init-missing-package-manager.js +17 -0
  25. package/dist/esm/src/generate/controller.js +12 -1
  26. package/dist/esm/src/generate/helpers/addResourceToRoutes.js +3 -0
  27. package/dist/esm/src/helpers/openapiJsonPath.js +5 -1
  28. package/dist/esm/src/i18n/provider.js +4 -1
  29. package/dist/esm/src/openapi-renderer/app.js +29 -17
  30. package/dist/esm/src/openapi-renderer/body-segment.js +3 -2
  31. package/dist/esm/src/openapi-renderer/endpoint.js +30 -15
  32. package/dist/esm/src/openapi-renderer/serializer.js +25 -13
  33. package/dist/esm/src/psychic-application/index.js +46 -2
  34. package/dist/types/src/bin/index.d.ts +1 -0
  35. package/dist/types/src/error/UnexpectedUndefined.d.ts +4 -0
  36. package/dist/types/src/error/psychic-application/init-missing-package-manager.d.ts +4 -0
  37. package/dist/types/src/generate/helpers/generateControllerContent.d.ts +3 -3
  38. package/dist/types/src/psychic-application/index.d.ts +25 -4
  39. package/package.json +5 -6
  40. package/dist/cjs/src/helpers/sspawn.js +0 -26
  41. package/dist/esm/src/helpers/sspawn.js +0 -22
  42. package/dist/types/src/helpers/sspawn.d.ts +0 -2
@@ -7,6 +7,7 @@ import EnvInternal from '../helpers/EnvInternal.js';
7
7
  import { cachePsychicApplication, getCachedPsychicApplicationOrFail } from './cache.js';
8
8
  import importControllers, { getControllersOrFail } from './helpers/import/importControllers.js';
9
9
  import lookupClassByGlobalName from './helpers/lookupClassByGlobalName.js';
10
+ import PsychicApplicationInitMissingPackageManager from '../error/psychic-application/init-missing-package-manager.js';
10
11
  export default class PsychicApplication {
11
12
  static async init(cb, dreamCb, opts = {}) {
12
13
  let psychicApp;
@@ -19,11 +20,16 @@ export default class PsychicApplication {
19
20
  throw new PsychicApplicationInitMissingApiRoot();
20
21
  if (!psychicApp.routesCb)
21
22
  throw new PsychicApplicationInitMissingRoutesCallback();
23
+ if (!PsychicApplicationAllowedPackageManagersEnumValues.includes(psychicApp.packageManager))
24
+ throw new PsychicApplicationInitMissingPackageManager();
22
25
  if (psychicApp.encryption?.cookies?.current)
23
26
  this.checkKey('cookies', psychicApp.encryption.cookies.current.key, psychicApp.encryption.cookies.current.algorithm);
24
27
  await psychicApp.inflections?.();
25
28
  dreamApp.set('projectRoot', psychicApp.apiRoot);
26
29
  dreamApp.set('logger', psychicApp.logger);
30
+ for (const plugin of psychicApp.plugins) {
31
+ await plugin(psychicApp);
32
+ }
27
33
  cachePsychicApplication(psychicApp);
28
34
  });
29
35
  return psychicApp;
@@ -32,6 +38,29 @@ export default class PsychicApplication {
32
38
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
33
39
  return lookupClassByGlobalName(name);
34
40
  }
41
+ /**
42
+ * @internal
43
+ *
44
+ * used to provide the correct package manager syntax for running a script
45
+ * inside of the package.json "scripts" section.
46
+ */
47
+ packageManagerRunCmd(cmd) {
48
+ switch (this.packageManager) {
49
+ case 'npm':
50
+ return `npm run ${cmd}`;
51
+ default:
52
+ return `${this.packageManager} ${cmd}`;
53
+ }
54
+ }
55
+ /**
56
+ * @internal
57
+ *
58
+ * adds the necessary package manager prefix to the psy command provided
59
+ * i.e. `psyCmd('sync')`
60
+ */
61
+ psyCmd(cmd) {
62
+ return this.packageManagerRunCmd(`psy ${cmd}`);
63
+ }
35
64
  static checkKey(encryptionIdentifier, key, algorithm) {
36
65
  if (!Encrypt.validateKey(key, algorithm))
37
66
  console.warn(`
@@ -106,14 +135,18 @@ Try setting it to something valid, like:
106
135
  get logger() {
107
136
  return this._logger;
108
137
  }
109
- _sslCredentials;
138
+ _sslCredentials = undefined;
110
139
  get sslCredentials() {
111
140
  return this._sslCredentials;
112
141
  }
113
- _saltRounds;
142
+ _saltRounds = undefined;
114
143
  get saltRounds() {
115
144
  return this._saltRounds;
116
145
  }
146
+ _packageManager;
147
+ get packageManager() {
148
+ return this._packageManager;
149
+ }
117
150
  _routesCb;
118
151
  get routesCb() {
119
152
  return this._routesCb;
@@ -194,6 +227,10 @@ Try setting it to something valid, like:
194
227
  get controllers() {
195
228
  return getControllersOrFail();
196
229
  }
230
+ _plugins = [];
231
+ get plugins() {
232
+ return this._plugins;
233
+ }
197
234
  async load(resourceType, resourcePath,
198
235
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
199
236
  importCb) {
@@ -224,6 +261,9 @@ Try setting it to something valid, like:
224
261
  await this.inflections?.();
225
262
  this.booted = true;
226
263
  }
264
+ plugin(cb) {
265
+ this._plugins.push(cb);
266
+ }
227
267
  on(hookEventType, cb) {
228
268
  switch (hookEventType) {
229
269
  case 'server:error':
@@ -304,6 +344,9 @@ Try setting it to something valid, like:
304
344
  case 'port':
305
345
  this._port = value;
306
346
  break;
347
+ case 'packageManager':
348
+ this._packageManager = value;
349
+ break;
307
350
  case 'saltRounds':
308
351
  this._saltRounds = value;
309
352
  break;
@@ -341,3 +384,4 @@ Try setting it to something valid, like:
341
384
  }
342
385
  }
343
386
  }
387
+ export const PsychicApplicationAllowedPackageManagersEnumValues = ['yarn', 'npm', 'pnpm'];
@@ -5,6 +5,7 @@ export default class PsychicBin {
5
5
  static sync({ bypassDreamSync }?: {
6
6
  bypassDreamSync?: boolean;
7
7
  }): Promise<void>;
8
+ static postSync(): Promise<void>;
8
9
  static syncTypes(customTypes?: any): Promise<void>;
9
10
  static syncOpenapiJson(): Promise<void>;
10
11
  static syncRoutes(): Promise<void>;
@@ -0,0 +1,4 @@
1
+ export default class UnexpectedUndefined extends Error {
2
+ constructor();
3
+ get message(): string;
4
+ }
@@ -0,0 +1,4 @@
1
+ export default class PsychicApplicationInitMissingPackageManager extends Error {
2
+ constructor();
3
+ get message(): string;
4
+ }
@@ -2,7 +2,7 @@ export default function generateControllerContent({ ancestorName, ancestorImport
2
2
  ancestorName: string;
3
3
  ancestorImportStatement: string;
4
4
  fullyQualifiedControllerName: string;
5
- fullyQualifiedModelName?: string;
6
- actions?: string[];
7
- omitOpenApi?: boolean;
5
+ fullyQualifiedModelName?: string | undefined;
6
+ actions?: string[] | undefined;
7
+ omitOpenApi?: boolean | undefined;
8
8
  }): string;
@@ -11,6 +11,20 @@ import { PsychicHookEventType, PsychicHookLoadEventTypes } from './types.js';
11
11
  export default class PsychicApplication {
12
12
  static init(cb: (app: PsychicApplication) => void | Promise<void>, dreamCb: (app: DreamApplication) => void | Promise<void>, opts?: PsychicApplicationInitOptions): Promise<PsychicApplication>;
13
13
  static lookupClassByGlobalName(name: string): any;
14
+ /**
15
+ * @internal
16
+ *
17
+ * used to provide the correct package manager syntax for running a script
18
+ * inside of the package.json "scripts" section.
19
+ */
20
+ packageManagerRunCmd(cmd: string): string;
21
+ /**
22
+ * @internal
23
+ *
24
+ * adds the necessary package manager prefix to the psy command provided
25
+ * i.e. `psyCmd('sync')`
26
+ */
27
+ psyCmd(cmd: string): string;
14
28
  private static checkKey;
15
29
  /**
16
30
  * Returns the cached psychic application if it has been set.
@@ -45,10 +59,12 @@ export default class PsychicApplication {
45
59
  };
46
60
  private _logger;
47
61
  get logger(): DreamLogger;
48
- private _sslCredentials?;
62
+ private _sslCredentials;
49
63
  get sslCredentials(): PsychicSslCredentials | undefined;
50
- private _saltRounds?;
64
+ private _saltRounds;
51
65
  get saltRounds(): number | undefined;
66
+ private _packageManager;
67
+ get packageManager(): "yarn" | "npm" | "pnpm";
52
68
  private _routesCb;
53
69
  get routesCb(): (r: PsychicRouter) => void | Promise<void>;
54
70
  private _openapi;
@@ -73,16 +89,21 @@ export default class PsychicApplication {
73
89
  [x: string]: string | null;
74
90
  };
75
91
  get controllers(): Record<string, typeof import("../index.js").PsychicController>;
92
+ private _plugins;
93
+ get plugins(): ((app: PsychicApplication) => void | Promise<void>)[];
76
94
  load<RT extends 'controllers'>(resourceType: RT, resourcePath: string, importCb: (path: string) => Promise<any>): Promise<void>;
77
95
  private booted;
78
96
  boot(force?: boolean): Promise<void>;
97
+ plugin(cb: (app: PsychicApplication) => void | Promise<void>): void;
79
98
  on<T extends PsychicHookEventType>(hookEventType: T, cb: T extends 'server:error' ? (err: Error, req: Request, res: Response) => void | Promise<void> : T extends 'server:init' ? (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 'sync' ? () => any : (conf: PsychicApplication) => void | Promise<void>): void;
80
99
  set(option: 'openapi', name: string, value: NamedPsychicOpenapiOptions): void;
81
- set<Opt extends PsychicApplicationOption>(option: Opt, value: Opt extends 'appName' ? string : Opt extends 'apiOnly' ? boolean : Opt extends 'defaultResponseHeaders' ? Record<string, string | null> : Opt extends 'encryption' ? PsychicApplicationEncryptionOptions : 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 'inflections' ? () => void | Promise<void> : Opt extends 'routes' ? (r: PsychicRouter) => void | Promise<void> : never): void;
100
+ set<Opt extends PsychicApplicationOption>(option: Opt, value: Opt extends 'appName' ? string : Opt extends 'apiOnly' ? boolean : Opt extends 'defaultResponseHeaders' ? Record<string, string | null> : Opt extends 'encryption' ? PsychicApplicationEncryptionOptions : 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' ? PsychicApplicationAllowedPackageManagersEnum : Opt extends 'inflections' ? () => void | Promise<void> : Opt extends 'routes' ? (r: PsychicRouter) => void | Promise<void> : never): void;
82
101
  override<Override extends keyof PsychicApplicationOverrides>(override: Override, value: PsychicApplicationOverrides[Override]): void;
83
102
  private runHooksFor;
84
103
  }
85
- export type PsychicApplicationOption = 'appName' | 'apiOnly' | 'apiRoot' | 'encryption' | 'sessionCookieName' | 'client' | 'clientRoot' | 'cookie' | 'cors' | 'defaultResponseHeaders' | 'inflections' | 'json' | 'logger' | 'openapi' | 'paths' | 'port' | 'routes' | 'saltRounds' | 'ssl';
104
+ export type PsychicApplicationOption = 'appName' | 'apiOnly' | 'apiRoot' | 'encryption' | 'sessionCookieName' | 'client' | 'clientRoot' | 'cookie' | 'cors' | 'defaultResponseHeaders' | 'inflections' | 'json' | 'logger' | 'openapi' | 'packageManager' | 'paths' | 'port' | 'routes' | 'saltRounds' | 'ssl';
105
+ export declare const PsychicApplicationAllowedPackageManagersEnumValues: readonly ["yarn", "npm", "pnpm"];
106
+ export type PsychicApplicationAllowedPackageManagersEnum = (typeof PsychicApplicationAllowedPackageManagersEnumValues)[number];
86
107
  export interface PsychicApplicationSpecialHooks {
87
108
  sync: (() => any)[];
88
109
  serverInit: ((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": "0.26.3",
5
+ "version": "0.27.2",
6
6
  "author": "RVOHealth",
7
7
  "repository": {
8
8
  "type": "git",
@@ -24,13 +24,12 @@
24
24
  ],
25
25
  "scripts": {
26
26
  "client": "yarn --cwd=./client start",
27
- "psy": "NODE_ENV=${NODE_ENV:-test} yarn psyts",
27
+ "psy": "PSYCHIC_CORE_DEVELOPMENT=1 NODE_ENV=${NODE_ENV:-test} yarn psyts",
28
28
  "psyjs": "node ./dist/test-app/src/cli/index.js",
29
29
  "psyts": "NODE_ENV=${NODE_ENV:-test} tsx ./test-app/src/cli/index.ts",
30
- "psycore": "PSYCHIC_CORE_DEVELOPMENT=1 yarn psyts",
31
- "gpsycore": "PSYCHIC_CORE_DEVELOPMENT=1 tsx ./global-cli/main.ts",
30
+ "gpsy": "PSYCHIC_CORE_DEVELOPMENT=1 tsx ./global-cli/main.ts",
32
31
  "build": "echo \"building cjs...\" && rm -rf dist && npx tsc -p ./tsconfig.cjs.build.json && echo \"building esm...\" && npx tsc -p ./tsconfig.esm.build.json",
33
- "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",
32
+ "build:test-app": "rm -rf dist && echo \"building test app to esm...\" && npx tsc -p ./tsconfig.esm.build.test-app.json && echo \"building test app to cjs...\" && npx tsc -p ./tsconfig.cjs.build.test-app.json",
34
33
  "dev": "PSYCHIC_CORE_DEVELOPMENT=1 NODE_ENV=development tsx ./test-app/main.ts",
35
34
  "console": "PSYCHIC_CORE_DEVELOPMENT=1 tsx ./test-app/src/conf/repl.ts",
36
35
  "uspec": "PSYCHIC_CORE_DEVELOPMENT=1 vitest --config ./spec/unit/vite.config.ts",
@@ -63,7 +62,7 @@
63
62
  "devDependencies": {
64
63
  "@eslint/js": "^9.19.0",
65
64
  "@jest-mock/express": "^3.0.0",
66
- "@rvoh/dream": "^0.31.3",
65
+ "@rvoh/dream": "^0.32.3",
67
66
  "@rvoh/dream-spec-helpers": "=0.1.0",
68
67
  "@rvoh/psychic-spec-helpers": "=0.2.0",
69
68
  "@types/express": "^4.17.21",
@@ -1,26 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = sspawn;
4
- exports.ssspawn = ssspawn;
5
- const child_process_1 = require("child_process");
6
- function sspawn(command,
7
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
- opts = {}) {
9
- return new Promise((accept, reject) => {
10
- ssspawn(command, opts).on('close', code => {
11
- if (code !== 0)
12
- reject(new Error(code?.toString()));
13
- accept({});
14
- });
15
- });
16
- }
17
- function ssspawn(command,
18
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
- opts = {}) {
20
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
21
- return (0, child_process_1.spawn)(command, {
22
- stdio: 'inherit',
23
- shell: true,
24
- ...opts,
25
- });
26
- }
@@ -1,22 +0,0 @@
1
- import { spawn } from 'child_process';
2
- export default function sspawn(command,
3
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
- opts = {}) {
5
- return new Promise((accept, reject) => {
6
- ssspawn(command, opts).on('close', code => {
7
- if (code !== 0)
8
- reject(new Error(code?.toString()));
9
- accept({});
10
- });
11
- });
12
- }
13
- export function ssspawn(command,
14
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
- opts = {}) {
16
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
17
- return spawn(command, {
18
- stdio: 'inherit',
19
- shell: true,
20
- ...opts,
21
- });
22
- }
@@ -1,2 +0,0 @@
1
- export default function sspawn(command: string, opts?: any): Promise<unknown>;
2
- export declare function ssspawn(command: string, opts?: any): import("child_process").ChildProcessWithoutNullStreams;