libmodulor 0.28.0 → 0.30.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.
Files changed (189) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +3 -3
  3. package/dist/esm/apps/Helper/src/lib/layers/product.js +1 -1
  4. package/dist/esm/apps/Helper/src/lib/layers/project.js +7 -7
  5. package/dist/esm/apps/Helper/src/lib/layers/target.js +27 -11
  6. package/dist/esm/convention.d.ts +2 -0
  7. package/dist/esm/convention.js +1 -0
  8. package/dist/esm/dt/base/TBase.d.ts +2 -0
  9. package/dist/esm/dt/base/TBase.js +5 -0
  10. package/dist/esm/dt/base/TBoolean.d.ts +2 -0
  11. package/dist/esm/dt/base/TBoolean.js +3 -0
  12. package/dist/esm/dt/base/TInt.d.ts +2 -0
  13. package/dist/esm/dt/base/TInt.js +3 -0
  14. package/dist/esm/dt/base/TNumber.d.ts +2 -0
  15. package/dist/esm/dt/base/TNumber.js +3 -0
  16. package/dist/esm/dt/base/TObject.d.ts +2 -0
  17. package/dist/esm/dt/base/TObject.js +37 -0
  18. package/dist/esm/dt/final/TApiKey.d.ts +2 -0
  19. package/dist/esm/dt/final/TApiKey.js +3 -0
  20. package/dist/esm/dt/final/TDateISO8601.d.ts +2 -0
  21. package/dist/esm/dt/final/TDateISO8601.js +3 -0
  22. package/dist/esm/dt/final/TDomainName.d.ts +2 -0
  23. package/dist/esm/dt/final/TDomainName.js +3 -0
  24. package/dist/esm/dt/final/TEmail.d.ts +2 -0
  25. package/dist/esm/dt/final/TEmail.js +3 -0
  26. package/dist/esm/dt/final/TEncryptionKey.d.ts +2 -0
  27. package/dist/esm/dt/final/TEncryptionKey.js +3 -0
  28. package/dist/esm/dt/final/TFile.d.ts +2 -0
  29. package/dist/esm/dt/final/TFile.js +3 -0
  30. package/dist/esm/dt/final/TIPv4.d.ts +2 -0
  31. package/dist/esm/dt/final/TIPv4.js +3 -0
  32. package/dist/esm/dt/final/TIPv6.d.ts +2 -0
  33. package/dist/esm/dt/final/TIPv6.js +3 -0
  34. package/dist/esm/dt/final/TJWT.d.ts +2 -0
  35. package/dist/esm/dt/final/TJWT.js +3 -0
  36. package/dist/esm/dt/final/TPassword.d.ts +2 -0
  37. package/dist/esm/dt/final/TPassword.js +3 -0
  38. package/dist/esm/dt/final/TSSHPrivateKey.d.ts +2 -0
  39. package/dist/esm/dt/final/TSSHPrivateKey.js +3 -0
  40. package/dist/esm/dt/final/TTime.d.ts +2 -0
  41. package/dist/esm/dt/final/TTime.js +3 -0
  42. package/dist/esm/dt/final/TURL.d.ts +2 -0
  43. package/dist/esm/dt/final/TURL.js +3 -0
  44. package/dist/esm/dt/index.d.ts +1 -0
  45. package/dist/esm/dt/targets/json-schema.d.ts +36 -0
  46. package/dist/esm/error/funcs.d.ts +4 -0
  47. package/dist/esm/error/funcs.js +5 -1
  48. package/dist/esm/error/index.d.ts +1 -1
  49. package/dist/esm/error/index.js +1 -1
  50. package/dist/esm/i18n/locales/de.js +2 -0
  51. package/dist/esm/i18n/locales/en.js +2 -0
  52. package/dist/esm/i18n/locales/es.js +2 -0
  53. package/dist/esm/i18n/locales/fr.js +2 -0
  54. package/dist/esm/i18n/types.d.ts +1 -1
  55. package/dist/esm/index.d.ts +3 -0
  56. package/dist/esm/index.js +3 -0
  57. package/dist/esm/index.node-express.d.ts +2 -0
  58. package/dist/esm/index.node-express.js +1 -0
  59. package/dist/esm/index.node-hono.d.ts +2 -0
  60. package/dist/esm/index.node-hono.js +1 -0
  61. package/dist/esm/index.node-mcp-express.d.ts +3 -0
  62. package/dist/esm/index.node-mcp-express.js +2 -0
  63. package/dist/esm/index.node-mcp-hono.d.ts +3 -0
  64. package/dist/esm/index.node-mcp-hono.js +2 -0
  65. package/dist/esm/index.node-mcp.d.ts +3 -1
  66. package/dist/esm/index.node-mcp.js +3 -1
  67. package/dist/esm/product/manifest.d.ts +2 -0
  68. package/dist/esm/products/Helper/i18n.d.ts +2 -0
  69. package/dist/esm/std/impl/SimpleMapI18nManager.d.ts +1 -1
  70. package/dist/esm/std/impl/SimpleMapI18nManager.js +4 -2
  71. package/dist/esm/std/lib/settings.js +4 -5
  72. package/dist/esm/target/edge-worker-hono-server/SyncEdgeWorkerHonoServerManager.d.ts +8 -2
  73. package/dist/esm/target/edge-worker-hono-server/SyncEdgeWorkerHonoServerManager.js +20 -9
  74. package/dist/esm/target/index.d.ts +2 -1
  75. package/dist/esm/target/index.js +1 -1
  76. package/dist/esm/target/lib/client/AuthDataStore.d.ts +5 -0
  77. package/dist/esm/target/lib/client/AuthDataStore.js +1 -0
  78. package/dist/esm/target/lib/client/impl/InMemoryAuthDataStore.d.ts +7 -0
  79. package/dist/esm/target/lib/client/impl/InMemoryAuthDataStore.js +20 -0
  80. package/dist/esm/target/lib/client/impl/MixedServerClientManager.d.ts +15 -0
  81. package/dist/esm/target/lib/client/impl/MixedServerClientManager.js +44 -0
  82. package/dist/esm/target/lib/json-schema/error.d.ts +3 -0
  83. package/dist/esm/target/lib/json-schema/error.js +14 -0
  84. package/dist/esm/target/lib/json-schema/input.d.ts +16 -0
  85. package/dist/esm/target/lib/json-schema/input.js +67 -0
  86. package/dist/esm/target/lib/json-schema/output.d.ts +19 -0
  87. package/dist/esm/target/lib/json-schema/output.js +128 -0
  88. package/dist/esm/target/lib/manifest.d.ts +32 -1
  89. package/dist/esm/target/lib/manifest.js +22 -1
  90. package/dist/esm/target/lib/mcp-server/MCPServerRequestHandler.d.ts +16 -0
  91. package/dist/esm/target/lib/mcp-server/MCPServerRequestHandler.js +54 -0
  92. package/dist/esm/target/lib/mcp-server/consts.d.ts +1 -0
  93. package/dist/esm/target/lib/mcp-server/consts.js +1 -0
  94. package/dist/esm/target/lib/mcp-server/funcs.d.ts +13 -0
  95. package/dist/esm/target/lib/mcp-server/funcs.js +84 -0
  96. package/dist/esm/target/lib/mcp-server/http/MCPHTTPRequestHandlerBuilder.d.ts +14 -0
  97. package/dist/esm/target/lib/mcp-server/http/MCPHTTPRequestHandlerBuilder.js +1 -0
  98. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressFakeRequestHandlerBuilder.d.ts +5 -0
  99. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressFakeRequestHandlerBuilder.js +18 -0
  100. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressProtocolRequestHandlerBuilder.d.ts +15 -0
  101. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressProtocolRequestHandlerBuilder.js +88 -0
  102. package/dist/esm/target/lib/mcp-server/http/express/types.d.ts +3 -0
  103. package/dist/esm/target/lib/mcp-server/http/express/types.js +1 -0
  104. package/dist/esm/target/lib/mcp-server/http/funcs.d.ts +6 -0
  105. package/dist/esm/target/lib/mcp-server/http/funcs.js +50 -0
  106. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoFakeRequestHandlerBuilder.d.ts +5 -0
  107. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoFakeRequestHandlerBuilder.js +18 -0
  108. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoProtocolRequestHandlerBuilder.d.ts +15 -0
  109. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoProtocolRequestHandlerBuilder.js +88 -0
  110. package/dist/esm/target/lib/mcp-server/http/hono/types.d.ts +3 -0
  111. package/dist/esm/target/lib/mcp-server/http/hono/types.js +1 -0
  112. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioRequestHandler.d.ts +31 -0
  113. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioRequestHandler.js +108 -0
  114. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioUCClientConfirmManager.d.ts +7 -0
  115. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioUCClientConfirmManager.js +36 -0
  116. package/dist/esm/target/lib/mcp-server/stdio/consts.d.ts +2 -0
  117. package/dist/esm/target/lib/mcp-server/stdio/consts.js +3 -0
  118. package/dist/esm/target/lib/mcp-server/stdio/funcs.d.ts +2 -0
  119. package/dist/esm/target/lib/mcp-server/stdio/funcs.js +10 -0
  120. package/dist/esm/target/lib/mcp-server/stdio/input.d.ts +10 -0
  121. package/dist/esm/target/lib/mcp-server/stdio/input.js +15 -0
  122. package/dist/esm/target/lib/mcp-server/types.d.ts +2 -0
  123. package/dist/esm/target/lib/mcp-server/types.js +1 -0
  124. package/dist/esm/target/lib/openapi/OpenAPISpecBuilder.d.ts +25 -0
  125. package/dist/esm/target/lib/openapi/OpenAPISpecBuilder.js +135 -0
  126. package/dist/esm/target/lib/openapi/funcs.d.ts +11 -0
  127. package/dist/esm/target/lib/openapi/funcs.js +148 -0
  128. package/dist/esm/target/lib/openapi/types.d.ts +98 -0
  129. package/dist/esm/target/lib/openapi/types.js +1 -0
  130. package/dist/esm/target/lib/rn/input.d.ts +3 -0
  131. package/dist/esm/target/lib/server/AuthCookieCreator.d.ts +2 -1
  132. package/dist/esm/target/lib/server/ServerBooter.d.ts +4 -2
  133. package/dist/esm/target/lib/server/ServerBooter.js +44 -11
  134. package/dist/esm/target/lib/server/ServerManager.d.ts +29 -9
  135. package/dist/esm/target/lib/server/ServerRequestHandler.d.ts +10 -6
  136. package/dist/esm/target/lib/server/ServerRequestHandler.js +35 -25
  137. package/dist/esm/target/lib/server/consts.d.ts +4 -0
  138. package/dist/esm/target/lib/server/consts.js +26 -0
  139. package/dist/esm/target/lib/server-express/CORSMiddlewareBuilder.d.ts +15 -0
  140. package/dist/esm/target/lib/server-express/CORSMiddlewareBuilder.js +55 -0
  141. package/dist/esm/target/lib/server-express/funcs.d.ts +2 -1
  142. package/dist/esm/target/lib/server-express/funcs.js +6 -5
  143. package/dist/esm/target/lib/server-hono/CORSMiddlewareBuilder.d.ts +14 -0
  144. package/dist/esm/target/lib/server-hono/CORSMiddlewareBuilder.js +46 -0
  145. package/dist/esm/target/lib/server-hono/funcs.d.ts +2 -1
  146. package/dist/esm/target/lib/server-hono/funcs.js +6 -3
  147. package/dist/esm/target/lib/shared.d.ts +5 -0
  148. package/dist/esm/target/lib/shared.js +3 -1
  149. package/dist/esm/target/nextjs-server/NextJSServerManager.d.ts +5 -1
  150. package/dist/esm/target/nextjs-server/NextJSServerManager.js +6 -0
  151. package/dist/esm/target/node-express-server/NodeExpressServerManager.d.ts +12 -4
  152. package/dist/esm/target/node-express-server/NodeExpressServerManager.js +34 -15
  153. package/dist/esm/target/node-hono-server/NodeHonoServerManager.d.ts +11 -3
  154. package/dist/esm/target/node-hono-server/NodeHonoServerManager.js +31 -12
  155. package/dist/esm/target/{node-mcp-server/NodeLocalStdioMCPServerManager.d.ts → node-mcp-server-stdio/NodeMCPStdioServerManager.d.ts} +12 -21
  156. package/dist/esm/target/node-mcp-server-stdio/NodeMCPStdioServerManager.js +108 -0
  157. package/dist/esm/testing/impl/newNodeAppTester.js +5 -0
  158. package/dist/esm/uc/UC.d.ts +2 -0
  159. package/dist/esm/uc/UC.js +16 -1
  160. package/dist/esm/uc/cardinality.d.ts +7 -0
  161. package/dist/esm/uc/cardinality.js +14 -0
  162. package/dist/esm/uc/examples.d.ts +2 -0
  163. package/dist/esm/uc/examples.js +12 -0
  164. package/dist/esm/uc/helpers/UCOutputReader.d.ts +2 -2
  165. package/dist/esm/uc/helpers/UCOutputReader.js +2 -2
  166. package/dist/esm/uc/index.d.ts +2 -0
  167. package/dist/esm/uc/index.js +2 -0
  168. package/dist/esm/uc/input-field.d.ts +3 -6
  169. package/dist/esm/uc/input-field.js +5 -21
  170. package/dist/esm/uc/metadata.d.ts +7 -0
  171. package/dist/esm/uc/metadata.js +10 -0
  172. package/dist/esm/uc/opi.d.ts +3 -1
  173. package/dist/esm/uc/opi.js +4 -1
  174. package/dist/esm/uc/output-field.d.ts +14 -1
  175. package/dist/esm/uc/output-field.js +11 -1
  176. package/dist/esm/uc/utils/ucHTTPContract.js +1 -1
  177. package/dist/esm/utils/bundling/funcs.js +1 -1
  178. package/dist/esm/utils/bundling/vite/plugin.d.ts +1 -1
  179. package/dist/esm/utils/http/types.d.ts +5 -0
  180. package/dist/esm/utils/index.d.ts +2 -1
  181. package/dist/esm/utils/index.js +1 -0
  182. package/dist/esm/utils/streams/funcs.d.ts +2 -0
  183. package/dist/esm/utils/streams/funcs.js +10 -0
  184. package/package.json +25 -14
  185. package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.js +0 -183
  186. package/dist/esm/target/node-mcp-server/funcs.d.ts +0 -7
  187. package/dist/esm/target/node-mcp-server/funcs.js +0 -45
  188. package/dist/esm/target/node-mcp-server/types.d.ts +0 -19
  189. /package/dist/esm/{target/node-mcp-server/types.js → dt/targets/json-schema.js} +0 -0
