@pikku/cli 0.6.20 → 0.7.1

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 (100) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/bin/pikku-all.ts +41 -18
  3. package/bin/pikku-channels-map.ts +4 -4
  4. package/bin/pikku-channels.ts +17 -12
  5. package/bin/pikku-fetch.ts +3 -3
  6. package/bin/pikku-function-types.ts +4 -4
  7. package/bin/pikku-functions.ts +35 -0
  8. package/bin/{pikku-routes-map.ts → pikku-http-map.ts} +10 -10
  9. package/bin/{pikku-http.ts → pikku-http-routes.ts} +17 -10
  10. package/bin/pikku-nextjs.ts +9 -9
  11. package/bin/pikku-openapi.ts +10 -6
  12. package/bin/pikku-rpc.ts +22 -0
  13. package/bin/pikku-scheduler.ts +15 -13
  14. package/bin/pikku-schemas.ts +10 -6
  15. package/bin/pikku-websocket.ts +1 -1
  16. package/bin/pikku.ts +2 -2
  17. package/cli.schema.json +2 -2
  18. package/dist/bin/pikku-all.js +37 -16
  19. package/dist/bin/pikku-channels-map.js +4 -4
  20. package/dist/bin/pikku-channels.js +6 -10
  21. package/dist/bin/pikku-fetch.d.ts +1 -1
  22. package/dist/bin/pikku-fetch.js +3 -3
  23. package/dist/bin/pikku-function-types.js +4 -4
  24. package/dist/bin/pikku-functions.d.ts +3 -0
  25. package/dist/bin/pikku-functions.js +9 -0
  26. package/dist/bin/{pikku-routes-map.d.ts → pikku-http-map.d.ts} +1 -1
  27. package/dist/bin/{pikku-routes-map.js → pikku-http-map.js} +7 -7
  28. package/dist/bin/{pikku-http.js → pikku-http-routes.js} +6 -11
  29. package/dist/bin/pikku-nextjs.d.ts +1 -1
  30. package/dist/bin/pikku-nextjs.js +8 -8
  31. package/dist/bin/pikku-openapi.d.ts +1 -1
  32. package/dist/bin/pikku-openapi.js +6 -6
  33. package/dist/bin/pikku-rpc.d.ts +3 -0
  34. package/dist/bin/pikku-rpc.js +8 -0
  35. package/dist/bin/pikku-scheduler.js +7 -10
  36. package/dist/bin/pikku-schemas.d.ts +1 -1
  37. package/dist/bin/pikku-schemas.js +6 -6
  38. package/dist/bin/pikku-websocket.js +1 -1
  39. package/dist/bin/pikku.js +2 -2
  40. package/dist/src/inspector-glob.d.ts +1 -1
  41. package/dist/src/inspector-glob.js +2 -2
  42. package/dist/src/pikku-cli-config.d.ts +10 -4
  43. package/dist/src/pikku-cli-config.js +22 -4
  44. package/dist/src/{schema/schema-generator.d.ts → schema-generator.d.ts} +1 -1
  45. package/dist/src/{schema/schema-generator.js → schema-generator.js} +29 -8
  46. package/dist/src/{core/serialize-import-map.js → serialize-import-map.js} +2 -1
  47. package/dist/src/serialize-pikku-types.js +136 -0
  48. package/dist/src/{scheduler/serialize-schedulers.d.ts → serialize-scheduler-meta.d.ts} +0 -1
  49. package/dist/src/serialize-scheduler-meta.js +10 -0
  50. package/dist/src/{channels/serialize-typed-channel-map.js → serialize-typed-channel-map.js} +7 -4
  51. package/dist/src/{http/serialize-typed-route-map.js → serialize-typed-function-map.js} +2 -2
  52. package/dist/src/serialize-typed-http-map.d.ts +4 -0
  53. package/dist/src/serialize-typed-http-map.js +107 -0
  54. package/dist/src/utils.d.ts +1 -0
  55. package/dist/src/utils.js +17 -5
  56. package/dist/tsconfig.tsbuildinfo +1 -1
  57. package/package.json +3 -3
  58. package/src/inspector-glob.ts +2 -2
  59. package/src/pikku-cli-config.ts +44 -8
  60. package/src/{schema/schema-generator.ts → schema-generator.ts} +31 -9
  61. package/src/{core/serialize-import-map.ts → serialize-import-map.ts} +2 -1
  62. package/src/serialize-pikku-types.ts +143 -0
  63. package/src/serialize-scheduler-meta.ts +18 -0
  64. package/src/{channels/serialize-typed-channel-map.ts → serialize-typed-channel-map.ts} +8 -6
  65. package/src/{http/serialize-typed-route-map.ts → serialize-typed-function-map.ts} +3 -2
  66. package/src/serialize-typed-http-map.ts +151 -0
  67. package/src/utils.ts +29 -5
  68. package/dist/src/channels/serialize-channels.d.ts +0 -3
  69. package/dist/src/channels/serialize-channels.js +0 -19
  70. package/dist/src/core/serialize-pikku-types.js +0 -48
  71. package/dist/src/http/serialize-route-imports.d.ts +0 -1
  72. package/dist/src/http/serialize-route-imports.js +0 -13
  73. package/dist/src/http/serialize-route-meta.d.ts +0 -2
  74. package/dist/src/http/serialize-route-meta.js +0 -6
  75. package/dist/src/scheduler/serialize-schedulers.js +0 -22
  76. package/src/channels/serialize-channels.ts +0 -34
  77. package/src/core/serialize-pikku-types.ts +0 -55
  78. package/src/http/serialize-route-imports.ts +0 -24
  79. package/src/http/serialize-route-meta.ts +0 -10
  80. package/src/scheduler/serialize-schedulers.ts +0 -41
  81. /package/dist/bin/{pikku-http.d.ts → pikku-http-routes.d.ts} +0 -0
  82. /package/dist/src/{openapi/openapi-spec-generator.d.ts → openapi-spec-generator.d.ts} +0 -0
  83. /package/dist/src/{openapi/openapi-spec-generator.js → openapi-spec-generator.js} +0 -0
  84. /package/dist/src/{http/serialize-fetch-wrapper.d.ts → serialize-fetch-wrapper.d.ts} +0 -0
  85. /package/dist/src/{http/serialize-fetch-wrapper.js → serialize-fetch-wrapper.js} +0 -0
  86. /package/dist/src/{core/serialize-import-map.d.ts → serialize-import-map.d.ts} +0 -0
  87. /package/dist/src/{nextjs/serialize-nextjs-backend-wrapper.d.ts → serialize-nextjs-backend-wrapper.d.ts} +0 -0
  88. /package/dist/src/{nextjs/serialize-nextjs-backend-wrapper.js → serialize-nextjs-backend-wrapper.js} +0 -0
  89. /package/dist/src/{nextjs/serialize-nextjs-http-wrapper.d.ts → serialize-nextjs-http-wrapper.d.ts} +0 -0
  90. /package/dist/src/{nextjs/serialize-nextjs-http-wrapper.js → serialize-nextjs-http-wrapper.js} +0 -0
  91. /package/dist/src/{core/serialize-pikku-types.d.ts → serialize-pikku-types.d.ts} +0 -0
  92. /package/dist/src/{channels/serialize-typed-channel-map.d.ts → serialize-typed-channel-map.d.ts} +0 -0
  93. /package/dist/src/{http/serialize-typed-route-map.d.ts → serialize-typed-function-map.d.ts} +0 -0
  94. /package/dist/src/{channels/serialize-websocket-wrapper.d.ts → serialize-websocket-wrapper.d.ts} +0 -0
  95. /package/dist/src/{channels/serialize-websocket-wrapper.js → serialize-websocket-wrapper.js} +0 -0
  96. /package/src/{openapi/openapi-spec-generator.ts → openapi-spec-generator.ts} +0 -0
  97. /package/src/{http/serialize-fetch-wrapper.ts → serialize-fetch-wrapper.ts} +0 -0
  98. /package/src/{nextjs/serialize-nextjs-backend-wrapper.ts → serialize-nextjs-backend-wrapper.ts} +0 -0
  99. /package/src/{nextjs/serialize-nextjs-http-wrapper.ts → serialize-nextjs-http-wrapper.ts} +0 -0
  100. /package/src/{channels/serialize-websocket-wrapper.ts → serialize-websocket-wrapper.ts} +0 -0
