@pikku/cli 0.6.20 → 0.7.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 (111) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/cli.schema.json +2 -2
  3. package/dist/bin/pikku-all.js +34 -16
  4. package/dist/bin/pikku-channels-map.js +4 -4
  5. package/dist/bin/pikku-channels.js +6 -10
  6. package/dist/bin/pikku-fetch.d.ts +1 -1
  7. package/dist/bin/pikku-fetch.js +3 -3
  8. package/dist/bin/pikku-function-types.js +4 -4
  9. package/dist/bin/pikku-functions.d.ts +5 -0
  10. package/dist/bin/pikku-functions.js +24 -0
  11. package/dist/bin/pikku-http-map.d.ts +5 -0
  12. package/dist/bin/pikku-http-map.js +23 -0
  13. package/dist/bin/pikku-http-routes.d.ts +5 -0
  14. package/dist/bin/pikku-http-routes.js +24 -0
  15. package/dist/bin/pikku-http.js +3 -5
  16. package/dist/bin/pikku-nextjs.d.ts +1 -1
  17. package/dist/bin/pikku-nextjs.js +8 -8
  18. package/dist/bin/pikku-openapi.d.ts +1 -1
  19. package/dist/bin/pikku-openapi.js +6 -6
  20. package/dist/bin/pikku-routes-map.d.ts +1 -1
  21. package/dist/bin/pikku-routes-map.js +3 -3
  22. package/dist/bin/pikku-scheduler.js +7 -10
  23. package/dist/bin/pikku-schemas.d.ts +1 -1
  24. package/dist/bin/pikku-schemas.js +6 -6
  25. package/dist/bin/pikku-websocket.js +1 -1
  26. package/dist/bin/pikku.js +2 -2
  27. package/dist/src/channels/serialize-typed-channel-map.js +5 -2
  28. package/dist/src/core/serialize-import-map.js +1 -0
  29. package/dist/src/core/serialize-pikku-types.js +90 -6
  30. package/dist/src/events/channels/serialize-channels.d.ts +3 -0
  31. package/dist/src/events/channels/serialize-channels.js +19 -0
  32. package/dist/src/events/channels/serialize-typed-channel-map.d.ts +3 -0
  33. package/dist/src/events/channels/serialize-typed-channel-map.js +90 -0
  34. package/dist/src/events/channels/serialize-websocket-wrapper.d.ts +1 -0
  35. package/{src/channels/serialize-websocket-wrapper.ts → dist/src/events/channels/serialize-websocket-wrapper.js} +4 -4
  36. package/dist/src/events/http/serialize-fetch-wrapper.d.ts +1 -0
  37. package/{src/http/serialize-fetch-wrapper.ts → dist/src/events/http/serialize-fetch-wrapper.js} +4 -4
  38. package/dist/src/events/http/serialize-route-imports.d.ts +1 -0
  39. package/dist/src/events/http/serialize-route-imports.js +13 -0
  40. package/dist/src/events/http/serialize-route-meta.d.ts +2 -0
  41. package/dist/src/events/http/serialize-route-meta.js +6 -0
  42. package/dist/src/events/http/serialize-typed-route-map.d.ts +4 -0
  43. package/dist/src/events/http/serialize-typed-route-map.js +107 -0
  44. package/dist/src/events/scheduler/serialize-schedulers.d.ts +3 -0
  45. package/dist/src/events/scheduler/serialize-schedulers.js +23 -0
  46. package/dist/src/http/serialize-typed-route-map.js +1 -1
  47. package/dist/src/inspector-glob.d.ts +1 -1
  48. package/dist/src/inspector-glob.js +2 -2
  49. package/dist/src/openapi-spec-generator.d.ts +79 -0
  50. package/dist/src/openapi-spec-generator.js +136 -0
  51. package/dist/src/pikku-cli-config.d.ts +9 -4
  52. package/dist/src/pikku-cli-config.js +19 -4
  53. package/dist/src/scheduler/serialize-schedulers.js +3 -2
  54. package/dist/src/schema/schema-generator.d.ts +1 -1
  55. package/dist/src/schema/schema-generator.js +20 -7
  56. package/dist/src/schema-generator.d.ts +5 -0
  57. package/dist/src/schema-generator.js +98 -0
  58. package/dist/src/serialize-fetch-wrapper.d.ts +1 -0
  59. package/dist/src/serialize-fetch-wrapper.js +67 -0
  60. package/dist/src/serialize-import-map.d.ts +2 -0
  61. package/dist/src/serialize-import-map.js +24 -0
  62. package/dist/src/serialize-nextjs-backend-wrapper.d.ts +1 -0
  63. package/{src/nextjs/serialize-nextjs-backend-wrapper.ts → dist/src/serialize-nextjs-backend-wrapper.js} +4 -11
  64. package/dist/src/serialize-nextjs-http-wrapper.d.ts +1 -0
  65. package/{src/nextjs/serialize-nextjs-http-wrapper.ts → dist/src/serialize-nextjs-http-wrapper.js} +4 -7
  66. package/dist/src/serialize-pikku-types.d.ts +4 -0
  67. package/dist/src/serialize-pikku-types.js +136 -0
  68. package/dist/src/serialize-scheduler-meta.d.ts +2 -0
  69. package/dist/src/serialize-scheduler-meta.js +10 -0
  70. package/dist/src/serialize-typed-channel-map.d.ts +3 -0
  71. package/dist/src/serialize-typed-channel-map.js +93 -0
  72. package/dist/src/serialize-typed-function-map.d.ts +4 -0
  73. package/dist/src/serialize-typed-function-map.js +107 -0
  74. package/dist/src/serialize-typed-http-map.d.ts +4 -0
  75. package/dist/src/serialize-typed-http-map.js +107 -0
  76. package/dist/src/serialize-typed-route-map.d.ts +4 -0
  77. package/dist/src/serialize-typed-route-map.js +107 -0
  78. package/dist/src/serialize-websocket-wrapper.d.ts +1 -0
  79. package/dist/src/serialize-websocket-wrapper.js +61 -0
  80. package/dist/src/utils.d.ts +1 -0
  81. package/dist/src/utils.js +17 -5
  82. package/package.json +3 -3
  83. package/bin/pikku-all.ts +0 -180
  84. package/bin/pikku-channels-map.ts +0 -55
  85. package/bin/pikku-channels.ts +0 -58
  86. package/bin/pikku-fetch.ts +0 -55
  87. package/bin/pikku-function-types.ts +0 -84
  88. package/bin/pikku-http.ts +0 -56
  89. package/bin/pikku-nextjs.test.ts +0 -279
  90. package/bin/pikku-nextjs.ts +0 -152
  91. package/bin/pikku-openapi.ts +0 -70
  92. package/bin/pikku-routes-map.ts +0 -55
  93. package/bin/pikku-scheduler.ts +0 -62
  94. package/bin/pikku-schemas.ts +0 -52
  95. package/bin/pikku-websocket.ts +0 -58
  96. package/bin/pikku.ts +0 -26
  97. package/dist/tsconfig.tsbuildinfo +0 -1
  98. package/src/channels/serialize-channels.ts +0 -34
  99. package/src/channels/serialize-typed-channel-map.ts +0 -136
  100. package/src/core/serialize-import-map.ts +0 -33
  101. package/src/core/serialize-pikku-types.ts +0 -55
  102. package/src/http/serialize-route-imports.ts +0 -24
  103. package/src/http/serialize-route-meta.ts +0 -10
  104. package/src/http/serialize-typed-route-map.ts +0 -150
  105. package/src/inspector-glob.ts +0 -28
  106. package/src/openapi/openapi-spec-generator.ts +0 -227
  107. package/src/pikku-cli-config.ts +0 -204
  108. package/src/scheduler/serialize-schedulers.ts +0 -41
  109. package/src/schema/schema-generator.ts +0 -114
  110. package/src/utils.ts +0 -260
  111. package/tsconfig.json +0 -21