@@ -0,0 +1,135 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { inject, injectable } from 'inversify';
14
+ import { WordingManager } from '../../../i18n/index.js';
15
+ import { formatFQUCInputName, formatFQUCName, ucHTTPContract, } from '../../../uc/index.js';
16
+ import { serverErrorJsonSchema } from '../json-schema/error.js';
17
+ import { ucInputJsonSchema } from '../json-schema/input.js';
18
+ import { DEFAULT_VERSION } from '../shared.js';
19
+ import { openAPIErrors, openAPIParameters, openAPIRequestBody, openAPISecurity, openAPISecuritySchemes, openAPISuccess, } from './funcs.js';
20
+ let OpenAPISpecBuilder = class OpenAPISpecBuilder {
21
+ i18nManager;
22
+ productManifest;
23
+ settingsManager;
24
+ wordingManager;
25
+ constructor(i18nManager, productManifest, settingsManager, wordingManager) {
26
+ this.i18nManager = i18nManager;
27
+ this.productManifest = productManifest;
28
+ this.settingsManager = settingsManager;
29
+ this.wordingManager = wordingManager;
30
+ }
31
+ s() {
32
+ return {
33
+ server_cookies_name_auth: this.settingsManager.get()('server_cookies_name_auth'),
34
+ server_public_api_key_header_name: this.settingsManager.get()('server_public_api_key_header_name'),
35
+ server_public_url: this.settingsManager.get()('server_public_url'),
36
+ };
37
+ }
38
+ async exec({ ucs }) {
39
+ const output = this.initOutput();
40
+ const errors = this.initErrors();
41
+ const { desc, slogan } = this.wordingManager.p();
42
+ if (desc) {
43
+ output.spec.info.description = desc;
44
+ }
45
+ if (slogan) {
46
+ output.spec.info.summary = slogan;
47
+ }
48
+ for (const uc of ucs) {
49
+ const { method, path, pathAliases, envelope } = ucHTTPContract(uc);
50
+ const httpMethod = method.toLowerCase();
51
+ const fqUCName = formatFQUCName(uc.appManifest.name, uc.def.metadata.name);
52
+ const fqUCInputName = formatFQUCInputName(fqUCName);
53
+ output.spec.components.schemas[fqUCInputName] =
54
+ ucInputJsonSchema(uc);
55
+ for (const p of [path, ...pathAliases]) {
56
+ output.spec.paths[p] = {
57
+ ...output.spec.paths[p],
58
+ [httpMethod]: this.initPath(errors, uc, envelope, fqUCInputName),
59
+ };
60
+ }
61
+ }
62
+ return output;
63
+ }
64
+ initErrors() {
65
+ const errors = openAPIErrors();
66
+ for (const error of Object.values(errors)) {
67
+ error.description = this.i18nManager.t(error.description);
68
+ }
69
+ return errors;
70
+ }
71
+ initOutput() {
72
+ return {
73
+ spec: {
74
+ components: {
75
+ schemas: {
76
+ Error: serverErrorJsonSchema(),
77
+ },
78
+ securitySchemes: openAPISecuritySchemes(this.s().server_cookies_name_auth, this.s().server_public_api_key_header_name),
79
+ },
80
+ info: {
81
+ title: this.productManifest.name,
82
+ version: this.productManifest.version ?? DEFAULT_VERSION,
83
+ },
84
+ openapi: '3.1.0',
85
+ paths: {},
86
+ servers: [
87
+ {
88
+ url: this.s().server_public_url,
89
+ },
90
+ ],
91
+ },
92
+ };
93
+ }
94
+ initPath(errors,
95
+ // biome-ignore lint/suspicious/noExplicitAny: can be anything
96
+ uc, envelope, fqUCInputName) {
97
+ const { desc, label } = this.wordingManager.uc(uc.def);
98
+ const res_200 = this.i18nManager.t('res_200');
99
+ const res_204 = this.i18nManager.t('res_204');
100
+ const path = {
101
+ responses: {
102
+ ...openAPISuccess(uc, { 200: res_200, 204: res_204 }),
103
+ ...errors,
104
+ // TODO : Infer errors that can be sent within ServerMain
105
+ },
106
+ security: openAPISecurity(uc.def.sec),
107
+ summary: label,
108
+ tags: [uc.appManifest.name],
109
+ };
110
+ if (desc) {
111
+ path.description = desc;
112
+ }
113
+ switch (envelope) {
114
+ case 'form-data':
115
+ case 'json':
116
+ path.requestBody = openAPIRequestBody(uc, envelope, fqUCInputName);
117
+ break;
118
+ case 'query-params':
119
+ path.parameters = openAPIParameters(uc, envelope);
120
+ break;
121
+ default:
122
+ envelope;
123
+ }
124
+ return path;
125
+ }
126
+ };
127
+ OpenAPISpecBuilder = __decorate([
128
+ injectable(),
129
+ __param(0, inject('I18nManager')),
130
+ __param(1, inject('ProductManifest')),
131
+ __param(2, inject('SettingsManager')),
132
+ __param(3, inject(WordingManager)),
133
+ __metadata("design:paramtypes", [Object, Object, Object, WordingManager])
134
+ ], OpenAPISpecBuilder);
135
+ export { OpenAPISpecBuilder };
@@ -0,0 +1,11 @@
1
+ import type { HTTPStatusNumber } from '../../../dt/index.js';
2
+ import { type FQUCInputName, type UC, type UCInput, type UCOPIBase, type UCSec } from '../../../uc/index.js';
3
+ import { type HTTPDataEnvelope } from '../../../utils/index.js';
4
+ import { type AuthCookieName, type PublicApiKeyHeaderName } from '../shared.js';
5
+ import type { OpenAPIParameter, OpenAPIRequestBody, OpenAPIResponses, OpenAPISecurity, OpenAPISecuritySchemes } from './types.js';
6
+ export declare function openAPIErrors(): OpenAPIResponses;
7
+ export declare function openAPIParameters<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>, envelope: Extract<HTTPDataEnvelope, 'query-params'>): OpenAPIParameter[];
8
+ export declare function openAPIRequestBody<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>, envelope: Extract<HTTPDataEnvelope, 'form-data' | 'json'>, fqUCInputName: FQUCInputName): OpenAPIRequestBody;
9
+ export declare function openAPISecuritySchemes(authCookieName: AuthCookieName, publicApiKeyHeaderName: PublicApiKeyHeaderName): OpenAPISecuritySchemes;
10
+ export declare function openAPISecurity(sec: UCSec | undefined): OpenAPISecurity;
11
+ export declare function openAPISuccess<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>, descriptions: Record<Extract<HTTPStatusNumber, 200 | 204>, string>): OpenAPIResponses;
@@ -0,0 +1,148 @@
1
+ import { ERROR_HTTP_STATUS_MAP } from '../../../error/index.js';
2
+ import { DEFAULT_UC_SEC_AT, DEFAULT_UC_SEC_PAKCT, } from '../../../uc/index.js';
3
+ import { isBlank } from '../../../utils/index.js';
4
+ import { serverErrorJsonSchema } from '../json-schema/error.js';
5
+ import { ucifJsonSchemaDef } from '../json-schema/input.js';
6
+ import { ucOutputJsonSchema } from '../json-schema/output.js';
7
+ import { AUTHORIZATION_HEADER_NAME, } from '../shared.js';
8
+ export function openAPIErrors() {
9
+ return ERROR_HTTP_STATUS_MAP.entries().reduce((acc, cur) => {
10
+ const [status, clazz] = cur;
11
+ const message = new clazz().message;
12
+ acc[status] = {
13
+ content: {
14
+ 'application/json': {
15
+ schema: serverErrorJsonSchema(message),
16
+ },
17
+ },
18
+ description: message,
19
+ };
20
+ return acc;
21
+ }, {});
22
+ }
23
+ export function openAPIParameters(uc, envelope) {
24
+ const res = [];
25
+ switch (envelope) {
26
+ case 'query-params':
27
+ {
28
+ for (const f of uc.inputFields) {
29
+ const { key } = f;
30
+ const { internal, spec } = ucifJsonSchemaDef(f);
31
+ if (!spec) {
32
+ continue;
33
+ }
34
+ res.push({
35
+ in: 'query',
36
+ name: key,
37
+ required: internal?.required ?? false,
38
+ schema: spec,
39
+ });
40
+ }
41
+ }
42
+ break;
43
+ default:
44
+ envelope;
45
+ }
46
+ return res;
47
+ }
48
+ export function openAPIRequestBody(uc, envelope, fqUCInputName) {
49
+ const innerContent = {
50
+ schema: {
51
+ $ref: `#/components/schemas/${fqUCInputName}`,
52
+ },
53
+ };
54
+ switch (envelope) {
55
+ case 'form-data': {
56
+ const repeatableFields = uc.inputFieldsRepeatable();
57
+ const content = {
58
+ 'multipart/form-data': innerContent,
59
+ };
60
+ if (!isBlank(repeatableFields)) {
61
+ content['multipart/form-data'].encoding = {};
62
+ }
63
+ for (const f of repeatableFields) {
64
+ // This is to prevent SwaggerUI from sending the values comma separated
65
+ // biome-ignore lint/style/noNonNullAssertion: we want it
66
+ content['multipart/form-data'].encoding[f.key] = {
67
+ explode: true,
68
+ style: 'form',
69
+ };
70
+ }
71
+ return {
72
+ content,
73
+ required: true,
74
+ };
75
+ }
76
+ case 'json':
77
+ return {
78
+ content: {
79
+ 'application/json': innerContent,
80
+ },
81
+ required: true,
82
+ };
83
+ default:
84
+ envelope;
85
+ throw new Error();
86
+ }
87
+ }
88
+ export function openAPISecuritySchemes(authCookieName, publicApiKeyHeaderName) {
89
+ return {
90
+ apiKey: {
91
+ bearerFormat: 'Bearer',
92
+ in: 'header',
93
+ name: AUTHORIZATION_HEADER_NAME,
94
+ type: 'apiKey',
95
+ },
96
+ basic: {
97
+ scheme: 'basic',
98
+ type: 'http',
99
+ },
100
+ jwt: {
101
+ in: 'cookie',
102
+ name: authCookieName,
103
+ type: 'apiKey',
104
+ },
105
+ publicApiKey: {
106
+ in: 'header',
107
+ name: publicApiKeyHeaderName,
108
+ type: 'apiKey',
109
+ },
110
+ };
111
+ }
112
+ export function openAPISecurity(sec) {
113
+ const item = {};
114
+ const res = [item];
115
+ const publicApiCheckType = sec?.publicApiKeyCheckType ?? DEFAULT_UC_SEC_PAKCT;
116
+ switch (publicApiCheckType) {
117
+ case 'off':
118
+ break;
119
+ case 'on':
120
+ item.publicApiKey = [];
121
+ break;
122
+ default:
123
+ publicApiCheckType;
124
+ }
125
+ const authType = sec?.authType ?? DEFAULT_UC_SEC_AT;
126
+ item[authType] = [];
127
+ return res;
128
+ }
129
+ export function openAPISuccess(uc, descriptions) {
130
+ const schema = ucOutputJsonSchema(uc);
131
+ if (!schema) {
132
+ return {
133
+ '204': {
134
+ description: descriptions[204],
135
+ },
136
+ };
137
+ }
138
+ return {
139
+ '200': {
140
+ content: {
141
+ 'application/json': {
142
+ schema,
143
+ },
144
+ },
145
+ description: descriptions[200],
146
+ },
147
+ };
148
+ }
@@ -0,0 +1,98 @@
1
+ import type { FreeTextLong, FreeTextShort, HTTPMethod, HTTPStatusNumber, JSONSchemaObject, JSONSchemaProperty, SemVerVersion, URL } from '../../../dt/index.js';
2
+ import type { ProductName } from '../../../product/index.js';
3
+ import type { FQUCInputName, FQUCOPI0Name, FQUCOPI1Name, UCFieldKey } from '../../../uc/index.js';
4
+ import type { AUTHORIZATION_HEADER_NAME, AuthCookieName, PublicApiKeyHeaderName } from '../shared.js';
5
+ export type OpenAPIPathName = string;
6
+ export type OpenAPIDescription = FreeTextLong;
7
+ export type OpenAPISchemaName = FQUCInputName | FQUCOPI0Name | FQUCOPI1Name | `Error`;
8
+ export type OpenAPISchemaRef = `#/components/schemas/${OpenAPISchemaName}`;
9
+ export type OpenAPISummary = FreeTextShort;
10
+ export type OpenAPISecurityItem = Partial<Record<keyof OpenAPISecuritySchemes, []>>;
11
+ export type OpenAPISecurity = OpenAPISecurityItem[];
12
+ export interface OpenAPISecurityScheme {
13
+ description?: OpenAPIDescription;
14
+ }
15
+ export interface OpenAPISecuritySchemes {
16
+ apiKey?: OpenAPISecurityScheme & {
17
+ bearerFormat: 'Bearer';
18
+ in: 'header';
19
+ name: typeof AUTHORIZATION_HEADER_NAME;
20
+ type: 'apiKey';
21
+ };
22
+ basic?: OpenAPISecurityScheme & {
23
+ scheme: 'basic';
24
+ type: 'http';
25
+ };
26
+ jwt?: OpenAPISecurityScheme & {
27
+ in: 'cookie';
28
+ name: AuthCookieName;
29
+ type: 'apiKey';
30
+ };
31
+ publicApiKey?: OpenAPISecurityScheme & {
32
+ in: 'header';
33
+ name: PublicApiKeyHeaderName;
34
+ type: 'apiKey';
35
+ };
36
+ }
37
+ export interface OpenAPIComponents {
38
+ securitySchemes: OpenAPISecuritySchemes;
39
+ schemas: Record<OpenAPISchemaName, JSONSchemaObject<any>>;
40
+ }
41
+ export interface OpenAPIParameter {
42
+ description?: OpenAPIDescription;
43
+ in: 'path' | 'query';
44
+ name: UCFieldKey;
45
+ required: boolean;
46
+ schema: JSONSchemaProperty<any>;
47
+ }
48
+ export interface OpenAPIPath {
49
+ description?: OpenAPIDescription;
50
+ parameters?: OpenAPIParameter[];
51
+ requestBody?: OpenAPIRequestBody;
52
+ responses: OpenAPIResponses;
53
+ security?: OpenAPISecurity;
54
+ summary?: OpenAPISummary;
55
+ tags?: string[];
56
+ }
57
+ export interface OpenAPIInnerContent {
58
+ schema: {
59
+ $ref: OpenAPISchemaRef;
60
+ } | JSONSchemaObject<any>;
61
+ }
62
+ export type OpenAPIContent = {
63
+ 'application/json': OpenAPIInnerContent;
64
+ } | {
65
+ 'multipart/form-data': OpenAPIInnerContent & {
66
+ encoding?: Record<UCFieldKey, {
67
+ style: 'form';
68
+ explode: boolean;
69
+ }>;
70
+ };
71
+ };
72
+ export interface OpenAPIRequestBody {
73
+ content: OpenAPIContent;
74
+ description?: OpenAPIDescription;
75
+ required: boolean;
76
+ }
77
+ export type OpenAPIPaths = Record<OpenAPIPathName, Partial<Record<Lowercase<HTTPMethod>, OpenAPIPath>>>;
78
+ export interface OpenAPIResponse {
79
+ content?: OpenAPIContent;
80
+ description: OpenAPIDescription;
81
+ }
82
+ export type OpenAPIResponses = Partial<Record<HTTPStatusNumber, OpenAPIResponse>>;
83
+ export interface OpenAPIServer {
84
+ description?: OpenAPIDescription;
85
+ url: URL;
86
+ }
87
+ export interface OpenAPISpec {
88
+ components: OpenAPIComponents;
89
+ info: {
90
+ description?: OpenAPIDescription;
91
+ title: ProductName;
92
+ summary?: OpenAPISummary;
93
+ version: SemVerVersion;
94
+ };
95
+ openapi: '3.1.0';
96
+ paths: OpenAPIPaths;
97
+ servers: OpenAPIServer[];
98
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -2,6 +2,9 @@ import type { TextInputProps } from 'react-native';
2
2
  import { type DataType, type ErrorMessage } from '../../../dt/index.js';
3
3
  import { type UCInputField } from '../../../uc/index.js';
4
4
  export interface RNInputDef {
5
+ /**
6
+ * Internal types that are not part of the spec
7
+ */
5
8
  internal?: undefined;
6
9
  /**
7
10
  * Fields that are part of {@link TextInputProps}
@@ -1,10 +1,11 @@
1
1
  import type { JWT, Timestamp } from '../../../dt/index.js';
2
2
  import type { JWTManager, SettingsManager, Worker } from '../../../std/index.js';
3
+ import type { HTTPCookieSameSite } from '../../../utils/index.js';
3
4
  import type { ServerManagerSettings } from '../../lib/server/ServerManager.js';
4
5
  export interface CookieOpts {
5
6
  expires: Date;
6
7
  httpOnly: boolean;
7
- sameSite: 'strict';
8
+ sameSite: HTTPCookieSameSite;
8
9
  secure: boolean;
9
10
  signed: boolean;
10
11
  }
@@ -2,9 +2,10 @@ import { ProductUCsLoader } from '../../../product/index.js';
2
2
  import type { Configurable, EmailManager, FSManager, I18nManager, JobManager, Logger, SettingsManager, Worker } from '../../../std/index.js';
3
3
  import { type UCManager } from '../../../uc/index.js';
4
4
  import type { TargetEntrypointInput } from '../entrypoint.js';
5
+ import { OpenAPISpecBuilder } from '../openapi/OpenAPISpecBuilder.js';
5
6
  import { ServerInstaller } from './ServerInstaller.js';
6
7
  import type { ServerManager, ServerManagerSettings } from './ServerManager.js';
7
- type S = Pick<ServerManagerSettings, 'server_static_dir_path' | 'server_tmp_path'>;
8
+ type S = Pick<ServerManagerSettings, 'server_expose_mcp' | 'server_expose_mcp_at' | 'server_expose_openapi_spec' | 'server_expose_openapi_spec_at' | 'server_static_dir_path' | 'server_tmp_path'>;
8
9
  type Input = TargetEntrypointInput & {
9
10
  autoMountUCs?: boolean;
10
11
  };
@@ -13,13 +14,14 @@ export declare class ServerBooter implements Configurable<S>, Worker<Input, Prom
13
14
  private fsManager;
14
15
  private i18nManager;
15
16
  private jobManager;
17
+ private openAPISpecBuilder;
16
18
  private logger;
17
19
  private productUCsLoader;
18
20
  private serverManager;
19
21
  private serverInstaller;
20
22
  private settingsManager;
21
23
  private ucManager;
22
- constructor(emailManager: EmailManager, fsManager: FSManager, i18nManager: I18nManager, jobManager: JobManager, logger: Logger, productUCsLoader: ProductUCsLoader, serverManager: ServerManager, serverInstaller: ServerInstaller, settingsManager: SettingsManager<S>, ucManager: UCManager);
24
+ constructor(emailManager: EmailManager, fsManager: FSManager, i18nManager: I18nManager, jobManager: JobManager, openAPISpecBuilder: OpenAPISpecBuilder, logger: Logger, productUCsLoader: ProductUCsLoader, serverManager: ServerManager, serverInstaller: ServerInstaller, settingsManager: SettingsManager<S>, ucManager: UCManager);
23
25
  s(): S;
24
26
  exec({ appsRootPath, autoMountUCs, srcImporter, }: Input): Promise<void>;
25
27
  private mountUC;
@@ -11,8 +11,9 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
13
  import { inject, injectable } from 'inversify';
14
- import { ProductUCsLoader } from '../../../product/index.js';
14
+ import { ProductUCsLoader, } from '../../../product/index.js';
15
15
  import { ucHTTPContract, } from '../../../uc/index.js';
16
+ import { OpenAPISpecBuilder } from '../openapi/OpenAPISpecBuilder.js';
16
17
  import { shouldMountUC } from './funcs.js';
17
18
  import { ServerInstaller } from './ServerInstaller.js';
18
19
  let ServerBooter = class ServerBooter {
@@ -20,17 +21,19 @@ let ServerBooter = class ServerBooter {
20
21
  fsManager;
21
22
  i18nManager;
22
23
  jobManager;
24
+ openAPISpecBuilder;
23
25
  logger;
24
26
  productUCsLoader;
25
27
  serverManager;
26
28
  serverInstaller;
27
29
  settingsManager;
28
30
  ucManager;
29
- constructor(emailManager, fsManager, i18nManager, jobManager, logger, productUCsLoader, serverManager, serverInstaller, settingsManager, ucManager) {
31
+ constructor(emailManager, fsManager, i18nManager, jobManager, openAPISpecBuilder, logger, productUCsLoader, serverManager, serverInstaller, settingsManager, ucManager) {
30
32
  this.emailManager = emailManager;
31
33
  this.fsManager = fsManager;
32
34
  this.i18nManager = i18nManager;
33
35
  this.jobManager = jobManager;
36
+ this.openAPISpecBuilder = openAPISpecBuilder;
34
37
  this.logger = logger;
35
38
  this.productUCsLoader = productUCsLoader;
36
39
  this.serverManager = serverManager;
@@ -40,6 +43,10 @@ let ServerBooter = class ServerBooter {
40
43
  }
41
44
  s() {
42
45
  return {
46
+ server_expose_mcp: this.settingsManager.get()('server_expose_mcp'),
47
+ server_expose_mcp_at: this.settingsManager.get()('server_expose_mcp_at'),
48
+ server_expose_openapi_spec: this.settingsManager.get()('server_expose_openapi_spec'),
49
+ server_expose_openapi_spec_at: this.settingsManager.get()('server_expose_openapi_spec_at'),
43
50
  server_static_dir_path: this.settingsManager.get()('server_static_dir_path'),
44
51
  server_tmp_path: this.settingsManager.get()('server_tmp_path'),
45
52
  };
@@ -55,13 +62,18 @@ let ServerBooter = class ServerBooter {
55
62
  await this.emailManager.verify();
56
63
  this.logger.info('Initializing server manager');
57
64
  await this.serverManager.init();
65
+ const mountedUCs = [];
58
66
  if (autoMountUCs) {
59
67
  const ucs = await this.productUCsLoader.exec({
60
68
  appsRootPath,
61
69
  srcImporter,
62
70
  });
63
71
  for await (const uc of ucs) {
64
- await this.mountUC(uc);
72
+ const mounted = await this.mountUC(uc);
73
+ if (!mounted) {
74
+ continue;
75
+ }
76
+ mountedUCs.push(uc);
65
77
  }
66
78
  }
67
79
  const staticDirPath = this.s().server_static_dir_path;
@@ -76,6 +88,25 @@ let ServerBooter = class ServerBooter {
76
88
  if (!(await this.fsManager.exists(tmpDirPath))) {
77
89
  await this.fsManager.mkdir(tmpDirPath);
78
90
  }
91
+ if (this.s().server_expose_openapi_spec) {
92
+ const at = this.s().server_expose_openapi_spec_at;
93
+ this.logger.info('Mounting OpenAPI spec', {
94
+ at,
95
+ mountedUCs: mountedUCs.length,
96
+ });
97
+ const { spec } = await this.openAPISpecBuilder.exec({
98
+ ucs: mountedUCs,
99
+ });
100
+ await this.serverManager.mountOpenAPISpec(spec, at);
101
+ }
102
+ if (this.s().server_expose_mcp) {
103
+ const at = this.s().server_expose_mcp_at;
104
+ this.logger.info('Mounting MCP', {
105
+ at,
106
+ mountedUCs: mountedUCs.length,
107
+ });
108
+ await this.serverManager.mountMCP(mountedUCs, at);
109
+ }
79
110
  await this.serverManager.warmUp();
80
111
  await this.serverManager.start();
81
112
  }
@@ -88,7 +119,7 @@ let ServerBooter = class ServerBooter {
88
119
  this.logger.debug(`Not mounting ${mountingPoint}`, {
89
120
  reason: shouldNotMountReason,
90
121
  });
91
- return;
122
+ return false;
92
123
  }
93
124
  this.logger.info(`Mounting ${mountingPoint}`, {
94
125
  contract,
@@ -96,6 +127,7 @@ let ServerBooter = class ServerBooter {
96
127
  });
97
128
  await this.ucManager.initServer(uc);
98
129
  await this.serverManager.mount(uc.appManifest, uc.def, contract);
130
+ return true;
99
131
  }
100
132
  };
101
133
  ServerBooter = __decorate([
@@ -104,12 +136,13 @@ ServerBooter = __decorate([
104
136
  __param(1, inject('FSManager')),
105
137
  __param(2, inject('I18nManager')),
106
138
  __param(3, inject('JobManager')),
107
- __param(4, inject('Logger')),
108
- __param(5, inject(ProductUCsLoader)),
109
- __param(6, inject('ServerManager')),
110
- __param(7, inject(ServerInstaller)),
111
- __param(8, inject('SettingsManager')),
112
- __param(9, inject('UCManager')),
113
- __metadata("design:paramtypes", [Object, Object, Object, Object, Object, ProductUCsLoader, Object, ServerInstaller, Object, Object])
139
+ __param(4, inject(OpenAPISpecBuilder)),
140
+ __param(5, inject('Logger')),
141
+ __param(6, inject(ProductUCsLoader)),
142
+ __param(7, inject('ServerManager')),
143
+ __param(8, inject(ServerInstaller)),
144
+ __param(9, inject('SettingsManager')),
145
+ __param(10, inject('UCManager')),
146
+ __metadata("design:paramtypes", [Object, Object, Object, Object, OpenAPISpecBuilder, Object, ProductUCsLoader, Object, ServerInstaller, Object, Object])
114
147
  ], ServerBooter);
115
148
  export { ServerBooter };
@@ -1,12 +1,12 @@
1
1
  import type { AppManifest } from '../../../app/index.js';
2
- import type { ApiKey, DirPath, FilePath, HostPort, Password, URL, Username } from '../../../dt/index.js';
2
+ import type { ApiKey, DirPath, FilePath, HostPort, HTTPMethod, Password, URL, URLPath, Username } from '../../../dt/index.js';
3
+ import type { ProductUCsLoaderOutput } from '../../../product/index.js';
3
4
  import type { Settings } from '../../../std/index.js';
4
5
  import type { UCDef, UCHTTPContract, UCInput, UCManager, UCOPIBase } from '../../../uc/index.js';
5
- import type { Initializable } from '../../../utils/index.js';
6
+ import type { HTTPCSPValue } from '../../../utils/http/types.js';
7
+ import type { HTTPCookieSameSite, HTTPHeaderName, Initializable } from '../../../utils/index.js';
8
+ import type { OpenAPISpec } from '../openapi/types.js';
6
9
  import type { AuthCookieName, PublicApiKeyHeaderName } from '../shared.js';
7
- export type ServerManagerCSPDefType = 'defaultSrc' | 'imgSrc' | 'scriptSrc';
8
- export type ServerManagerCSPDefValue = URL[];
9
- export type ServerManagerCSPDef = Record<ServerManagerCSPDefType, ServerManagerCSPDefValue>;
10
10
  export interface ServerManagerAuthSettings {
11
11
  server_basic_auth_entries: Record<Username, Password>;
12
12
  server_private_api_key_entries: ApiKey[];
@@ -17,11 +17,21 @@ export interface ServerManagerSettings extends ServerManagerAuthSettings, Settin
17
17
  server_binding_port: HostPort;
18
18
  server_cookies_http_only: boolean;
19
19
  server_cookies_name_auth: AuthCookieName;
20
- server_cookies_same_site: 'strict';
20
+ server_cookies_same_site: HTTPCookieSameSite;
21
21
  server_cookies_secure: boolean;
22
- server_csp_default_src: ServerManagerCSPDefValue;
23
- server_csp_img_src: ServerManagerCSPDefValue;
24
- server_csp_script_src: ServerManagerCSPDefValue;
22
+ server_csp_default_src: HTTPCSPValue;
23
+ server_csp_img_src: HTTPCSPValue;
24
+ server_csp_script_src: HTTPCSPValue;
25
+ server_cors_credentials: boolean;
26
+ server_cors_headers: HTTPHeaderName[];
27
+ server_cors_methods: HTTPMethod[];
28
+ server_cors_origins: URL[];
29
+ server_expose_mcp: boolean;
30
+ server_expose_mcp_at: URLPath;
31
+ server_expose_openapi_spec: boolean;
32
+ server_expose_openapi_spec_at: URLPath;
33
+ server_mcp_dangerously_skip_pub_api_key_check: boolean;
34
+ server_mcp_dangerously_skip_auth_check: boolean;
25
35
  server_public_api_key_header_name: PublicApiKeyHeaderName;
26
36
  server_public_url: URL;
27
37
  server_ssl_fullchain_path: FilePath | null;
@@ -46,6 +56,16 @@ export interface ServerManager extends Initializable {
46
56
  * @param contract
47
57
  */
48
58
  mountSync<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(appManifest: AppManifest, ucd: UCDef<I, OPI0, OPI1>, contract: UCHTTPContract): void;
59
+ /**
60
+ * Mount the MCP endpoint
61
+ * @param spec
62
+ */
63
+ mountMCP(ucs: ProductUCsLoaderOutput, at: URLPath): Promise<void>;
64
+ /**
65
+ * Mount the OpenAPI spec
66
+ * @param spec
67
+ */
68
+ mountOpenAPISpec(spec: OpenAPISpec, at: URLPath): Promise<void>;
49
69
  /**
50
70
  * Mount the static directory at `/`
51
71
  * @param dirPath