@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,5 +1,5 @@
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
4
  import { JSONValue } from '@pikku/core'
5
5
  import { HTTPRoutesMeta } from '@pikku/core/http'
@@ -7,17 +7,39 @@ import { TypesMap } from '@pikku/inspector'
7
7
 
8
8
  export async function generateSchemas(
9
9
  tsconfig: string,
10
- typesMap: TypesMap,
11
- routesMeta: HTTPRoutesMeta
10
+ typesMaps: TypesMap[],
11
+ httpRoutesMeta: HTTPRoutesMeta
12
12
  ): Promise<Record<string, JSONValue>> {
13
- const schemasSet = new Set(typesMap.customTypes.keys())
14
- for (const { input, output, inputTypes } of routesMeta) {
13
+ const schemasSet = new Set(
14
+ typesMaps.flatMap((tm) => [...tm.customTypes.keys()])
15
+ )
16
+ for (const { input, inputTypes } of httpRoutesMeta) {
15
17
  if (input) {
16
- schemasSet.add(typesMap.getTypeMeta(input).uniqueName)
17
- }
18
- if (output) {
19
- schemasSet.add(typesMap.getTypeMeta(output).uniqueName)
18
+ let found = false
19
+ for (const typesMap of typesMaps) {
20
+ try {
21
+ const uniqueName = typesMap.getUniqueName(input)
22
+ if (uniqueName) {
23
+ found = true
24
+ schemasSet.add(uniqueName)
25
+ break
26
+ }
27
+ } catch (e) {}
28
+ }
29
+ if (!found) {
30
+ console.error('Input type not found in any types map:', input)
31
+ }
20
32
  }
33
+ // if (output) {
34
+ // for (const typesMap of typesMaps) {
35
+ // const uniqueName = typesMap.getUniqueName(output)
36
+ // if (uniqueName) {
37
+ // console.log('Adding output schema:', uniqueName)
38
+ // schemasSet.add(uniqueName)
39
+ // break
40
+ // }
41
+ // }
42
+ // }
21
43
  if (inputTypes?.body) {
22
44
  schemasSet.add(inputTypes.body)
23
45
  }
@@ -1,5 +1,5 @@
1
1
  import { TypesMap } from '@pikku/inspector'
2
- import { getFileImportRelativePath } from '../utils.js'
2
+ import { getFileImportRelativePath } from './utils.js'
3
3
 
4
4
  export const serializeImportMap = (
5
5
  relativeToPath: string,
@@ -12,6 +12,7 @@ export const serializeImportMap = (
12
12
  const { originalName, uniqueName, path } =
13
13
  typesMap.getTypeMeta(requiredType)
14
14
  if (!path) {
15
+ // This is a custom type that exists in file, so we don't need to import it
15
16
  return
16
17
  }
17
18
  const variables = paths.get(path) || []
@@ -0,0 +1,143 @@
1
+ /**
2
+ *
3
+ */
4
+ export const serializePikkuTypes = (
5
+ userSessionTypeImport: string,
6
+ userSessionTypeName: string,
7
+ singletonServicesTypeImport: string,
8
+ singletonServicesTypeName: string,
9
+ sessionServicesTypeImport: string,
10
+ servicesTypeName: string
11
+ ) => {
12
+ return `/**
13
+ * This is used to provide the application types in the typescript project
14
+ */
15
+
16
+ import { CoreAPIPermission, PikkuMiddleware } from '@pikku/core'
17
+ import { CoreAPIFunction, CoreAPIFunctionSessionless } from '@pikku/core/function'
18
+ import { CoreHTTPFunctionRoute, AssertRouteParams, addHTTPRoute as addCoreHTTPRoute } from '@pikku/core/http'
19
+ import { CoreScheduledTask, addScheduledTask as addCoreScheduledTask } from '@pikku/core/scheduler'
20
+ import { CoreAPIChannel, PikkuChannel, addChannel as addCoreChannel } from '@pikku/core/channel'
21
+
22
+ ${userSessionTypeImport}
23
+ ${singletonServicesTypeImport}
24
+ ${sessionServicesTypeImport}
25
+
26
+ export type APIPermission<In = unknown, RequiredServices extends ${singletonServicesTypeName} = ${singletonServicesTypeName}> = CoreAPIPermission<In, RequiredServices, ${userSessionTypeName}>
27
+ export type APIMiddleware<RequiredServices extends ${singletonServicesTypeName} = ${singletonServicesTypeName}> = PikkuMiddleware<RequiredServices, ${userSessionTypeName}>
28
+
29
+ type APIFunctionSessionless<
30
+ In = unknown,
31
+ Out = never,
32
+ ChannelData = null, // null means optional channel
33
+ RequiredServices extends Services = Services & (
34
+ [ChannelData] extends [null]
35
+ ? { channel?: PikkuChannel<unknown, Out> } // Optional channel
36
+ : { channel: PikkuChannel<ChannelData, Out> } // Required channel with any data type
37
+ )
38
+ > = CoreAPIFunctionSessionless<In, Out, ChannelData, RequiredServices, ${userSessionTypeName}>
39
+
40
+ type APIFunction<
41
+ In = unknown,
42
+ Out = never,
43
+ ChannelData = null, // null means optional channel
44
+ RequiredServices extends Services = Services & (
45
+ [ChannelData] extends [null]
46
+ ? { channel?: PikkuChannel<unknown, Out> } // Optional channel
47
+ : { channel: PikkuChannel<ChannelData, Out> } // Required channel with any data type
48
+ )
49
+ > = CoreAPIFunction<In, Out, ChannelData, RequiredServices, ${userSessionTypeName}>
50
+
51
+ type APIRoute<In, Out, Route extends string> = CoreHTTPFunctionRoute<In, Out, Route, APIFunction<In, Out>, APIFunctionSessionless<In, Out>, APIPermission<In>, APIMiddleware>
52
+ 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>
53
+ type ScheduledTask = CoreScheduledTask<APIFunctionSessionless<void, void>, ${userSessionTypeName}>
54
+
55
+ export const pikkuFunc = <In, Out = unknown>(
56
+ func:
57
+ | APIFunction<In, Out>
58
+ | {
59
+ func: APIFunction<In, Out>
60
+ auth?: true
61
+ name?: string
62
+ }
63
+ | {
64
+ func: APIFunctionSessionless<In, Out>
65
+ auth: false
66
+ name?: string
67
+ }
68
+ ) => {
69
+ return typeof func === 'function' ? func : func.func
70
+ }
71
+
72
+ export const pikkuSessionlessFunc = <In, Out = unknown>(
73
+ func:
74
+ | APIFunctionSessionless<In, Out>
75
+ | {
76
+ func: APIFunctionSessionless<In, Out>
77
+ name?: string
78
+ }
79
+ ) => {
80
+ return typeof func === 'function' ? func : func.func
81
+ }
82
+
83
+ export const pikkuChannelConnectionFunc = <Out = unknown, ChannelData = unknown>(
84
+ func:
85
+ | APIFunctionSessionless<void, Out, ChannelData>
86
+ | {
87
+ func: APIFunctionSessionless<void, Out, ChannelData>
88
+ name?: string
89
+ }
90
+ ) => {
91
+ return typeof func === 'function' ? func : func.func
92
+ }
93
+
94
+ export const pikkuChannelDisconnectionFunc = <ChannelData = unknown>(
95
+ func:
96
+ | APIFunctionSessionless<void, void, ChannelData>
97
+ | {
98
+ func: APIFunction<void, void, ChannelData>
99
+ name?: string
100
+ }
101
+ ) => {
102
+ return typeof func === 'function' ? func : func.func
103
+ }
104
+
105
+ export const pikkuChannelFunc = <In = unknown, Out = unknown, ChannelData = unknown>(
106
+ func:
107
+ | APIFunctionSessionless<In, Out, ChannelData>
108
+ | {
109
+ func: APIFunctionSessionless<In, Out, ChannelData>
110
+ name?: string
111
+ }
112
+ ) => {
113
+ return typeof func === 'function' ? func : func.func
114
+ }
115
+
116
+ export const pikkuVoidFunc = (
117
+ func:
118
+ | APIFunctionSessionless<void, void>
119
+ | {
120
+ func: APIFunctionSessionless<void, void>
121
+ name?: string
122
+ }
123
+ ) => {
124
+ return typeof func === 'function' ? func : func.func
125
+ }
126
+
127
+ export const addChannel = <ChannelData, Channel extends string>(
128
+ channel: APIChannel<ChannelData, Channel> & AssertRouteParams<ChannelData, Channel>
129
+ ) => {
130
+ addCoreChannel(channel as any) // TODO
131
+ }
132
+
133
+ export const addHTTPRoute = <In, Out, Route extends string>(
134
+ route: APIRoute<In, Out, Route> & AssertRouteParams<In, Route>
135
+ ) => {
136
+ addCoreHTTPRoute(route)
137
+ }
138
+
139
+ export const addScheduledTask = (task: ScheduledTask) => {
140
+ addCoreScheduledTask(task as any) // TODO
141
+ }
142
+ `
143
+ }
@@ -0,0 +1,18 @@
1
+ import { ScheduledTasksMeta } from '@pikku/core/scheduler'
2
+
3
+ export const serializeSchedulerMeta = (
4
+ scheduledTasksMeta: ScheduledTasksMeta
5
+ ) => {
6
+ const serializedOutput: string[] = []
7
+ serializedOutput.push("import { pikkuState } from '@pikku/core'")
8
+ serializedOutput.push(
9
+ `pikkuState('scheduler', 'meta', ${JSON.stringify(scheduledTasksMeta, null, 2)})`
10
+ )
11
+ const scheduledTasksMetaValues = Object.values(scheduledTasksMeta)
12
+ if (scheduledTasksMetaValues.length > 0) {
13
+ serializedOutput.push(
14
+ `export type ScheduledTaskNames = '${scheduledTasksMetaValues.map((s) => s.name).join("' | '")}'`
15
+ )
16
+ }
17
+ return serializedOutput.join('\n')
18
+ }
@@ -1,7 +1,7 @@
1
1
  import { ChannelsMeta } from '@pikku/core/channel'
2
- import { serializeImportMap } from '../core/serialize-import-map.js'
2
+ import { serializeImportMap } from './serialize-import-map.js'
3
3
  import { TypesMap } from '@pikku/inspector'
4
- import { generateCustomTypes } from '../http/serialize-typed-route-map.js'
4
+ import { generateCustomTypes } from './serialize-typed-http-map.js'
5
5
 
6
6
  export const serializeTypedChannelsMap = (
7
7
  relativeToPath: string,
@@ -71,7 +71,7 @@ function generateChannels(channelsMeta: ChannelsMeta) {
71
71
  }
72
72
  > = {}
73
73
 
74
- for (const meta of channelsMeta) {
74
+ for (const meta of Object.values(channelsMeta)) {
75
75
  const { name, messageRoutes, message } = meta
76
76
 
77
77
  if (!channelsObject[name]) {
@@ -107,9 +107,9 @@ function generateChannels(channelsMeta: ChannelsMeta) {
107
107
  for (const [key, methods] of Object.entries(routes)) {
108
108
  routesStr += ` readonly ${key}: {\n`
109
109
  for (const [method, handler] of Object.entries(methods)) {
110
- routesStr += ` readonly ${method}: ChannelHandler<${formatTypeArray(
111
- handler.inputTypes
112
- )}, ${formatTypeArray(handler.outputTypes) || 'never'}>,\n`
110
+ routesStr += ` readonly ${method}: ChannelHandler<${
111
+ formatTypeArray(handler.inputTypes) || 'void'
112
+ }, ${formatTypeArray(handler.outputTypes) || 'never'}>,\n`
113
113
  }
114
114
  routesStr += ' },\n'
115
115
  }
@@ -120,6 +120,8 @@ function generateChannels(channelsMeta: ChannelsMeta) {
120
120
  routesStr += ` readonly defaultMessage: ChannelHandler<${formatTypeArray(
121
121
  message.inputs
122
122
  )}, ${formatTypeArray(message.outputs)}>,\n`
123
+ } else {
124
+ routesStr += ` readonly defaultMessage: never,\n`
123
125
  }
124
126
 
125
127
  routesStr += ' },\n'
@@ -1,5 +1,5 @@
1
1
  import { HTTPRoutesMeta } from '@pikku/core/http'
2
- import { serializeImportMap } from '../core/serialize-import-map.js'
2
+ import { serializeImportMap } from './serialize-import-map.js'
3
3
  import { MetaInputTypes, TypesMap } from '@pikku/inspector'
4
4
 
5
5
  export const serializeTypedRoutesMap = (
@@ -12,13 +12,14 @@ export const serializeTypedRoutesMap = (
12
12
  const requiredTypes = new Set<string>()
13
13
  const serializedCustomTypes = generateCustomTypes(typesMap, requiredTypes)
14
14
  const serializedMetaTypes = generateMetaTypes(metaTypes, typesMap)
15
+ const serializedRoutes = generateRoutes(routesMeta, typesMap, requiredTypes)
16
+
15
17
  const serializedImportMap = serializeImportMap(
16
18
  relativeToPath,
17
19
  packageMappings,
18
20
  typesMap,
19
21
  requiredTypes
20
22
  )
21
- const serializedRoutes = generateRoutes(routesMeta, typesMap, requiredTypes)
22
23
 
23
24
  return `/**
24
25
  * This provides the structure needed for typescript to be aware of routes and their return types
@@ -0,0 +1,151 @@
1
+ import { HTTPRoutesMeta } from '@pikku/core/http'
2
+ import { serializeImportMap } from './serialize-import-map.js'
3
+ import { MetaInputTypes, TypesMap } from '@pikku/inspector'
4
+
5
+ export const serializeTypedRoutesMap = (
6
+ relativeToPath: string,
7
+ packageMappings: Record<string, string>,
8
+ typesMap: TypesMap,
9
+ routesMeta: HTTPRoutesMeta,
10
+ metaTypes: MetaInputTypes
11
+ ) => {
12
+ const requiredTypes = new Set<string>()
13
+ const serializedCustomTypes = generateCustomTypes(typesMap, requiredTypes)
14
+ const serializedMetaTypes = generateMetaTypes(metaTypes, typesMap)
15
+ const serializedRoutes = generateRoutes(routesMeta, typesMap, requiredTypes)
16
+
17
+ const serializedImportMap = serializeImportMap(
18
+ relativeToPath,
19
+ packageMappings,
20
+ typesMap,
21
+ requiredTypes
22
+ )
23
+
24
+ return `/**
25
+ * This provides the structure needed for typescript to be aware of routes and their return types
26
+ */
27
+
28
+ ${serializedImportMap}
29
+ ${serializedCustomTypes}
30
+ ${serializedMetaTypes}
31
+
32
+ interface RouteHandler<I, O> {
33
+ input: I;
34
+ output: O;
35
+ }
36
+
37
+ ${serializedRoutes}
38
+
39
+ export type RouteHandlerOf<Route extends keyof RoutesMap, Method extends keyof RoutesMap[Route]> =
40
+ RoutesMap[Route][Method] extends { input: infer I; output: infer O }
41
+ ? RouteHandler<I, O>
42
+ : never;
43
+
44
+ export type RoutesWithMethod<Method extends string> = {
45
+ [Route in keyof RoutesMap]: Method extends keyof RoutesMap[Route] ? Route : never;
46
+ }[keyof RoutesMap];
47
+ `
48
+ }
49
+
50
+ export function generateCustomTypes(
51
+ typesMap: TypesMap,
52
+ requiredTypes: Set<string>
53
+ ) {
54
+ return `
55
+ // Custom types are those that are defined directly within generics
56
+ // or are broken into simpler types
57
+ ${Array.from(typesMap.customTypes.entries())
58
+ .map(([name, { type, references }]) => {
59
+ references.forEach((name) => {
60
+ const originalName = typesMap.getTypeMeta(name).originalName
61
+ requiredTypes.add(originalName)
62
+ })
63
+ return `export type ${name} = ${type}`
64
+ })
65
+ .join('\n')}`
66
+ }
67
+
68
+ function generateRoutes(
69
+ routesMeta: HTTPRoutesMeta,
70
+ typesMap: TypesMap,
71
+ requiredTypes: Set<string>
72
+ ) {
73
+ // Initialize an object to collect routes
74
+ const routesObj: Record<
75
+ string,
76
+ Record<string, { inputType: string; outputType: string }>
77
+ > = {}
78
+
79
+ for (const meta of routesMeta) {
80
+ const { route, method, input, output } = meta
81
+
82
+ // Initialize the route entry if it doesn't exist
83
+ if (!routesObj[route]) {
84
+ routesObj[route] = {}
85
+ }
86
+
87
+ // Store the input and output types separately for RouteHandler
88
+ const inputType = input ? typesMap.getTypeMeta(input).uniqueName : 'null'
89
+ const outputType = output ? typesMap.getTypeMeta(output).uniqueName : 'null'
90
+
91
+ requiredTypes.add(inputType)
92
+ requiredTypes.add(outputType)
93
+
94
+ // Add method entry
95
+ routesObj[route][method] = {
96
+ inputType,
97
+ outputType,
98
+ }
99
+ }
100
+
101
+ // Build the routes object as a string
102
+ let routesStr = 'export type RoutesMap = {\n'
103
+
104
+ for (const [routePath, methods] of Object.entries(routesObj)) {
105
+ routesStr += ` readonly '${routePath}': {\n`
106
+ for (const [method, handler] of Object.entries(methods)) {
107
+ routesStr += ` readonly ${method.toUpperCase()}: RouteHandler<${handler.inputType}, ${handler.outputType}>,\n`
108
+ }
109
+ routesStr += ' },\n'
110
+ }
111
+
112
+ routesStr += '};'
113
+
114
+ return routesStr
115
+ }
116
+
117
+ const generateMetaTypes = (metaTypes: MetaInputTypes, typesMap: TypesMap) => {
118
+ const nameToTypeMap = Array.from(metaTypes.entries()).reduce<
119
+ Map<string, string>
120
+ >((result, [_name, { query, body, params }]) => {
121
+ const { uniqueName } = typesMap.getTypeMeta(_name)
122
+ const queryType =
123
+ query && query.length > 0
124
+ ? `Pick<${uniqueName}, '${query?.join("' | '")}'>`
125
+ : undefined
126
+ if (queryType) {
127
+ result.set(`${uniqueName}Query`, queryType)
128
+ }
129
+ const paramsType =
130
+ params && params.length > 0
131
+ ? `Pick<${uniqueName}, '${params.join("' | '")}'>`
132
+ : undefined
133
+ if (paramsType) {
134
+ result.set(`${uniqueName}Params`, paramsType)
135
+ }
136
+ const bodyType =
137
+ (body && body.length > 0) || (params && params.length > 0)
138
+ ? `Omit<${uniqueName}, '${[...new Set([...(query || []), ...(params || [])])].join("' | '")}'>`
139
+ : uniqueName!
140
+ if (bodyType) {
141
+ result.set(`${uniqueName}Body`, bodyType)
142
+ }
143
+ return result
144
+ }, new Map())
145
+
146
+ return `
147
+ // The '& {}' is a workaround for not directly refering to a type since it confuses typescript
148
+ ${Array.from(nameToTypeMap.entries())
149
+ .map(([name, type]) => `export type ${name} = ${type} & {}`)
150
+ .join('\n')}`
151
+ }
package/src/utils.ts CHANGED
@@ -28,17 +28,17 @@ export const getFileImportRelativePath = (
28
28
  if (!/^\.+\//.test(filePath)) {
29
29
  filePath = `./${filePath}`
30
30
  }
31
- let usesPackageName = false
31
+ // let usesPackageName = false
32
32
  for (const [path, packageName] of Object.entries(packageMappings)) {
33
33
  if (filePath.includes(path)) {
34
- usesPackageName = true
34
+ // usesPackageName = true
35
35
  filePath = filePath.replace(new RegExp(`.*${path}`), packageName)
36
36
  break
37
37
  }
38
38
  }
39
- if (usesPackageName) {
40
- return filePath.replace('.ts', '')
41
- }
39
+ // if (usesPackageName) {
40
+ // return filePath.replace('.ts', '')
41
+ // }
42
42
  return filePath.replace('.ts', '.js')
43
43
  }
44
44
 
@@ -258,3 +258,27 @@ export const DO_NOT_MODIFY_COMMENT = `/**
258
258
  * This file was generated by the @pikku/cli
259
259
  */
260
260
  `
261
+
262
+ export const serializeFileImports = (
263
+ importType: string,
264
+ outputPath: string,
265
+ files: Set<string>,
266
+ packageMappings: Record<string, string> = {}
267
+ ) => {
268
+ const serializedOutput: string[] = [
269
+ `/* The files with an ${importType} function call */`,
270
+ ]
271
+
272
+ Array.from(files)
273
+ .sort()
274
+ .forEach((path) => {
275
+ const filePath = getFileImportRelativePath(
276
+ outputPath,
277
+ path,
278
+ packageMappings
279
+ )
280
+ serializedOutput.push(`import '${filePath}'`)
281
+ })
282
+
283
+ return serializedOutput.join('\n')
284
+ }
@@ -1,3 +0,0 @@
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;
@@ -1,19 +0,0 @@
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
- };
@@ -1,48 +0,0 @@
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 { CoreAPIFunction, CoreAPIFunctionSessionless, CoreAPIPermission, PikkuMiddleware, MakeRequired } from '@pikku/core'
10
- import { CoreHTTPFunctionRoute, AssertRouteParams, addRoute as addCoreHTTP } from '@pikku/core/http'
11
- import { CoreScheduledTask, addScheduledTask as addCoreScheduledTask } from '@pikku/core/scheduler'
12
- import { CoreAPIChannel, PikkuChannel, addChannel as addCoreChannel } from '@pikku/core/channel'
13
-
14
- ${userSessionTypeImport}
15
- ${singletonServicesTypeImport}
16
- ${sessionServicesTypeImport}
17
-
18
- export type APIPermission<In = unknown, RequiredServices extends ${singletonServicesTypeName} = ${singletonServicesTypeName}> = CoreAPIPermission<In, RequiredServices, ${userSessionTypeName}>
19
- export type APIMiddleware<RequiredServices extends ${singletonServicesTypeName} = ${singletonServicesTypeName}> = PikkuMiddleware<RequiredServices, ${userSessionTypeName}>
20
-
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>
24
-
25
- export type ChannelConnection<Out = unknown, ChannelData = unknown, RequiredServices extends ${servicesTypeName} = ${servicesTypeName}> = (services: MakeRequired<RequiredServices, 'userSession'>, channel: PikkuChannel<ChannelData, Out>) => Promise<void>
26
- 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>
29
-
30
- type ScheduledTask = CoreScheduledTask<APIFunctionSessionless<void, void>, ${userSessionTypeName}>
31
-
32
- export const addChannel = <ChannelData, Channel extends string>(
33
- channel: APIChannel<ChannelData, Channel> & AssertRouteParams<ChannelData, Channel>
34
- ) => {
35
- addCoreChannel(channel as any) // TODO
36
- }
37
-
38
- export const addRoute = <In, Out, Route extends string>(
39
- route: APIRoute<In, Out, Route> & AssertRouteParams<In, Route>
40
- ) => {
41
- addCoreHTTP(route)
42
- }
43
-
44
- export const addScheduledTask = (task: ScheduledTask) => {
45
- addCoreScheduledTask(task as any) // TODO
46
- }
47
- `;
48
- };
@@ -1 +0,0 @@
1
- export declare const serializeRoutes: (outputPath: string, filesWithRoutes: Set<string>, packageMappings?: Record<string, string>) => string;
@@ -1,13 +0,0 @@
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
- };
@@ -1,2 +0,0 @@
1
- import type { HTTPRoutesMeta } from '@pikku/core/http';
2
- export declare const serializeHTTPRoutesMeta: (routesMeta: HTTPRoutesMeta) => string;
@@ -1,6 +0,0 @@
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
- };
@@ -1,22 +0,0 @@
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
- if (scheduledTasksMeta.length > 0) {
19
- serializedOutput.push(`export type ScheduledTaskNames = '${scheduledTasksMeta.map((s) => s.name).join("' | '")}'`);
20
- }
21
- return serializedOutput.join('\n');
22
- };
@@ -1,34 +0,0 @@
1
- import { ChannelsMeta } from '@pikku/core/channel'
2
- import { getFileImportRelativePath } from '../utils.js'
3
-
4
- export const serializeChannels = (
5
- outputPath: string,
6
- filesWithChannels: Set<string>,
7
- packageMappings: Record<string, string> = {}
8
- ) => {
9
- const serializedOutput: string[] = [
10
- '/* The files with an addChannel function call */',
11
- ]
12
-
13
- Array.from(filesWithChannels)
14
- .sort()
15
- .forEach((path) => {
16
- const filePath = getFileImportRelativePath(
17
- outputPath,
18
- path,
19
- packageMappings
20
- )
21
- serializedOutput.push(`import '${filePath}'`)
22
- })
23
-
24
- return serializedOutput.join('\n')
25
- }
26
-
27
- export const serializeChannelMeta = (channelsMeta: ChannelsMeta) => {
28
- const serializedOutput: string[] = []
29
- serializedOutput.push("import { pikkuState } from '@pikku/core'")
30
- serializedOutput.push(
31
- `pikkuState('channel', 'meta', ${JSON.stringify(channelsMeta, null, 2)})`
32
- )
33
- return serializedOutput.join('\n')
34
- }