@@ -1,13 +1,19 @@
1
- import { OpenAPISpecInfo } from './openapi/openapi-spec-generator.js';
1
+ import { OpenAPISpecInfo } from './openapi-spec-generator.js';
2
2
  import { InspectorFilters } from '@pikku/inspector';
3
3
  export interface PikkuCLICoreOutputFiles {
4
4
  outDir?: string;
5
- routesFile: string;
5
+ functionsFile: string;
6
+ functionsMetaFile: string;
7
+ httpRoutesFile: string;
8
+ httpRoutesMetaFile: string;
6
9
  channelsFile: string;
10
+ channelsMetaFile: string;
7
11
  schedulersFile: string;
12
+ schedulersMetaFile: string;
13
+ rpcFile: string;
8
14
  schemaDirectory: string;
9
15
  typesDeclarationFile: string;
10
- routesMapDeclarationFile: string;
16
+ httpRoutesMapDeclarationFile: string;
11
17
  channelsMapDeclarationFile: string;
12
18
  bootstrapFile: string;
13
19
  }
@@ -15,7 +21,7 @@ export type PikkuCLIConfig = {
15
21
  $schema?: string;
16
22
  extends?: string;
17
23
  rootDir: string;
18
- routeDirectories: string[];
24
+ srcDirectories: string[];
19
25
  packageMappings: Record<string, string>;
20
26
  supportsImportAttributes: boolean;
21
27
  configDir: string;
@@ -56,20 +56,38 @@ const _getPikkuCLIConfig = async (configFile = undefined, requiredFields, tags =
56
56
  if (!result.schemaDirectory) {
57
57
  result.schemaDirectory = join(result.outDir, 'pikku-schemas');
58
58
  }
59
- if (!result.routesFile) {
60
- result.routesFile = join(result.outDir, 'pikku-routes.gen.ts');
59
+ if (!result.functionsFile) {
60
+ result.functionsFile = join(result.outDir, 'pikku-functions.gen.ts');
61
+ }
62
+ if (!result.functionsMetaFile) {
63
+ result.functionsMetaFile = join(result.outDir, 'pikku-functions-meta.gen.ts');
64
+ }
65
+ if (!result.rpcFile) {
66
+ result.rpcFile = join(result.outDir, 'pikku-rpc.gen.ts');
67
+ }
68
+ if (!result.httpRoutesFile) {
69
+ result.httpRoutesFile = join(result.outDir, 'pikku-http-routes.gen.ts');
70
+ }
71
+ if (!result.httpRoutesMetaFile) {
72
+ result.httpRoutesMetaFile = join(result.outDir, 'pikku-http-routes-meta.gen.ts');
61
73
  }
62
74
  if (!result.schedulersFile) {
63
75
  result.schedulersFile = join(result.outDir, 'pikku-schedules.gen.ts');
64
76
  }
77
+ if (!result.schedulersMetaFile) {
78
+ result.schedulersMetaFile = join(result.outDir, 'pikku-schedules-meta.gen.ts');
79
+ }
65
80
  if (!result.channelsFile) {
66
81
  result.channelsFile = join(result.outDir, 'pikku-channels.gen.ts');
67
82
  }
83
+ if (!result.channelsMetaFile) {
84
+ result.channelsMetaFile = join(result.outDir, 'pikku-channels-meta.gen.ts');
85
+ }
68
86
  if (!result.typesDeclarationFile) {
69
87
  result.typesDeclarationFile = join(result.outDir, 'pikku-types.gen.ts');
70
88
  }
71
- if (!result.routesMapDeclarationFile) {
72
- result.routesMapDeclarationFile = join(result.outDir, 'pikku-routes-map.gen.d.ts');
89
+ if (!result.httpRoutesMapDeclarationFile) {
90
+ result.httpRoutesMapDeclarationFile = join(result.outDir, 'pikku-routes-map.gen.d.ts');
73
91
  }
74
92
  if (!result.channelsMapDeclarationFile) {
75
93
  result.channelsMapDeclarationFile = join(result.outDir, 'pikku-channels-map.gen.d.ts');
@@ -1,5 +1,5 @@
1
1
  import { JSONValue } from '@pikku/core';
2
2
  import { HTTPRoutesMeta } from '@pikku/core/http';
3
3
  import { TypesMap } from '@pikku/inspector';
4
- export declare function generateSchemas(tsconfig: string, typesMap: TypesMap, routesMeta: HTTPRoutesMeta): Promise<Record<string, JSONValue>>;
4
+ export declare function generateSchemas(tsconfig: string, typesMaps: TypesMap[], httpRoutesMeta: HTTPRoutesMeta): Promise<Record<string, JSONValue>>;
5
5
  export declare function saveSchemas(schemaParentDir: string, schemas: Record<string, JSONValue>, typesMap: TypesMap, routesMeta: HTTPRoutesMeta, supportsImportAttributes: boolean): Promise<void>;
@@ -1,15 +1,36 @@
1
1
  import { createGenerator, RootlessError } from 'ts-json-schema-generator';
2
- import { logInfo, writeFileInDir } from '../utils.js';
2
+ import { logInfo, writeFileInDir } from './utils.js';
3
3
  import { mkdir, writeFile } from 'fs/promises';
4
- export async function generateSchemas(tsconfig, typesMap, routesMeta) {
5
- const schemasSet = new Set(typesMap.customTypes.keys());
6
- for (const { input, output, inputTypes } of routesMeta) {
4
+ export async function generateSchemas(tsconfig, typesMaps, httpRoutesMeta) {
5
+ const schemasSet = new Set(typesMaps.flatMap((tm) => [...tm.customTypes.keys()]));
6
+ for (const { input, inputTypes } of httpRoutesMeta) {
7
7
  if (input) {
8
- schemasSet.add(typesMap.getTypeMeta(input).uniqueName);
9
- }
10
- if (output) {
11
- schemasSet.add(typesMap.getTypeMeta(output).uniqueName);
8
+ let found = false;
9
+ for (const typesMap of typesMaps) {
10
+ try {
11
+ const uniqueName = typesMap.getUniqueName(input);
12
+ if (uniqueName) {
13
+ found = true;
14
+ schemasSet.add(uniqueName);
15
+ break;
16
+ }
17
+ }
18
+ catch (e) { }
19
+ }
20
+ if (!found) {
21
+ console.error('Input type not found in any types map:', input);
22
+ }
12
23
  }
24
+ // if (output) {
25
+ // for (const typesMap of typesMaps) {
26
+ // const uniqueName = typesMap.getUniqueName(output)
27
+ // if (uniqueName) {
28
+ // console.log('Adding output schema:', uniqueName)
29
+ // schemasSet.add(uniqueName)
30
+ // break
31
+ // }
32
+ // }
33
+ // }
13
34
  if (inputTypes?.body) {
14
35
  schemasSet.add(inputTypes.body);
15
36
  }
@@ -1,9 +1,10 @@
1
- import { getFileImportRelativePath } from '../utils.js';
1
+ import { getFileImportRelativePath } from './utils.js';
2
2
  export const serializeImportMap = (relativeToPath, packageMappings, typesMap, requiredTypes) => {
3
3
  const paths = new Map();
4
4
  Array.from(requiredTypes).forEach((requiredType) => {
5
5
  const { originalName, uniqueName, path } = typesMap.getTypeMeta(requiredType);
6
6
  if (!path) {
7
+ // This is a custom type that exists in file, so we don't need to import it
7
8
  return;
8
9
  }
9
10
  const variables = paths.get(path) || [];
@@ -0,0 +1,136 @@
1
+ /**
2
+ *
3
+ */
4
+ export const serializePikkuTypes = (userSessionTypeImport, userSessionTypeName, singletonServicesTypeImport, singletonServicesTypeName, sessionServicesTypeImport, servicesTypeName) => {
5
+ return `/**
6
+ * This is used to provide the application types in the typescript project
7
+ */
8
+
9
+ import { CoreAPIPermission, PikkuMiddleware } from '@pikku/core'
10
+ import { CoreAPIFunction, CoreAPIFunctionSessionless } from '@pikku/core/function'
11
+ import { CoreHTTPFunctionRoute, AssertRouteParams, addHTTPRoute as addCoreHTTPRoute } from '@pikku/core/http'
12
+ import { CoreScheduledTask, addScheduledTask as addCoreScheduledTask } from '@pikku/core/scheduler'
13
+ import { CoreAPIChannel, PikkuChannel, addChannel as addCoreChannel } from '@pikku/core/channel'
14
+
15
+ ${userSessionTypeImport}
16
+ ${singletonServicesTypeImport}
17
+ ${sessionServicesTypeImport}
18
+
19
+ export type APIPermission<In = unknown, RequiredServices extends ${singletonServicesTypeName} = ${singletonServicesTypeName}> = CoreAPIPermission<In, RequiredServices, ${userSessionTypeName}>
20
+ export type APIMiddleware<RequiredServices extends ${singletonServicesTypeName} = ${singletonServicesTypeName}> = PikkuMiddleware<RequiredServices, ${userSessionTypeName}>
21
+
22
+ type APIFunctionSessionless<
23
+ In = unknown,
24
+ Out = never,
25
+ ChannelData = null, // null means optional channel
26
+ RequiredServices extends Services = Services & (
27
+ [ChannelData] extends [null]
28
+ ? { channel?: PikkuChannel<unknown, Out> } // Optional channel
29
+ : { channel: PikkuChannel<ChannelData, Out> } // Required channel with any data type
30
+ )
31
+ > = CoreAPIFunctionSessionless<In, Out, ChannelData, RequiredServices, ${userSessionTypeName}>
32
+
33
+ type APIFunction<
34
+ In = unknown,
35
+ Out = never,
36
+ ChannelData = null, // null means optional channel
37
+ RequiredServices extends Services = Services & (
38
+ [ChannelData] extends [null]
39
+ ? { channel?: PikkuChannel<unknown, Out> } // Optional channel
40
+ : { channel: PikkuChannel<ChannelData, Out> } // Required channel with any data type
41
+ )
42
+ > = CoreAPIFunction<In, Out, ChannelData, RequiredServices, ${userSessionTypeName}>
43
+
44
+ type APIRoute<In, Out, Route extends string> = CoreHTTPFunctionRoute<In, Out, Route, APIFunction<In, Out>, APIFunctionSessionless<In, Out>, APIPermission<In>, APIMiddleware>
45
+ type APIChannel<ChannelData, Channel extends string> = CoreAPIChannel<ChannelData, Channel, APIFunction<void, unknown> | APIFunction<void, unknown, ChannelData>, APIFunction<void, void> | APIFunction<void, void, ChannelData>, APIFunction<any, any> | APIFunction<any, any, ChannelData>, APIPermission>
46
+ type ScheduledTask = CoreScheduledTask<APIFunctionSessionless<void, void>, ${userSessionTypeName}>
47
+
48
+ export const pikkuFunc = <In, Out = unknown>(
49
+ func:
50
+ | APIFunction<In, Out>
51
+ | {
52
+ func: APIFunction<In, Out>
53
+ auth?: true
54
+ name?: string
55
+ }
56
+ | {
57
+ func: APIFunctionSessionless<In, Out>
58
+ auth: false
59
+ name?: string
60
+ }
61
+ ) => {
62
+ return typeof func === 'function' ? func : func.func
63
+ }
64
+
65
+ export const pikkuSessionlessFunc = <In, Out = unknown>(
66
+ func:
67
+ | APIFunctionSessionless<In, Out>
68
+ | {
69
+ func: APIFunctionSessionless<In, Out>
70
+ name?: string
71
+ }
72
+ ) => {
73
+ return typeof func === 'function' ? func : func.func
74
+ }
75
+
76
+ export const pikkuChannelConnectionFunc = <Out = unknown, ChannelData = unknown>(
77
+ func:
78
+ | APIFunctionSessionless<void, Out, ChannelData>
79
+ | {
80
+ func: APIFunctionSessionless<void, Out, ChannelData>
81
+ name?: string
82
+ }
83
+ ) => {
84
+ return typeof func === 'function' ? func : func.func
85
+ }
86
+
87
+ export const pikkuChannelDisconnectionFunc = <ChannelData = unknown>(
88
+ func:
89
+ | APIFunctionSessionless<void, void, ChannelData>
90
+ | {
91
+ func: APIFunction<void, void, ChannelData>
92
+ name?: string
93
+ }
94
+ ) => {
95
+ return typeof func === 'function' ? func : func.func
96
+ }
97
+
98
+ export const pikkuChannelFunc = <In = unknown, Out = unknown, ChannelData = unknown>(
99
+ func:
100
+ | APIFunctionSessionless<In, Out, ChannelData>
101
+ | {
102
+ func: APIFunctionSessionless<In, Out, ChannelData>
103
+ name?: string
104
+ }
105
+ ) => {
106
+ return typeof func === 'function' ? func : func.func
107
+ }
108
+
109
+ export const pikkuVoidFunc = (
110
+ func:
111
+ | APIFunctionSessionless<void, void>
112
+ | {
113
+ func: APIFunctionSessionless<void, void>
114
+ name?: string
115
+ }
116
+ ) => {
117
+ return typeof func === 'function' ? func : func.func
118
+ }
119
+
120
+ export const addChannel = <ChannelData, Channel extends string>(
121
+ channel: APIChannel<ChannelData, Channel> & AssertRouteParams<ChannelData, Channel>
122
+ ) => {
123
+ addCoreChannel(channel as any) // TODO
124
+ }
125
+
126
+ export const addHTTPRoute = <In, Out, Route extends string>(
127
+ route: APIRoute<In, Out, Route> & AssertRouteParams<In, Route>
128
+ ) => {
129
+ addCoreHTTPRoute(route)
130
+ }
131
+
132
+ export const addScheduledTask = (task: ScheduledTask) => {
133
+ addCoreScheduledTask(task as any) // TODO
134
+ }
135
+ `;
136
+ };
@@ -1,3 +1,2 @@
1
1
  import { ScheduledTasksMeta } from '@pikku/core/scheduler';
2
- export declare const serializeSchedulers: (outputPath: string, filesWithScheduledTasks: Set<string>, packageMappings?: Record<string, string>) => string;
3
2
  export declare const serializeSchedulerMeta: (scheduledTasksMeta: ScheduledTasksMeta) => string;
@@ -0,0 +1,10 @@
1
+ export const serializeSchedulerMeta = (scheduledTasksMeta) => {
2
+ const serializedOutput = [];
3
+ serializedOutput.push("import { pikkuState } from '@pikku/core'");
4
+ serializedOutput.push(`pikkuState('scheduler', 'meta', ${JSON.stringify(scheduledTasksMeta, null, 2)})`);
5
+ const scheduledTasksMetaValues = Object.values(scheduledTasksMeta);
6
+ if (scheduledTasksMetaValues.length > 0) {
7
+ serializedOutput.push(`export type ScheduledTaskNames = '${scheduledTasksMetaValues.map((s) => s.name).join("' | '")}'`);
8
+ }
9
+ return serializedOutput.join('\n');
10
+ };
@@ -1,5 +1,5 @@
1
- import { serializeImportMap } from '../core/serialize-import-map.js';
2
- import { generateCustomTypes } from '../http/serialize-typed-route-map.js';
1
+ import { serializeImportMap } from './serialize-import-map.js';
2
+ import { generateCustomTypes } from './serialize-typed-http-map.js';
3
3
  export const serializeTypedChannelsMap = (relativeToPath, packageMappings, typesMap, channelsMeta) => {
4
4
  const { channels, requiredTypes } = generateChannels(channelsMeta);
5
5
  typesMap.customTypes.forEach(({ references }) => {
@@ -41,7 +41,7 @@ export type ChannelRouteHandlerOf<
41
41
  function generateChannels(channelsMeta) {
42
42
  const requiredTypes = new Set();
43
43
  const channelsObject = {};
44
- for (const meta of channelsMeta) {
44
+ for (const meta of Object.values(channelsMeta)) {
45
45
  const { name, messageRoutes, message } = meta;
46
46
  if (!channelsObject[name]) {
47
47
  channelsObject[name] = { message, routes: {} };
@@ -70,7 +70,7 @@ function generateChannels(channelsMeta) {
70
70
  for (const [key, methods] of Object.entries(routes)) {
71
71
  routesStr += ` readonly ${key}: {\n`;
72
72
  for (const [method, handler] of Object.entries(methods)) {
73
- routesStr += ` readonly ${method}: ChannelHandler<${formatTypeArray(handler.inputTypes)}, ${formatTypeArray(handler.outputTypes) || 'never'}>,\n`;
73
+ routesStr += ` readonly ${method}: ChannelHandler<${formatTypeArray(handler.inputTypes) || 'void'}, ${formatTypeArray(handler.outputTypes) || 'never'}>,\n`;
74
74
  }
75
75
  routesStr += ' },\n';
76
76
  }
@@ -79,6 +79,9 @@ function generateChannels(channelsMeta) {
79
79
  if (message) {
80
80
  routesStr += ` readonly defaultMessage: ChannelHandler<${formatTypeArray(message.inputs)}, ${formatTypeArray(message.outputs)}>,\n`;
81
81
  }
82
+ else {
83
+ routesStr += ` readonly defaultMessage: never,\n`;
84
+ }
82
85
  routesStr += ' },\n';
83
86
  }
84
87
  routesStr += '};';
@@ -1,10 +1,10 @@
1
- import { serializeImportMap } from '../core/serialize-import-map.js';
1
+ import { serializeImportMap } from './serialize-import-map.js';
2
2
  export const serializeTypedRoutesMap = (relativeToPath, packageMappings, typesMap, routesMeta, metaTypes) => {
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
  */
@@ -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 './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
+ };
@@ -38,4 +38,5 @@ export declare const writeFileInDir: (path: string, content: string, ignoreModif
38
38
  export declare const logCommandInfoAndTime: (commandStart: string, commandEnd: string, [skipCondition, skipMessage]: [boolean] | [boolean, string], callback: (...args: any[]) => Promise<unknown>) => Promise<boolean>;
39
39
  export declare const logPikkuLogo: () => void;
40
40
  export declare const DO_NOT_MODIFY_COMMENT = "/**\n * This file was generated by the @pikku/cli\n */\n";
41
+ export declare const serializeFileImports: (importType: string, outputPath: string, files: Set<string>, packageMappings?: Record<string, string>) => string;
41
42
  export {};
package/dist/src/utils.js CHANGED
@@ -18,17 +18,17 @@ export const getFileImportRelativePath = (from, to, packageMappings) => {
18
18
  if (!/^\.+\//.test(filePath)) {
19
19
  filePath = `./${filePath}`;
20
20
  }
21
- let usesPackageName = false;
21
+ // let usesPackageName = false
22
22
  for (const [path, packageName] of Object.entries(packageMappings)) {
23
23
  if (filePath.includes(path)) {
24
- usesPackageName = true;
24
+ // usesPackageName = true
25
25
  filePath = filePath.replace(new RegExp(`.*${path}`), packageName);
26
26
  break;
27
27
  }
28
28
  }
29
- if (usesPackageName) {
30
- return filePath.replace('.ts', '');
31
- }
29
+ // if (usesPackageName) {
30
+ // return filePath.replace('.ts', '')
31
+ // }
32
32
  return filePath.replace('.ts', '.js');
33
33
  };
34
34
  const getMetaTypes = (type, errors, map, desiredType) => {
@@ -131,3 +131,15 @@ export const DO_NOT_MODIFY_COMMENT = `/**
131
131
  * This file was generated by the @pikku/cli
132
132
  */
133
133
  `;
134
+ export const serializeFileImports = (importType, outputPath, files, packageMappings = {}) => {
135
+ const serializedOutput = [
136
+ `/* The files with an ${importType} function call */`,
137
+ ];
138
+ Array.from(files)
139
+ .sort()
140
+ .forEach((path) => {
141
+ const filePath = getFileImportRelativePath(outputPath, path, packageMappings);
142
+ serializedOutput.push(`import '${filePath}'`);
143
+ });
144
+ return serializedOutput.join('\n');
145
+ };
@@ -1 +1 @@
1
- {"root":["../bin/pikku-all.ts","../bin/pikku-channels-map.ts","../bin/pikku-channels.ts","../bin/pikku-fetch.ts","../bin/pikku-function-types.ts","../bin/pikku-http.ts","../bin/pikku-nextjs.ts","../bin/pikku-openapi.ts","../bin/pikku-routes-map.ts","../bin/pikku-scheduler.ts","../bin/pikku-schemas.ts","../bin/pikku-websocket.ts","../bin/pikku.ts","../src/inspector-glob.ts","../src/pikku-cli-config.ts","../src/utils.ts","../src/channels/serialize-channels.ts","../src/channels/serialize-typed-channel-map.ts","../src/channels/serialize-websocket-wrapper.ts","../src/core/serialize-import-map.ts","../src/core/serialize-pikku-types.ts","../src/http/serialize-fetch-wrapper.ts","../src/http/serialize-route-imports.ts","../src/http/serialize-route-meta.ts","../src/http/serialize-typed-route-map.ts","../src/nextjs/serialize-nextjs-backend-wrapper.ts","../src/nextjs/serialize-nextjs-http-wrapper.ts","../src/openapi/openapi-spec-generator.ts","../src/scheduler/serialize-schedulers.ts","../src/schema/schema-generator.ts"],"version":"5.7.3"}
1
+ {"root":["../bin/pikku-all.ts","../bin/pikku-channels-map.ts","../bin/pikku-channels.ts","../bin/pikku-fetch.ts","../bin/pikku-function-types.ts","../bin/pikku-functions.ts","../bin/pikku-http-map.ts","../bin/pikku-http-routes.ts","../bin/pikku-nextjs.ts","../bin/pikku-openapi.ts","../bin/pikku-rpc.ts","../bin/pikku-scheduler.ts","../bin/pikku-schemas.ts","../bin/pikku-websocket.ts","../bin/pikku.ts","../src/inspector-glob.ts","../src/openapi-spec-generator.ts","../src/pikku-cli-config.ts","../src/schema-generator.ts","../src/serialize-fetch-wrapper.ts","../src/serialize-import-map.ts","../src/serialize-nextjs-backend-wrapper.ts","../src/serialize-nextjs-http-wrapper.ts","../src/serialize-pikku-types.ts","../src/serialize-scheduler-meta.ts","../src/serialize-typed-channel-map.ts","../src/serialize-typed-function-map.ts","../src/serialize-typed-http-map.ts","../src/serialize-websocket-wrapper.ts","../src/utils.ts"],"version":"5.7.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/cli",
3
- "version": "0.6.20",
3
+ "version": "0.7.1",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -22,8 +22,8 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@openapi-contrib/json-schema-to-openapi-schema": "^3.0.2",
25
- "@pikku/core": "^0.6.24",
26
- "@pikku/inspector": "^0.6.4",
25
+ "@pikku/core": "^0.7.3",
26
+ "@pikku/inspector": "^0.7.3",
27
27
  "@types/cookie": "^0.6.0",
28
28
  "@types/uuid": "^10.0.0",
29
29
  "chalk": "^5.4.1",
@@ -5,7 +5,7 @@ import { logCommandInfoAndTime } from './utils.js'
5
5
 
6
6
  export const inspectorGlob = async (
7
7
  rootDir: string,
8
- routeDirectories: string[],
8
+ srcDirectories: string[],
9
9
  filters: InspectorFilters
10
10
  ) => {
11
11
  let result: InspectorState
@@ -16,7 +16,7 @@ export const inspectorGlob = async (
16
16
  async () => {
17
17
  const routeFiles = (
18
18
  await Promise.all(
19
- routeDirectories.map((dir) =>
19
+ srcDirectories.map((dir) =>
20
20
  glob(`${path.join(rootDir, dir)}/**/*.ts`)
21
21
  )
22
22
  )
@@ -1,16 +1,22 @@
1
1
  import { join, dirname, resolve, isAbsolute } from 'path'
2
2
  import { readdir, readFile } from 'fs/promises'
3
- import { OpenAPISpecInfo } from './openapi/openapi-spec-generator.js'
3
+ import { OpenAPISpecInfo } from './openapi-spec-generator.js'
4
4
  import { InspectorFilters } from '@pikku/inspector'
5
5
 
6
6
  export interface PikkuCLICoreOutputFiles {
7
7
  outDir?: string
8
- routesFile: string
8
+ functionsFile: string
9
+ functionsMetaFile: string
10
+ httpRoutesFile: string
11
+ httpRoutesMetaFile: string
9
12
  channelsFile: string
13
+ channelsMetaFile: string
10
14
  schedulersFile: string
15
+ schedulersMetaFile: string
16
+ rpcFile: string
11
17
  schemaDirectory: string
12
18
  typesDeclarationFile: string
13
- routesMapDeclarationFile: string
19
+ httpRoutesMapDeclarationFile: string
14
20
  channelsMapDeclarationFile: string
15
21
  bootstrapFile: string
16
22
  }
@@ -21,7 +27,7 @@ export type PikkuCLIConfig = {
21
27
  extends?: string
22
28
 
23
29
  rootDir: string
24
- routeDirectories: string[]
30
+ srcDirectories: string[]
25
31
  packageMappings: Record<string, string>
26
32
  supportsImportAttributes: boolean
27
33
 
@@ -121,20 +127,50 @@ const _getPikkuCLIConfig = async (
121
127
  if (!result.schemaDirectory) {
122
128
  result.schemaDirectory = join(result.outDir, 'pikku-schemas')
123
129
  }
124
- if (!result.routesFile) {
125
- result.routesFile = join(result.outDir, 'pikku-routes.gen.ts')
130
+ if (!result.functionsFile) {
131
+ result.functionsFile = join(result.outDir, 'pikku-functions.gen.ts')
132
+ }
133
+ if (!result.functionsMetaFile) {
134
+ result.functionsMetaFile = join(
135
+ result.outDir,
136
+ 'pikku-functions-meta.gen.ts'
137
+ )
138
+ }
139
+ if (!result.rpcFile) {
140
+ result.rpcFile = join(result.outDir, 'pikku-rpc.gen.ts')
141
+ }
142
+ if (!result.httpRoutesFile) {
143
+ result.httpRoutesFile = join(result.outDir, 'pikku-http-routes.gen.ts')
144
+ }
145
+ if (!result.httpRoutesMetaFile) {
146
+ result.httpRoutesMetaFile = join(
147
+ result.outDir,
148
+ 'pikku-http-routes-meta.gen.ts'
149
+ )
126
150
  }
127
151
  if (!result.schedulersFile) {
128
152
  result.schedulersFile = join(result.outDir, 'pikku-schedules.gen.ts')
129
153
  }
154
+ if (!result.schedulersMetaFile) {
155
+ result.schedulersMetaFile = join(
156
+ result.outDir,
157
+ 'pikku-schedules-meta.gen.ts'
158
+ )
159
+ }
130
160
  if (!result.channelsFile) {
131
161
  result.channelsFile = join(result.outDir, 'pikku-channels.gen.ts')
132
162
  }
163
+ if (!result.channelsMetaFile) {
164
+ result.channelsMetaFile = join(
165
+ result.outDir,
166
+ 'pikku-channels-meta.gen.ts'
167
+ )
168
+ }
133
169
  if (!result.typesDeclarationFile) {
134
170
  result.typesDeclarationFile = join(result.outDir, 'pikku-types.gen.ts')
135
171
  }
136
- if (!result.routesMapDeclarationFile) {
137
- result.routesMapDeclarationFile = join(
172
+ if (!result.httpRoutesMapDeclarationFile) {
173
+ result.httpRoutesMapDeclarationFile = join(
138
174
  result.outDir,
139
175
  'pikku-routes-map.gen.d.ts'
140
176
  )