@@ -6,7 +6,8 @@ export const serializePikkuTypes = (userSessionTypeImport, userSessionTypeName,
6
6
  * This is used to provide the application types in the typescript project
7
7
  */
8
8
 
9
- import { CoreAPIFunction, CoreAPIFunctionSessionless, CoreAPIPermission, PikkuMiddleware, MakeRequired } from '@pikku/core'
9
+ import { CorePermissionGroup, CoreAPIPermission, PikkuMiddleware, MakeRequired } from '@pikku/core'
10
+ import { CoreAPIFunction, CoreAPIFunctionSessionless } from '@pikku/core/function'
10
11
  import { CoreHTTPFunctionRoute, AssertRouteParams, addRoute as addCoreHTTP } from '@pikku/core/http'
11
12
  import { CoreScheduledTask, addScheduledTask as addCoreScheduledTask } from '@pikku/core/scheduler'
12
13
  import { CoreAPIChannel, PikkuChannel, addChannel as addCoreChannel } from '@pikku/core/channel'
@@ -18,17 +19,100 @@ ${sessionServicesTypeImport}
18
19
  export type APIPermission<In = unknown, RequiredServices extends ${singletonServicesTypeName} = ${singletonServicesTypeName}> = CoreAPIPermission<In, RequiredServices, ${userSessionTypeName}>
19
20
  export type APIMiddleware<RequiredServices extends ${singletonServicesTypeName} = ${singletonServicesTypeName}> = PikkuMiddleware<RequiredServices, ${userSessionTypeName}>
20
21
 
21
- export type APIFunctionSessionless<In = unknown, Out = never, RequiredServices extends ${servicesTypeName} = ${servicesTypeName}> = CoreAPIFunctionSessionless<In, Out, RequiredServices, ${userSessionTypeName}>
22
- export type APIFunction<In = unknown, Out = never, RequiredServices extends ${servicesTypeName} = ${servicesTypeName}> = CoreAPIFunction<In, Out, RequiredServices, ${userSessionTypeName}>
23
- type APIRoute<In, Out, Route extends string> = CoreHTTPFunctionRoute<In, Out, Route, APIFunction<In, Out>, APIFunctionSessionless<In, Out>, APIPermission<In>, APIMiddleware>
22
+ type APIFunctionSessionless<In = unknown, Out = never, Channel extends boolean = false, RequiredServices extends Services = Services & (Channel extends true ? { channel: PikkuChannel<unknown, Out> } : { channel?: PikkuChannel<unknown, Out> })> = CoreAPIFunctionSessionless<In, Out, Channel, RequiredServices, ${userSessionTypeName}>
23
+ type APIFunction<In = unknown, Out = never, Channel extends boolean = false, RequiredServices extends Services = Services & (Channel extends true ? { channel: PikkuChannel<unknown, Out> } : { channel?: PikkuChannel<unknown, Out> })> = CoreAPIFunction<In, Out, Channel, RequiredServices, ${userSessionTypeName}>
24
+ type APIRoute<In, Out, Route extends string> = CoreHTTPFunctionRoute<In, Out, Route, APIFunction<In, Out>, APIFunctionSessionless<In, Out>, CorePermissionGroup<APIPermission>, APIMiddleware>
24
25
 
25
26
  export type ChannelConnection<Out = unknown, ChannelData = unknown, RequiredServices extends ${servicesTypeName} = ${servicesTypeName}> = (services: MakeRequired<RequiredServices, 'userSession'>, channel: PikkuChannel<ChannelData, Out>) => Promise<void>
26
27
  export type ChannelDisconnection<ChannelData = unknown, RequiredServices extends ${servicesTypeName} = ${servicesTypeName}> = (services: MakeRequired<RequiredServices, 'userSession'>, channel: PikkuChannel<ChannelData, never>) => Promise<void>
27
- export type ChannelMessage<In, Out = unknown, ChannelData = unknown, RequiredServices extends ${servicesTypeName} = ${servicesTypeName}> = (services: MakeRequired<RequiredServices, 'userSession'>, channel: PikkuChannel<ChannelData, Out>, data: In) => Promise<Out | void>
28
- type APIChannel<ChannelData, Channel extends string> = CoreAPIChannel<ChannelData, Channel, ChannelConnection, ChannelDisconnection, ChannelMessage<any, any, ChannelData>, ChannelMessage<any, any, ChannelData>, APIPermission>
28
+ type APIChannel<ChannelData, Channel extends string> = CoreAPIChannel<ChannelData, Channel, APIFunction<any, any, false> | APIFunction<any, any, true>, APIPermission>
29
29
 
30
30
  type ScheduledTask = CoreScheduledTask<APIFunctionSessionless<void, void>, ${userSessionTypeName}>
31
31
 
32
+ export const pikkuFunc = <In, Out = unknown>(
33
+ func:
34
+ | APIFunction<In, Out>
35
+ | {
36
+ func: APIFunction<In, Out>
37
+ auth?: true
38
+ name?: string
39
+ }
40
+ | {
41
+ func: APIFunctionSessionless<In, Out>
42
+ auth: false
43
+ name?: string
44
+ }
45
+ ) => {
46
+ return typeof func === 'function' ? func : func.func
47
+ }
48
+
49
+ export const pikkuSessionlessFunc = <In, Out = unknown>(
50
+ func:
51
+ | APIFunctionSessionless<In, Out>
52
+ | {
53
+ func: APIFunctionSessionless<In, Out>
54
+ name?: string
55
+ }
56
+ ) => {
57
+ return typeof func === 'function' ? func : func.func
58
+ }
59
+
60
+ export const pikkuChannelConnection = <In, Out = unknown>(
61
+ func:
62
+ | ChannelConnection<In, Out>
63
+ | {
64
+ func: ChannelConnection<In, Out>
65
+ auth?: true
66
+ name?: string
67
+ }
68
+ | {
69
+ func: ChannelConnection<In, Out>
70
+ auth: false
71
+ name?: string
72
+ }
73
+ ) => {
74
+ return typeof func === 'function' ? func : func.func
75
+ }
76
+
77
+ export const pikkuChannelDisconnection = <In>(
78
+ func:
79
+ | ChannelDisconnection<In>
80
+ | {
81
+ func: ChannelDisconnection<In>
82
+ auth?: true
83
+ name?: string
84
+ }
85
+ | {
86
+ func: ChannelDisconnection<In>
87
+ auth: false
88
+ name?: string
89
+ }
90
+ ) => {
91
+ return typeof func === 'function' ? func : func.func
92
+ }
93
+
94
+ export const pikkuChannelFunc = <In, Out = unknown>(
95
+ func:
96
+ | APIFunctionSessionless<In, Out, true>
97
+ | {
98
+ func: APIFunctionSessionless<In, Out, true>
99
+ name?: string
100
+ }
101
+ ) => {
102
+ return typeof func === 'function' ? func : func.func
103
+ }
104
+
105
+ export const pikkuVoidFunc = (
106
+ func:
107
+ | APIFunctionSessionless<void, void>
108
+ | {
109
+ func: APIFunctionSessionless<void, void>
110
+ name?: string
111
+ }
112
+ ) => {
113
+ return typeof func === 'function' ? func : func.func
114
+ }
115
+
32
116
  export const addChannel = <ChannelData, Channel extends string>(
33
117
  channel: APIChannel<ChannelData, Channel> & AssertRouteParams<ChannelData, Channel>
34
118
  ) => {
@@ -0,0 +1,3 @@
1
+ import { ChannelsMeta } from '@pikku/core/channel';
2
+ export declare const serializeChannels: (outputPath: string, filesWithChannels: Set<string>, packageMappings?: Record<string, string>) => string;
3
+ export declare const serializeChannelMeta: (channelsMeta: ChannelsMeta) => string;
@@ -0,0 +1,19 @@
1
+ import { getFileImportRelativePath } from '../utils.js';
2
+ export const serializeChannels = (outputPath, filesWithChannels, packageMappings = {}) => {
3
+ const serializedOutput = [
4
+ '/* The files with an addChannel function call */',
5
+ ];
6
+ Array.from(filesWithChannels)
7
+ .sort()
8
+ .forEach((path) => {
9
+ const filePath = getFileImportRelativePath(outputPath, path, packageMappings);
10
+ serializedOutput.push(`import '${filePath}'`);
11
+ });
12
+ return serializedOutput.join('\n');
13
+ };
14
+ export const serializeChannelMeta = (channelsMeta) => {
15
+ const serializedOutput = [];
16
+ serializedOutput.push("import { pikkuState } from '@pikku/core'");
17
+ serializedOutput.push(`pikkuState('channel', 'meta', ${JSON.stringify(channelsMeta, null, 2)})`);
18
+ return serializedOutput.join('\n');
19
+ };
@@ -0,0 +1,3 @@
1
+ import { ChannelsMeta } from '@pikku/core/channel';
2
+ import { TypesMap } from '@pikku/inspector';
3
+ export declare const serializeTypedChannelsMap: (relativeToPath: string, packageMappings: Record<string, string>, typesMap: TypesMap, channelsMeta: ChannelsMeta) => string;
@@ -0,0 +1,90 @@
1
+ import { serializeImportMap } from '../core/serialize-import-map.js';
2
+ import { generateCustomTypes } from '../http/serialize-typed-route-map.js';
3
+ export const serializeTypedChannelsMap = (relativeToPath, packageMappings, typesMap, channelsMeta) => {
4
+ const { channels, requiredTypes } = generateChannels(channelsMeta);
5
+ typesMap.customTypes.forEach(({ references }) => {
6
+ for (const reference of references) {
7
+ requiredTypes.add(reference);
8
+ }
9
+ });
10
+ const imports = serializeImportMap(relativeToPath, packageMappings, typesMap, requiredTypes);
11
+ const serializedCustomTypes = generateCustomTypes(typesMap, requiredTypes);
12
+ return `/**
13
+ * This provides the structure needed for TypeScript to be aware of channels
14
+ */
15
+
16
+ ${imports}
17
+ ${serializedCustomTypes}
18
+
19
+ interface ChannelHandler<I, O> {
20
+ input: I;
21
+ output: O;
22
+ }
23
+
24
+ ${channels}
25
+
26
+ export type ChannelDefaultHandlerOf<Channel extends keyof ChannelsMap> =
27
+ ChannelsMap[Channel]['defaultMessage'] extends { input: infer I; output: infer O }
28
+ ? ChannelHandler<I, O>
29
+ : never;
30
+
31
+ export type ChannelRouteHandlerOf<
32
+ Channel extends keyof ChannelsMap,
33
+ Route extends keyof ChannelsMap[Channel]['routes'],
34
+ Method extends keyof ChannelsMap[Channel]['routes'][Route],
35
+ > =
36
+ ChannelsMap[Channel]['routes'][Route][Method] extends { input: infer I; output: infer O }
37
+ ? ChannelHandler<I, O>
38
+ : never;
39
+ `;
40
+ };
41
+ function generateChannels(channelsMeta) {
42
+ const requiredTypes = new Set();
43
+ const channelsObject = {};
44
+ for (const meta of channelsMeta) {
45
+ const { name, messageRoutes, message } = meta;
46
+ if (!channelsObject[name]) {
47
+ channelsObject[name] = { message, routes: {} };
48
+ }
49
+ for (const [key, route] of Object.entries(messageRoutes)) {
50
+ if (!channelsObject[name].routes[key]) {
51
+ channelsObject[name].routes[key] = {};
52
+ }
53
+ for (const [method, { inputs, outputs }] of Object.entries(route)) {
54
+ const inputTypes = inputs || null;
55
+ const outputTypes = outputs || null;
56
+ channelsObject[name].routes[key][method] = {
57
+ inputTypes,
58
+ outputTypes,
59
+ };
60
+ inputTypes?.forEach((type) => requiredTypes.add(type));
61
+ outputTypes?.forEach((type) => requiredTypes.add(type));
62
+ }
63
+ }
64
+ }
65
+ let routesStr = 'export type ChannelsMap = {\n';
66
+ for (const [channelPath, { routes, message }] of Object.entries(channelsObject)) {
67
+ routesStr += ` readonly '${channelPath}': {\n`;
68
+ // Add `routes` object
69
+ routesStr += ` readonly routes: {\n`;
70
+ for (const [key, methods] of Object.entries(routes)) {
71
+ routesStr += ` readonly ${key}: {\n`;
72
+ for (const [method, handler] of Object.entries(methods)) {
73
+ routesStr += ` readonly ${method}: ChannelHandler<${formatTypeArray(handler.inputTypes) || 'void'}, ${formatTypeArray(handler.outputTypes) || 'never'}>,\n`;
74
+ }
75
+ routesStr += ' },\n';
76
+ }
77
+ routesStr += ' },\n';
78
+ // Add `defaultMessage` outside `routes`
79
+ if (message) {
80
+ routesStr += ` readonly defaultMessage: ChannelHandler<${formatTypeArray(message.inputs)}, ${formatTypeArray(message.outputs)}>,\n`;
81
+ }
82
+ routesStr += ' },\n';
83
+ }
84
+ routesStr += '};';
85
+ return { channels: routesStr, requiredTypes };
86
+ }
87
+ // Utility to format type arrays
88
+ function formatTypeArray(types) {
89
+ return types ? types.join(' | ') : 'null';
90
+ }
@@ -0,0 +1 @@
1
+ export declare const serializeWebsocketWrapper: (channelsMapPath: string) => string;
@@ -1,5 +1,5 @@
1
- export const serializeWebsocketWrapper = (channelsMapPath: string) => {
2
- return `import { CorePikkuWebsocket, CorePikkuRouteHandler } from '@pikku/websocket'
1
+ export const serializeWebsocketWrapper = (channelsMapPath) => {
2
+ return `import { CorePikkuWebsocket, CorePikkuRouteHandler } from '@pikku/websocket'
3
3
  import { ChannelDefaultHandlerOf, ChannelRouteHandlerOf, ChannelsMap } from '${channelsMapPath}';
4
4
 
5
5
  class PikkuWebSocketRoute<Channel extends keyof ChannelsMap, Route extends keyof ChannelsMap[Channel]['routes']> extends CorePikkuRouteHandler {
@@ -57,5 +57,5 @@ export class PikkuWebSocket<Channel extends keyof ChannelsMap> extends CorePikku
57
57
  super.send(data)
58
58
  }
59
59
  }
60
- `
61
- }
60
+ `;
61
+ };
@@ -0,0 +1 @@
1
+ export declare const serializeFetchWrapper: (routesMapPath: string) => string;
@@ -1,5 +1,5 @@
1
- export const serializeFetchWrapper = (routesMapPath: string) => {
2
- return `
1
+ export const serializeFetchWrapper = (routesMapPath) => {
2
+ return `
3
3
  import { CorePikkuFetch, HTTPMethod } from '@pikku/fetch'
4
4
  import type { RoutesMap, RouteHandlerOf, RoutesWithMethod } from '${routesMapPath}'
5
5
 
@@ -63,5 +63,5 @@ export class PikkuFetch extends CorePikkuFetch {
63
63
  }
64
64
 
65
65
  export const pikkuFetch = new PikkuFetch();
66
- `
67
- }
66
+ `;
67
+ };
@@ -0,0 +1 @@
1
+ export declare const serializeRoutes: (outputPath: string, filesWithRoutes: Set<string>, packageMappings?: Record<string, string>) => string;
@@ -0,0 +1,13 @@
1
+ import { getFileImportRelativePath } from '../utils.js';
2
+ export const serializeRoutes = (outputPath, filesWithRoutes, packageMappings = {}) => {
3
+ const serializedOutput = [
4
+ '/* The files with an addRoute function call */',
5
+ ];
6
+ Array.from(filesWithRoutes)
7
+ .sort()
8
+ .forEach((path) => {
9
+ const filePath = getFileImportRelativePath(outputPath, path, packageMappings);
10
+ serializedOutput.push(`import '${filePath}'`);
11
+ });
12
+ return serializedOutput.join('\n');
13
+ };
@@ -0,0 +1,2 @@
1
+ import type { HTTPRoutesMeta } from '@pikku/core/http';
2
+ export declare const serializeHTTPRoutesMeta: (routesMeta: HTTPRoutesMeta) => string;
@@ -0,0 +1,6 @@
1
+ export const serializeHTTPRoutesMeta = (routesMeta) => {
2
+ const serializedOutput = [];
3
+ serializedOutput.push("import { pikkuState } from '@pikku/core'");
4
+ serializedOutput.push(`pikkuState('http', 'meta', ${JSON.stringify(routesMeta, null, 2)})`);
5
+ return serializedOutput.join('\n');
6
+ };
@@ -0,0 +1,4 @@
1
+ import { HTTPRoutesMeta } from '@pikku/core/http';
2
+ import { MetaInputTypes, TypesMap } from '@pikku/inspector';
3
+ export declare const serializeTypedRoutesMap: (relativeToPath: string, packageMappings: Record<string, string>, typesMap: TypesMap, routesMeta: HTTPRoutesMeta, metaTypes: MetaInputTypes) => string;
4
+ export declare function generateCustomTypes(typesMap: TypesMap, requiredTypes: Set<string>): string;
@@ -0,0 +1,107 @@
1
+ import { serializeImportMap } from '../core/serialize-import-map.js';
2
+ export const serializeTypedRoutesMap = (relativeToPath, packageMappings, typesMap, routesMeta, metaTypes) => {
3
+ const requiredTypes = new Set();
4
+ const serializedCustomTypes = generateCustomTypes(typesMap, requiredTypes);
5
+ const serializedMetaTypes = generateMetaTypes(metaTypes, typesMap);
6
+ const serializedRoutes = generateRoutes(routesMeta, typesMap, requiredTypes);
7
+ const serializedImportMap = serializeImportMap(relativeToPath, packageMappings, typesMap, requiredTypes);
8
+ return `/**
9
+ * This provides the structure needed for typescript to be aware of routes and their return types
10
+ */
11
+
12
+ ${serializedImportMap}
13
+ ${serializedCustomTypes}
14
+ ${serializedMetaTypes}
15
+
16
+ interface RouteHandler<I, O> {
17
+ input: I;
18
+ output: O;
19
+ }
20
+
21
+ ${serializedRoutes}
22
+
23
+ export type RouteHandlerOf<Route extends keyof RoutesMap, Method extends keyof RoutesMap[Route]> =
24
+ RoutesMap[Route][Method] extends { input: infer I; output: infer O }
25
+ ? RouteHandler<I, O>
26
+ : never;
27
+
28
+ export type RoutesWithMethod<Method extends string> = {
29
+ [Route in keyof RoutesMap]: Method extends keyof RoutesMap[Route] ? Route : never;
30
+ }[keyof RoutesMap];
31
+ `;
32
+ };
33
+ export function generateCustomTypes(typesMap, requiredTypes) {
34
+ return `
35
+ // Custom types are those that are defined directly within generics
36
+ // or are broken into simpler types
37
+ ${Array.from(typesMap.customTypes.entries())
38
+ .map(([name, { type, references }]) => {
39
+ references.forEach((name) => {
40
+ const originalName = typesMap.getTypeMeta(name).originalName;
41
+ requiredTypes.add(originalName);
42
+ });
43
+ return `export type ${name} = ${type}`;
44
+ })
45
+ .join('\n')}`;
46
+ }
47
+ function generateRoutes(routesMeta, typesMap, requiredTypes) {
48
+ // Initialize an object to collect routes
49
+ const routesObj = {};
50
+ for (const meta of routesMeta) {
51
+ const { route, method, input, output } = meta;
52
+ // Initialize the route entry if it doesn't exist
53
+ if (!routesObj[route]) {
54
+ routesObj[route] = {};
55
+ }
56
+ // Store the input and output types separately for RouteHandler
57
+ const inputType = input ? typesMap.getTypeMeta(input).uniqueName : 'null';
58
+ const outputType = output ? typesMap.getTypeMeta(output).uniqueName : 'null';
59
+ requiredTypes.add(inputType);
60
+ requiredTypes.add(outputType);
61
+ // Add method entry
62
+ routesObj[route][method] = {
63
+ inputType,
64
+ outputType,
65
+ };
66
+ }
67
+ // Build the routes object as a string
68
+ let routesStr = 'export type RoutesMap = {\n';
69
+ for (const [routePath, methods] of Object.entries(routesObj)) {
70
+ routesStr += ` readonly '${routePath}': {\n`;
71
+ for (const [method, handler] of Object.entries(methods)) {
72
+ routesStr += ` readonly ${method.toUpperCase()}: RouteHandler<${handler.inputType}, ${handler.outputType}>,\n`;
73
+ }
74
+ routesStr += ' },\n';
75
+ }
76
+ routesStr += '};';
77
+ return routesStr;
78
+ }
79
+ const generateMetaTypes = (metaTypes, typesMap) => {
80
+ const nameToTypeMap = Array.from(metaTypes.entries()).reduce((result, [_name, { query, body, params }]) => {
81
+ const { uniqueName } = typesMap.getTypeMeta(_name);
82
+ const queryType = query && query.length > 0
83
+ ? `Pick<${uniqueName}, '${query?.join("' | '")}'>`
84
+ : undefined;
85
+ if (queryType) {
86
+ result.set(`${uniqueName}Query`, queryType);
87
+ }
88
+ const paramsType = params && params.length > 0
89
+ ? `Pick<${uniqueName}, '${params.join("' | '")}'>`
90
+ : undefined;
91
+ if (paramsType) {
92
+ result.set(`${uniqueName}Params`, paramsType);
93
+ }
94
+ const bodyType = (body && body.length > 0) || (params && params.length > 0)
95
+ ? `Omit<${uniqueName}, '${[...new Set([...(query || []), ...(params || [])])].join("' | '")}'>`
96
+ : uniqueName;
97
+ if (bodyType) {
98
+ result.set(`${uniqueName}Body`, bodyType);
99
+ }
100
+ return result;
101
+ }, new Map());
102
+ return `
103
+ // The '& {}' is a workaround for not directly refering to a type since it confuses typescript
104
+ ${Array.from(nameToTypeMap.entries())
105
+ .map(([name, type]) => `export type ${name} = ${type} & {}`)
106
+ .join('\n')}`;
107
+ };
@@ -0,0 +1,3 @@
1
+ import { ScheduledTasksMeta } from '@pikku/core/scheduler';
2
+ export declare const serializeSchedulers: (outputPath: string, filesWithScheduledTasks: Set<string>, packageMappings?: Record<string, string>) => string;
3
+ export declare const serializeSchedulerMeta: (scheduledTasksMeta: ScheduledTasksMeta) => string;
@@ -0,0 +1,23 @@
1
+ import { getFileImportRelativePath } from '../../utils.js';
2
+ export const serializeSchedulers = (outputPath, filesWithScheduledTasks, packageMappings = {}) => {
3
+ const serializedOutput = [
4
+ '/* The files with an addSerializedTasks function call */',
5
+ ];
6
+ Array.from(filesWithScheduledTasks)
7
+ .sort()
8
+ .forEach((path) => {
9
+ const filePath = getFileImportRelativePath(outputPath, path, packageMappings);
10
+ serializedOutput.push(`import '${filePath}'`);
11
+ });
12
+ return serializedOutput.join('\n');
13
+ };
14
+ export const serializeSchedulerMeta = (scheduledTasksMeta) => {
15
+ const serializedOutput = [];
16
+ serializedOutput.push("import { pikkuState } from '@pikku/core'");
17
+ serializedOutput.push(`pikkuState('scheduler', 'meta', ${JSON.stringify(scheduledTasksMeta, null, 2)})`);
18
+ const scheduledTasksMetaValues = Object.values(scheduledTasksMeta);
19
+ if (scheduledTasksMetaValues.length > 0) {
20
+ serializedOutput.push(`export type ScheduledTaskNames = '${scheduledTasksMetaValues.map((s) => s.name).join("' | '")}'`);
21
+ }
22
+ return serializedOutput.join('\n');
23
+ };
@@ -3,8 +3,8 @@ export const serializeTypedRoutesMap = (relativeToPath, packageMappings, typesMa
3
3
  const requiredTypes = new Set();
4
4
  const serializedCustomTypes = generateCustomTypes(typesMap, requiredTypes);
5
5
  const serializedMetaTypes = generateMetaTypes(metaTypes, typesMap);
6
- const serializedImportMap = serializeImportMap(relativeToPath, packageMappings, typesMap, requiredTypes);
7
6
  const serializedRoutes = generateRoutes(routesMeta, typesMap, requiredTypes);
7
+ const serializedImportMap = serializeImportMap(relativeToPath, packageMappings, typesMap, requiredTypes);
8
8
  return `/**
9
9
  * This provides the structure needed for typescript to be aware of routes and their return types
10
10
  */
@@ -1,2 +1,2 @@
1
1
  import { InspectorFilters, InspectorState } from '@pikku/inspector';
2
- export declare const inspectorGlob: (rootDir: string, routeDirectories: string[], filters: InspectorFilters) => Promise<InspectorState>;
2
+ export declare const inspectorGlob: (rootDir: string, srcDirectories: string[], filters: InspectorFilters) => Promise<InspectorState>;
@@ -2,10 +2,10 @@ import * as path from 'path';
2
2
  import { glob } from 'tinyglobby';
3
3
  import { inspect } from '@pikku/inspector';
4
4
  import { logCommandInfoAndTime } from './utils.js';
5
- export const inspectorGlob = async (rootDir, routeDirectories, filters) => {
5
+ export const inspectorGlob = async (rootDir, srcDirectories, filters) => {
6
6
  let result;
7
7
  await logCommandInfoAndTime('Inspecting codebase', 'Inspected codebase', [false], async () => {
8
- const routeFiles = (await Promise.all(routeDirectories.map((dir) => glob(`${path.join(rootDir, dir)}/**/*.ts`)))).flat();
8
+ const routeFiles = (await Promise.all(srcDirectories.map((dir) => glob(`${path.join(rootDir, dir)}/**/*.ts`)))).flat();
9
9
  result = await inspect(routeFiles, filters);
10
10
  });
11
11
  return result;
@@ -0,0 +1,79 @@
1
+ import { HTTPRoutesMeta } from '@pikku/core';
2
+ interface OpenAPISpec {
3
+ openapi: string;
4
+ info: {
5
+ title: string;
6
+ version: string;
7
+ description?: string;
8
+ termsOfService?: string;
9
+ contact?: {
10
+ name?: string;
11
+ url?: string;
12
+ email?: string;
13
+ };
14
+ license?: {
15
+ name: string;
16
+ url?: string;
17
+ };
18
+ };
19
+ servers: {
20
+ url: string;
21
+ description?: string;
22
+ }[];
23
+ paths: Record<string, any>;
24
+ components: {
25
+ schemas: Record<string, any>;
26
+ responses?: Record<string, any>;
27
+ parameters?: Record<string, any>;
28
+ examples?: Record<string, any>;
29
+ requestBodies?: Record<string, any>;
30
+ headers?: Record<string, any>;
31
+ securitySchemes?: Record<string, any>;
32
+ };
33
+ security?: {
34
+ [key: string]: any[];
35
+ }[];
36
+ tags?: {
37
+ name: string;
38
+ description?: string;
39
+ }[];
40
+ externalDocs?: {
41
+ description?: string;
42
+ url: string;
43
+ };
44
+ }
45
+ export interface OpenAPISpecInfo {
46
+ info: {
47
+ title: string;
48
+ version: string;
49
+ description: string;
50
+ termsOfService?: string;
51
+ contact?: {
52
+ name?: string;
53
+ url?: string;
54
+ email?: string;
55
+ };
56
+ license?: {
57
+ name: string;
58
+ url?: string;
59
+ };
60
+ };
61
+ servers: {
62
+ url: string;
63
+ description?: string;
64
+ }[];
65
+ tags?: {
66
+ name: string;
67
+ description?: string;
68
+ }[];
69
+ externalDocs?: {
70
+ description?: string;
71
+ url: string;
72
+ };
73
+ securitySchemes?: Record<string, any>;
74
+ security?: {
75
+ [key: string]: any[];
76
+ }[];
77
+ }
78
+ export declare function generateOpenAPISpec(routeMeta: HTTPRoutesMeta, schemas: Record<string, any>, additionalInfo: OpenAPISpecInfo): Promise<OpenAPISpec>;
79
+ export {};