@rvoh/psychic 0.24.2 → 0.24.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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Psychic is a typescript first Node framework built on top of [kysely](http://kysely.dev) and heavily inspired by Ruby on Rails. It provides a light-weight routing layer around [expressjs](https://expressjs.com) to create a familiar MVC pattern for those coming from a conventional MVC framework, a type-safe ORM with an incredibly powerful autocomplete API, elegant redis and socket.io bindings for distributed websocket applications, the ability to couple with a front-end framework (like react, angular, etc...) and write specs that drive through your front end, while still maintaining a back end-centric context from which to write specs.
6
6
 
7
- For more comprehensive documentation, please see [The official Psychic guides](https://psychic-docs.netlify.app). We will also be publishing api docs shortly, but the Psychic guides should be comprehensive enough to provide an understanding of the technology and how to use it.
7
+ For more comprehensive documentation, please see [The official Psychic guides](https://psychicframework.com). We will also be publishing api docs shortly, but the Psychic guides should be comprehensive enough to provide an understanding of the technology and how to use it.
8
8
 
9
9
  NOTE: doing so will create the new app in the psychic folder, so once done testing remember to remove it.
10
10
 
@@ -12,7 +12,7 @@ within conf/app.ts, you must have a call to "#set('routes', routesCb)", i.e.
12
12
 
13
13
 
14
14
  // conf/app.ts
15
- import routes from './routes'
15
+ import routes from './routes.js'
16
16
 
17
17
  export default async (app: PsychicApplication) => {
18
18
  await app.set('routes', routes)
@@ -76,9 +76,9 @@ function baseAncestorNameAndImport(controllerNameParts, isAdmin, { forBaseContro
76
76
  const dotFiles = forBaseController ? '..' : '.';
77
77
  return controllerNameParts.length === (isAdmin ? 2 : 1)
78
78
  ? isAdmin
79
- ? [`AdminAuthedController`, `import AdminAuthedController from '${dotFiles}/AuthedController'`]
80
- : [`AuthedController`, `import AuthedController from '${dotFiles}/AuthedController'`]
81
- : [maybeAncestorNameForBase, `import ${maybeAncestorNameForBase} from '${dotFiles}/BaseController'`];
79
+ ? [`AdminAuthedController`, `import AdminAuthedController from '${dotFiles}/AuthedController.js'`]
80
+ : [`AuthedController`, `import AuthedController from '${dotFiles}/AuthedController.js'`]
81
+ : [maybeAncestorNameForBase, `import ${maybeAncestorNameForBase} from '${dotFiles}/BaseController.js'`];
82
82
  }
83
83
  async function generateControllerSpec({ fullyQualifiedControllerName, route, fullyQualifiedModelName, columnsWithTypes, resourceSpecs, }) {
84
84
  const { relFilePath, absDirPath, absFilePath } = (0, psychicFileAndDirPaths_js_1.default)((0, psychicPath_js_1.default)('controllerSpecs'), fullyQualifiedControllerName + `.spec.ts`);
@@ -34,15 +34,11 @@ function generateControllerContent({ ancestorName, ancestorImportStatement, full
34
34
  }`;
35
35
  else
36
36
  return `\
37
- @OpenAPI({
38
- response: {
39
- 200: {
40
- tags: openApiTags,
41
- description: '<tbd>',
42
- // add openapi definition for your custom endpoint
43
- }
44
- }
45
- })
37
+ // @OpenAPI(<model, view model, or serializer>, {
38
+ // status: 201,
39
+ // tags: openApiTags,
40
+ // description: '<tbd>',
41
+ // })
46
42
  public async create() {
47
43
  }`;
48
44
  case 'index':
@@ -61,15 +57,13 @@ function generateControllerContent({ ancestorName, ancestorImportStatement, full
61
57
  }`;
62
58
  else
63
59
  return `\
64
- @OpenAPI({
65
- response: {
66
- 200: {
67
- tags: openApiTags,
68
- description: '<tbd>',
69
- // add openapi definition for your custom endpoint
70
- }
71
- }
72
- })
60
+ // @OpenAPI(<model, view model, or serializer>, {
61
+ // status: 200,
62
+ // tags: openApiTags,
63
+ // description: '<tbd>',
64
+ // many: true,
65
+ // serializerKey: 'summary',
66
+ // })
73
67
  public async index() {
74
68
  }`;
75
69
  case 'show':
@@ -86,15 +80,11 @@ function generateControllerContent({ ancestorName, ancestorImportStatement, full
86
80
  }`;
87
81
  else
88
82
  return `\
89
- @OpenAPI({
90
- response: {
91
- 200: {
92
- tags: openApiTags,
93
- description: '<tbd>',
94
- // add openapi definition for your custom endpoint
95
- }
96
- }
97
- })
83
+ // @OpenAPI(<model, view model, or serializer>, {
84
+ // status: 200,
85
+ // tags: openApiTags,
86
+ // description: '<tbd>',
87
+ // })
98
88
  public async show() {
99
89
  }`;
100
90
  case 'update':
@@ -112,11 +102,11 @@ function generateControllerContent({ ancestorName, ancestorImportStatement, full
112
102
  }`;
113
103
  else
114
104
  return `\
115
- @OpenAPI({
116
- status: 204,
117
- tags: openApiTags,
118
- description: '<tbd>',
119
- })
105
+ // @OpenAPI(<model, view model, or serializer>, {
106
+ // status: 204,
107
+ // tags: openApiTags,
108
+ // description: '<tbd>',
109
+ // })
120
110
  public async update() {
121
111
  }`;
122
112
  case 'destroy':
@@ -134,24 +124,32 @@ function generateControllerContent({ ancestorName, ancestorImportStatement, full
134
124
  }`;
135
125
  else
136
126
  return `\
137
- @OpenAPI({
138
- status: 204,
139
- tags: openApiTags,
140
- description: '<tbd>',
141
- })
127
+ // @OpenAPI({
128
+ // status: 204,
129
+ // tags: openApiTags,
130
+ // description: '<tbd>',
131
+ // })
142
132
  public async destroy() {
143
133
  }`;
144
134
  default:
145
- return `\
146
- @OpenAPI({
147
- response: {
148
- 200: {
149
- tags: openApiTags,
150
- description: '<tbd>',
151
- // add openapi definition for your custom endpoint
152
- }
153
- }
135
+ if (modelAttributeName)
136
+ return `\
137
+ @OpenAPI(${modelClassName}, {
138
+ status: 200,
139
+ tags: openApiTags,
140
+ description: 'Fetch ${aOrAnDreamModelName(modelClassName)}',
154
141
  })
142
+ public async ${methodName}() {
143
+ // const ${modelAttributeName} = await this.${modelAttributeName}()
144
+ // this.ok(${modelAttributeName})
145
+ }`;
146
+ else
147
+ return `\
148
+ // @OpenAPI(<model, view model, or serializer>, {
149
+ // status: 200,
150
+ // tags: openApiTags,
151
+ // description: '<tbd>',
152
+ // })
155
153
  public async ${methodName}() {
156
154
  }`;
157
155
  }
@@ -40,7 +40,7 @@ function generateResourceControllerSpecContent({ fullyQualifiedControllerName, r
40
40
  import { UpdateableProperties } from '@rvoh/dream'
41
41
  import { PsychicServer } from '@rvoh/psychic'
42
42
  import { specRequest as request } from '@rvoh/psychic-spec-helpers'${(0, dream_1.uniq)(importStatements).join('')}
43
- import { addEndUserAuthHeader } from '${specUnitUpdirs}helpers/authentication'
43
+ import { addEndUserAuthHeader } from '${specUnitUpdirs}helpers/authentication.js'
44
44
 
45
45
  describe('${fullyQualifiedControllerName}', () => {
46
46
  let user: User
@@ -5,6 +5,7 @@ exports.rescuableHttpErrorClasses = rescuableHttpErrorClasses;
5
5
  const BadGateway_js_1 = require("../../error/http/BadGateway.js");
6
6
  const BadRequest_js_1 = require("../../error/http/BadRequest.js");
7
7
  const Conflict_js_1 = require("../../error/http/Conflict.js");
8
+ const ContentTooLarge_js_1 = require("../../error/http/ContentTooLarge.js");
8
9
  const ExpectationFailed_js_1 = require("../../error/http/ExpectationFailed.js");
9
10
  const FailedDependency_js_1 = require("../../error/http/FailedDependency.js");
10
11
  const Forbidden_js_1 = require("../../error/http/Forbidden.js");
@@ -20,7 +21,6 @@ const NotAcceptable_js_1 = require("../../error/http/NotAcceptable.js");
20
21
  const NotExtended_js_1 = require("../../error/http/NotExtended.js");
21
22
  const NotFound_js_1 = require("../../error/http/NotFound.js");
22
23
  const NotImplemented_js_1 = require("../../error/http/NotImplemented.js");
23
- const ContentTooLarge_js_1 = require("../../error/http/ContentTooLarge.js");
24
24
  const PaymentRequired_js_1 = require("../../error/http/PaymentRequired.js");
25
25
  const PreconditionFailed_js_1 = require("../../error/http/PreconditionFailed.js");
26
26
  const PreconditionRequired_js_1 = require("../../error/http/PreconditionRequired.js");
@@ -27,11 +27,11 @@ function default_1(originDreamPathType, destinationDreamPathType, fullyQualified
27
27
  case 'db':
28
28
  return destinationPath;
29
29
  case 'factories':
30
- return `${destinationPath}${fullyQualifiedDestinationModelName}Factory`;
30
+ return `${destinationPath}${fullyQualifiedDestinationModelName}Factory.js`;
31
31
  case 'serializers':
32
- return `${destinationPath}${fullyQualifiedDestinationModelName}Serializer`;
32
+ return `${destinationPath}${fullyQualifiedDestinationModelName}Serializer.js`;
33
33
  default:
34
- return `${destinationPath}${fullyQualifiedDestinationModelName}`;
34
+ return `${destinationPath}${fullyQualifiedDestinationModelName}.js`;
35
35
  }
36
36
  }
37
37
  function psychicPathTypeRelativePath(originDreamPathType, destinationDreamPathType) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ParamValidationError = exports.Params = exports.getPsychicHttpInstance = exports.PsychicServer = exports.PsychicRouter = exports.PsychicImporter = exports.PsychicApplication = 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.OpenAPI = exports.BeforeAction = exports.PsychicController = exports.PsychicCLI = exports.PsychicBin = exports.pluralize = void 0;
3
+ exports.ParamValidationError = 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.PsychicCLI = exports.PsychicBin = exports.pluralize = void 0;
4
4
  exports.PsychicSession = void 0;
5
5
  const pluralize_esm_1 = require("pluralize-esm");
6
6
  exports.pluralize = pluralize_esm_1.default;
@@ -8,11 +8,11 @@ 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 index_js_3 = require("./controller/index.js");
12
- Object.defineProperty(exports, "PsychicController", { enumerable: true, get: function () { return index_js_3.default; } });
13
11
  var decorators_js_1 = require("./controller/decorators.js");
14
12
  Object.defineProperty(exports, "BeforeAction", { enumerable: true, get: function () { return decorators_js_1.BeforeAction; } });
15
13
  Object.defineProperty(exports, "OpenAPI", { enumerable: true, get: function () { return decorators_js_1.OpenAPI; } });
14
+ var index_js_3 = require("./controller/index.js");
15
+ Object.defineProperty(exports, "PsychicController", { enumerable: true, get: function () { return index_js_3.default; } });
16
16
  var Loader_js_1 = require("./env/Loader.js");
17
17
  Object.defineProperty(exports, "envLoader", { enumerable: true, get: function () { return Loader_js_1.default; } });
18
18
  var provider_js_1 = require("./i18n/provider.js");
@@ -87,16 +87,16 @@ var pathifyNestedObject_js_1 = require("./helpers/pathifyNestedObject.js");
87
87
  Object.defineProperty(exports, "pathifyNestedObject", { enumerable: true, get: function () { return pathifyNestedObject_js_1.default; } });
88
88
  var endpoint_js_1 = require("./openapi-renderer/endpoint.js");
89
89
  Object.defineProperty(exports, "MissingControllerActionPairingInRoutes", { enumerable: true, get: function () { return endpoint_js_1.MissingControllerActionPairingInRoutes; } });
90
- var index_js_4 = require("./psychic-application/index.js");
91
- Object.defineProperty(exports, "PsychicApplication", { enumerable: true, get: function () { return index_js_4.default; } });
92
90
  var PsychicImporter_js_1 = require("./psychic-application/helpers/PsychicImporter.js");
93
91
  Object.defineProperty(exports, "PsychicImporter", { enumerable: true, get: function () { return PsychicImporter_js_1.default; } });
92
+ var index_js_4 = require("./psychic-application/index.js");
93
+ Object.defineProperty(exports, "PsychicApplication", { enumerable: true, get: function () { return index_js_4.default; } });
94
94
  var index_js_5 = require("./router/index.js");
95
95
  Object.defineProperty(exports, "PsychicRouter", { enumerable: true, get: function () { return index_js_5.default; } });
96
- var index_js_6 = require("./server/index.js");
97
- Object.defineProperty(exports, "PsychicServer", { enumerable: true, get: function () { return index_js_6.default; } });
98
96
  var startPsychicServer_js_1 = require("./server/helpers/startPsychicServer.js");
99
97
  Object.defineProperty(exports, "getPsychicHttpInstance", { enumerable: true, get: function () { return startPsychicServer_js_1.createPsychicHttpInstance; } });
98
+ var index_js_6 = require("./server/index.js");
99
+ Object.defineProperty(exports, "PsychicServer", { enumerable: true, get: function () { return index_js_6.default; } });
100
100
  var params_js_1 = require("./server/params.js");
101
101
  Object.defineProperty(exports, "Params", { enumerable: true, get: function () { return params_js_1.default; } });
102
102
  Object.defineProperty(exports, "ParamValidationError", { enumerable: true, get: function () { return params_js_1.ParamValidationError; } });
@@ -5,10 +5,7 @@ class PsychicImporter {
5
5
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
6
  static async importControllers(controllersPath, importCb) {
7
7
  const controllerPaths = await dream_1.DreamImporter.ls(controllersPath);
8
- const controllerClasses = [];
9
- for (const controllerPath of controllerPaths) {
10
- controllerClasses.push([controllerPath, (await importCb(controllerPath))]);
11
- }
8
+ const controllerClasses = (await Promise.all(controllerPaths.map(controllerPath => importCb(controllerPath).then(dreamClass => [controllerPath, dreamClass]))));
12
9
  return controllerClasses;
13
10
  }
14
11
  }
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ParamValidationError = void 0;
4
4
  const dream_1 = require("@rvoh/dream");
5
- const luxon_1 = require("luxon");
6
5
  const isUuid_js_1 = require("../helpers/isUuid.js");
7
6
  const typechecks_js_1 = require("../helpers/typechecks.js");
8
7
  class Params {
@@ -210,7 +209,7 @@ class Params {
210
209
  case 'date':
211
210
  switch (expectedType) {
212
211
  case 'datetime':
213
- dateClass = luxon_1.DateTime;
212
+ dateClass = dream_1.DateTime;
214
213
  break;
215
214
  case 'date':
216
215
  dateClass = dream_1.CalendarDate;
@@ -221,7 +220,7 @@ class Params {
221
220
  else
222
221
  throw Error(`expectedType is not a string`);
223
222
  }
224
- if ((paramValue instanceof luxon_1.DateTime || paramValue instanceof dream_1.CalendarDate) && paramValue.isValid)
223
+ if ((paramValue instanceof dream_1.DateTime || paramValue instanceof dream_1.CalendarDate) && paramValue.isValid)
225
224
  return paramValue;
226
225
  if (typeof paramValue === 'string') {
227
226
  const dateTime = dateClass.fromISO(paramValue, { zone: 'UTC' });
@@ -10,7 +10,7 @@ within conf/app.ts, you must have a call to "#set('routes', routesCb)", i.e.
10
10
 
11
11
 
12
12
  // conf/app.ts
13
- import routes from './routes'
13
+ import routes from './routes.js'
14
14
 
15
15
  export default async (app: PsychicApplication) => {
16
16
  await app.set('routes', routes)
@@ -73,9 +73,9 @@ function baseAncestorNameAndImport(controllerNameParts, isAdmin, { forBaseContro
73
73
  const dotFiles = forBaseController ? '..' : '.';
74
74
  return controllerNameParts.length === (isAdmin ? 2 : 1)
75
75
  ? isAdmin
76
- ? [`AdminAuthedController`, `import AdminAuthedController from '${dotFiles}/AuthedController'`]
77
- : [`AuthedController`, `import AuthedController from '${dotFiles}/AuthedController'`]
78
- : [maybeAncestorNameForBase, `import ${maybeAncestorNameForBase} from '${dotFiles}/BaseController'`];
76
+ ? [`AdminAuthedController`, `import AdminAuthedController from '${dotFiles}/AuthedController.js'`]
77
+ : [`AuthedController`, `import AuthedController from '${dotFiles}/AuthedController.js'`]
78
+ : [maybeAncestorNameForBase, `import ${maybeAncestorNameForBase} from '${dotFiles}/BaseController.js'`];
79
79
  }
80
80
  async function generateControllerSpec({ fullyQualifiedControllerName, route, fullyQualifiedModelName, columnsWithTypes, resourceSpecs, }) {
81
81
  const { relFilePath, absDirPath, absFilePath } = psychicFileAndDirPaths(psychicPath('controllerSpecs'), fullyQualifiedControllerName + `.spec.ts`);
@@ -31,15 +31,11 @@ export default function generateControllerContent({ ancestorName, ancestorImport
31
31
  }`;
32
32
  else
33
33
  return `\
34
- @OpenAPI({
35
- response: {
36
- 200: {
37
- tags: openApiTags,
38
- description: '<tbd>',
39
- // add openapi definition for your custom endpoint
40
- }
41
- }
42
- })
34
+ // @OpenAPI(<model, view model, or serializer>, {
35
+ // status: 201,
36
+ // tags: openApiTags,
37
+ // description: '<tbd>',
38
+ // })
43
39
  public async create() {
44
40
  }`;
45
41
  case 'index':
@@ -58,15 +54,13 @@ export default function generateControllerContent({ ancestorName, ancestorImport
58
54
  }`;
59
55
  else
60
56
  return `\
61
- @OpenAPI({
62
- response: {
63
- 200: {
64
- tags: openApiTags,
65
- description: '<tbd>',
66
- // add openapi definition for your custom endpoint
67
- }
68
- }
69
- })
57
+ // @OpenAPI(<model, view model, or serializer>, {
58
+ // status: 200,
59
+ // tags: openApiTags,
60
+ // description: '<tbd>',
61
+ // many: true,
62
+ // serializerKey: 'summary',
63
+ // })
70
64
  public async index() {
71
65
  }`;
72
66
  case 'show':
@@ -83,15 +77,11 @@ export default function generateControllerContent({ ancestorName, ancestorImport
83
77
  }`;
84
78
  else
85
79
  return `\
86
- @OpenAPI({
87
- response: {
88
- 200: {
89
- tags: openApiTags,
90
- description: '<tbd>',
91
- // add openapi definition for your custom endpoint
92
- }
93
- }
94
- })
80
+ // @OpenAPI(<model, view model, or serializer>, {
81
+ // status: 200,
82
+ // tags: openApiTags,
83
+ // description: '<tbd>',
84
+ // })
95
85
  public async show() {
96
86
  }`;
97
87
  case 'update':
@@ -109,11 +99,11 @@ export default function generateControllerContent({ ancestorName, ancestorImport
109
99
  }`;
110
100
  else
111
101
  return `\
112
- @OpenAPI({
113
- status: 204,
114
- tags: openApiTags,
115
- description: '<tbd>',
116
- })
102
+ // @OpenAPI(<model, view model, or serializer>, {
103
+ // status: 204,
104
+ // tags: openApiTags,
105
+ // description: '<tbd>',
106
+ // })
117
107
  public async update() {
118
108
  }`;
119
109
  case 'destroy':
@@ -131,24 +121,32 @@ export default function generateControllerContent({ ancestorName, ancestorImport
131
121
  }`;
132
122
  else
133
123
  return `\
134
- @OpenAPI({
135
- status: 204,
136
- tags: openApiTags,
137
- description: '<tbd>',
138
- })
124
+ // @OpenAPI({
125
+ // status: 204,
126
+ // tags: openApiTags,
127
+ // description: '<tbd>',
128
+ // })
139
129
  public async destroy() {
140
130
  }`;
141
131
  default:
142
- return `\
143
- @OpenAPI({
144
- response: {
145
- 200: {
146
- tags: openApiTags,
147
- description: '<tbd>',
148
- // add openapi definition for your custom endpoint
149
- }
150
- }
132
+ if (modelAttributeName)
133
+ return `\
134
+ @OpenAPI(${modelClassName}, {
135
+ status: 200,
136
+ tags: openApiTags,
137
+ description: 'Fetch ${aOrAnDreamModelName(modelClassName)}',
151
138
  })
139
+ public async ${methodName}() {
140
+ // const ${modelAttributeName} = await this.${modelAttributeName}()
141
+ // this.ok(${modelAttributeName})
142
+ }`;
143
+ else
144
+ return `\
145
+ // @OpenAPI(<model, view model, or serializer>, {
146
+ // status: 200,
147
+ // tags: openApiTags,
148
+ // description: '<tbd>',
149
+ // })
152
150
  public async ${methodName}() {
153
151
  }`;
154
152
  }
@@ -37,7 +37,7 @@ export default function generateResourceControllerSpecContent({ fullyQualifiedCo
37
37
  import { UpdateableProperties } from '@rvoh/dream'
38
38
  import { PsychicServer } from '@rvoh/psychic'
39
39
  import { specRequest as request } from '@rvoh/psychic-spec-helpers'${uniq(importStatements).join('')}
40
- import { addEndUserAuthHeader } from '${specUnitUpdirs}helpers/authentication'
40
+ import { addEndUserAuthHeader } from '${specUnitUpdirs}helpers/authentication.js'
41
41
 
42
42
  describe('${fullyQualifiedControllerName}', () => {
43
43
  let user: User
@@ -1,6 +1,7 @@
1
1
  import HttpStatusBadGateway from '../../error/http/BadGateway.js';
2
2
  import HttpStatusBadRequest from '../../error/http/BadRequest.js';
3
3
  import HttpStatusConflict from '../../error/http/Conflict.js';
4
+ import HttpStatusContentTooLarge from '../../error/http/ContentTooLarge.js';
4
5
  import HttpStatusExpectationFailed from '../../error/http/ExpectationFailed.js';
5
6
  import HttpStatusFailedDependency from '../../error/http/FailedDependency.js';
6
7
  import HttpStatusForbidden from '../../error/http/Forbidden.js';
@@ -16,7 +17,6 @@ import HttpStatusNotAcceptable from '../../error/http/NotAcceptable.js';
16
17
  import HttpStatusNotExtended from '../../error/http/NotExtended.js';
17
18
  import HttpStatusNotFound from '../../error/http/NotFound.js';
18
19
  import HttpStatusNotImplemented from '../../error/http/NotImplemented.js';
19
- import HttpStatusContentTooLarge from '../../error/http/ContentTooLarge.js';
20
20
  import HttpStatusPaymentRequired from '../../error/http/PaymentRequired.js';
21
21
  import HttpStatusPreconditionFailed from '../../error/http/PreconditionFailed.js';
22
22
  import HttpStatusPreconditionRequired from '../../error/http/PreconditionRequired.js';
@@ -23,11 +23,11 @@ export default function (originDreamPathType, destinationDreamPathType, fullyQua
23
23
  case 'db':
24
24
  return destinationPath;
25
25
  case 'factories':
26
- return `${destinationPath}${fullyQualifiedDestinationModelName}Factory`;
26
+ return `${destinationPath}${fullyQualifiedDestinationModelName}Factory.js`;
27
27
  case 'serializers':
28
- return `${destinationPath}${fullyQualifiedDestinationModelName}Serializer`;
28
+ return `${destinationPath}${fullyQualifiedDestinationModelName}Serializer.js`;
29
29
  default:
30
- return `${destinationPath}${fullyQualifiedDestinationModelName}`;
30
+ return `${destinationPath}${fullyQualifiedDestinationModelName}.js`;
31
31
  }
32
32
  }
33
33
  export function psychicPathTypeRelativePath(originDreamPathType, destinationDreamPathType) {
@@ -2,8 +2,8 @@ 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 PsychicController, } from './controller/index.js';
6
5
  export { BeforeAction, OpenAPI } from './controller/decorators.js';
6
+ export { default as PsychicController, } from './controller/index.js';
7
7
  export { default as envLoader } from './env/Loader.js';
8
8
  export { default as I18nProvider } from './i18n/provider.js';
9
9
  export { default as HttpStatusBadGateway } from './error/http/BadGateway.js';
@@ -41,10 +41,10 @@ export { default as generateResource } from './generate/resource.js';
41
41
  export { default as cookieMaxAgeFromCookieOpts } from './helpers/cookieMaxAgeFromCookieOpts.js';
42
42
  export { default as pathifyNestedObject } from './helpers/pathifyNestedObject.js';
43
43
  export { MissingControllerActionPairingInRoutes, } from './openapi-renderer/endpoint.js';
44
- export { default as PsychicApplication, } from './psychic-application/index.js';
45
44
  export { default as PsychicImporter } from './psychic-application/helpers/PsychicImporter.js';
45
+ export { default as PsychicApplication, } from './psychic-application/index.js';
46
46
  export { default as PsychicRouter } from './router/index.js';
47
- export { default as PsychicServer } from './server/index.js';
48
47
  export { createPsychicHttpInstance as getPsychicHttpInstance } from './server/helpers/startPsychicServer.js';
48
+ export { default as PsychicServer } from './server/index.js';
49
49
  export { default as Params, ParamValidationError } from './server/params.js';
50
50
  export { default as PsychicSession } from './session/index.js';
@@ -3,10 +3,7 @@ export default class PsychicImporter {
3
3
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
4
  static async importControllers(controllersPath, importCb) {
5
5
  const controllerPaths = await DreamImporter.ls(controllersPath);
6
- const controllerClasses = [];
7
- for (const controllerPath of controllerPaths) {
8
- controllerClasses.push([controllerPath, (await importCb(controllerPath))]);
9
- }
6
+ const controllerClasses = (await Promise.all(controllerPaths.map(controllerPath => importCb(controllerPath).then(dreamClass => [controllerPath, dreamClass]))));
10
7
  return controllerClasses;
11
8
  }
12
9
  }
@@ -1,5 +1,4 @@
1
- import { CalendarDate, camelize, compact, snakeify, } from '@rvoh/dream';
2
- import { DateTime } from 'luxon';
1
+ import { CalendarDate, camelize, compact, DateTime, snakeify, } from '@rvoh/dream';
3
2
  import isUuid from '../helpers/isUuid.js';
4
3
  import { isObject } from '../helpers/typechecks.js';
5
4
  export default class Params {
@@ -11,8 +11,8 @@ 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 PsychicController, type PsychicOpenapiControllerConfig, type PsychicParamsDictionary, type PsychicOpenapiNames, type PsychicParamsPrimitive, } from './controller/index.js';
15
14
  export { BeforeAction, OpenAPI } from './controller/decorators.js';
15
+ export { default as PsychicController, type PsychicOpenapiControllerConfig, type PsychicOpenapiNames, type PsychicParamsDictionary, type PsychicParamsPrimitive, } from './controller/index.js';
16
16
  export { default as envLoader } from './env/Loader.js';
17
17
  export { default as I18nProvider } from './i18n/provider.js';
18
18
  export { default as HttpStatusBadGateway } from './error/http/BadGateway.js';
@@ -49,13 +49,13 @@ export { default as generateController } from './generate/controller.js';
49
49
  export { default as generateResource } from './generate/resource.js';
50
50
  export { default as cookieMaxAgeFromCookieOpts } from './helpers/cookieMaxAgeFromCookieOpts.js';
51
51
  export { default as pathifyNestedObject } from './helpers/pathifyNestedObject.js';
52
- export { MissingControllerActionPairingInRoutes, type OpenapiContent, type OpenapiEndpointRendererOpts, type OpenapiEndpointResponse, type OpenapiHeaderOption, type OpenapiHeaderType, type OpenapiHeaders, type OpenapiMethodBody, type OpenapiParameterResponse, type OpenapiPathParams, type OpenapiQueryOption, type OpenapiResponses, type OpenapiSchema, type OpenapiPathParamOption as OpenapiUriOption, } from './openapi-renderer/endpoint.js';
53
- export { default as PsychicApplication, type DefaultPsychicOpenapiOptions, type NamedPsychicOpenapiOptions, type PsychicApplicationInitOptions, } from './psychic-application/index.js';
52
+ export { MissingControllerActionPairingInRoutes, type OpenapiContent, type OpenapiEndpointRendererOpts, type OpenapiEndpointResponse, type OpenapiHeaderOption, type OpenapiHeaders, type OpenapiHeaderType, type OpenapiMethodBody, type OpenapiParameterResponse, type OpenapiPathParams, type OpenapiQueryOption, type OpenapiResponses, type OpenapiSchema, type OpenapiPathParamOption as OpenapiUriOption, } from './openapi-renderer/endpoint.js';
54
53
  export { default as PsychicImporter } from './psychic-application/helpers/PsychicImporter.js';
54
+ export { default as PsychicApplication, type DefaultPsychicOpenapiOptions, type NamedPsychicOpenapiOptions, type PsychicApplicationInitOptions, } from './psychic-application/index.js';
55
55
  export { type UUID } from './psychic-application/types.js';
56
56
  export { default as PsychicRouter } from './router/index.js';
57
57
  export { type HttpMethod } from './router/types.js';
58
- export { default as PsychicServer } from './server/index.js';
59
58
  export { createPsychicHttpInstance as getPsychicHttpInstance } from './server/helpers/startPsychicServer.js';
59
+ export { default as PsychicServer } from './server/index.js';
60
60
  export { default as Params, ParamValidationError } from './server/params.js';
61
61
  export { default as PsychicSession } from './session/index.js';
@@ -1,5 +1,4 @@
1
- import { CalendarDate, Dream, DreamParamSafeAttributes, DreamParamSafeColumnNames } from '@rvoh/dream';
2
- import { DateTime } from 'luxon';
1
+ import { CalendarDate, DateTime, Dream, DreamParamSafeAttributes, DreamParamSafeColumnNames } from '@rvoh/dream';
3
2
  import { PsychicParamsDictionary, PsychicParamsPrimitive, PsychicParamsPrimitiveLiterals } from '../controller/index.js';
4
3
  export default class Params {
5
4
  /**
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.24.2",
5
+ "version": "0.24.4",
6
6
  "author": "RVOHealth",
7
7
  "repository": "https://github.com/rvohealth/psychic.git",
8
8
  "license": "MIT",
@@ -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.29.1",
64
+ "@rvoh/dream": "^0.29.10",
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",