@pikku/cli 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/bin/pikku-all.ts +13 -6
- package/bin/pikku-nextjs.ts +3 -3
- package/cli.schema.json +4 -0
- package/dist/bin/pikku-all.js +10 -6
- package/dist/bin/pikku-nextjs.js +3 -3
- package/dist/src/pikku-cli-config.d.ts +3 -0
- package/dist/src/pikku-cli-config.js +15 -4
- package/dist/src/serialize-import-map.js +62 -1
- package/dist/src/serialize-pikku-types.js +30 -27
- package/dist/src/utils.js +24 -2
- package/dist/src/wirings/functions/pikku-command-function-types.js +2 -2
- package/dist/src/wirings/functions/pikku-command-functions.d.ts +0 -4
- package/dist/src/wirings/functions/pikku-command-functions.js +10 -31
- package/dist/src/wirings/functions/pikku-command-services.js +1 -1
- package/dist/src/wirings/functions/pikku-function-types.js +2 -2
- package/dist/src/wirings/functions/serialize-function-imports.d.ts +6 -0
- package/dist/src/wirings/functions/serialize-function-imports.js +59 -0
- package/dist/src/wirings/rpc/pikku-command-rpc-client.js +3 -3
- package/dist/src/wirings/rpc/pikku-command-rpc-map.d.ts +2 -1
- package/dist/src/wirings/rpc/pikku-command-rpc-map.js +9 -3
- package/dist/src/wirings/rpc/pikku-command-rpc.js +7 -2
- package/dist/src/wirings/rpc/serialize-typed-rpc-map.d.ts +1 -2
- package/dist/src/wirings/rpc/serialize-typed-rpc-map.js +2 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -11
- package/src/pikku-cli-config.ts +35 -5
- package/src/serialize-import-map.ts +67 -2
- package/src/serialize-pikku-types.ts +30 -27
- package/src/utils.ts +31 -2
- package/src/wirings/functions/pikku-command-function-types.ts +6 -2
- package/src/wirings/functions/pikku-command-functions.ts +28 -64
- package/src/wirings/functions/pikku-command-services.ts +1 -1
- package/src/wirings/functions/pikku-function-types.ts +6 -2
- package/src/wirings/functions/serialize-function-imports.ts +97 -0
- package/src/wirings/rpc/pikku-command-rpc-client.ts +9 -5
- package/src/wirings/rpc/pikku-command-rpc-map.ts +27 -4
- package/src/wirings/rpc/pikku-command-rpc.ts +16 -6
- package/src/wirings/rpc/serialize-typed-rpc-map.ts +4 -5
- package/dist/src/wirings/functions/pikku-functions.d.ts +0 -6
- package/dist/src/wirings/functions/pikku-functions.js +0 -35
- package/dist/src/wirings/rpc/pikku-rpc.d.ts +0 -2
- package/dist/src/wirings/rpc/pikku-rpc.js +0 -6
- package/src/wirings/functions/pikku-functions.ts +0 -84
- package/src/wirings/rpc/pikku-rpc.ts +0 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# @pikku/cli
|
|
2
2
|
|
|
3
|
+
## 0.9.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 9691aba: fix: add-functions should support both functions only and objects
|
|
8
|
+
- 2ab0278: refactor: no longer import ALL functions, only the ones used by rpcs
|
|
9
|
+
- 81005ba: feat: creating a smaller meta file for functions to reduce size
|
|
10
|
+
- b3c2829: fix (using ai): generating custom types broke imports.. this fixes it, but needs more robust training
|
|
11
|
+
- Updated dependencies [9691aba]
|
|
12
|
+
- Updated dependencies [2ab0278]
|
|
13
|
+
- Updated dependencies [81005ba]
|
|
14
|
+
- Updated dependencies [b3c2829]
|
|
15
|
+
- @pikku/inspector@0.9.3
|
|
16
|
+
- @pikku/core@0.9.3
|
|
17
|
+
|
|
18
|
+
## 0.9.2
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 1256238: feat: pikkufunc in types extends function config to include all the different params
|
|
23
|
+
- d3a9a09: refactor: change addMiddleware to addHTTPMiddleware due to route support'
|
|
24
|
+
|
|
25
|
+
chore: export addHTTPMiddleware from pikku-types for consistency
|
|
26
|
+
|
|
27
|
+
- 840e078: refactor: change APIMiddleware type to PikkuMiddleware
|
|
28
|
+
- a5905a9: chore: updating all dependencies
|
|
29
|
+
- Updated dependencies [1256238]
|
|
30
|
+
- Updated dependencies [6cf8efd]
|
|
31
|
+
- Updated dependencies [d3a9a09]
|
|
32
|
+
- Updated dependencies [840e078]
|
|
33
|
+
- Updated dependencies [667d23c]
|
|
34
|
+
- Updated dependencies [a5905a9]
|
|
35
|
+
- @pikku/core@0.9.2
|
|
36
|
+
- @pikku/inspector@0.9.2
|
|
37
|
+
|
|
3
38
|
## 0.9.1
|
|
4
39
|
|
|
5
40
|
### Patch Changes
|
package/bin/pikku-all.ts
CHANGED
|
@@ -17,7 +17,10 @@ import chokidar from 'chokidar'
|
|
|
17
17
|
import { pikkuFunctions } from '../src/wirings/functions/pikku-command-functions.js'
|
|
18
18
|
import { pikkuServices } from '../src/wirings/functions/pikku-command-services.js'
|
|
19
19
|
import { pikkuRPC } from '../src/wirings/rpc/pikku-command-rpc.js'
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
pikkuRPCExposedMap,
|
|
22
|
+
pikkuRPCInternalMap,
|
|
23
|
+
} from '../src/wirings/rpc/pikku-command-rpc-map.js'
|
|
21
24
|
import { pikkuQueue } from '../src/wirings/queue/pikku-command-queue.js'
|
|
22
25
|
import { pikkuQueueMap } from '../src/wirings/queue/pikku-command-queue-map.js'
|
|
23
26
|
import { pikkuFetch } from '../src/wirings/fetch/index.js'
|
|
@@ -39,7 +42,10 @@ const generateBootstrapFile = async (
|
|
|
39
42
|
schemas?: boolean
|
|
40
43
|
) => {
|
|
41
44
|
// Common imports that every bootstrap file needs
|
|
42
|
-
const commonImports = [
|
|
45
|
+
const commonImports = [
|
|
46
|
+
cliConfig.functionsMetaMinFile,
|
|
47
|
+
cliConfig.functionsFile,
|
|
48
|
+
]
|
|
43
49
|
|
|
44
50
|
// Add schema if it exists
|
|
45
51
|
if (schemas) {
|
|
@@ -106,7 +112,8 @@ const runAll = async (
|
|
|
106
112
|
await pikkuServices(logger, cliConfig, visitState)
|
|
107
113
|
|
|
108
114
|
await pikkuRPC(logger, cliConfig, visitState)
|
|
109
|
-
await
|
|
115
|
+
await pikkuRPCInternalMap(logger, cliConfig, visitState)
|
|
116
|
+
await pikkuRPCExposedMap(logger, cliConfig, visitState)
|
|
110
117
|
await pikkuRPCClient(logger, cliConfig)
|
|
111
118
|
allImports.push(cliConfig.rpcWiringMetaFile)
|
|
112
119
|
|
|
@@ -319,13 +326,13 @@ export const all = (program: Command): void => {
|
|
|
319
326
|
program
|
|
320
327
|
.command('all', { isDefault: true })
|
|
321
328
|
.description('Generate all the files used by pikku')
|
|
322
|
-
.option('
|
|
329
|
+
.option('--pikku-config-type', 'The type of your pikku config object')
|
|
323
330
|
.option(
|
|
324
|
-
'
|
|
331
|
+
'--singleton-services-factory-type',
|
|
325
332
|
'The type of your singleton services factory'
|
|
326
333
|
)
|
|
327
334
|
.option(
|
|
328
|
-
'
|
|
335
|
+
'--session-services-factory-type',
|
|
329
336
|
'The type of your session services factory'
|
|
330
337
|
)
|
|
331
338
|
.option('-c | --config <string>', 'The path to pikku cli config file')
|
package/bin/pikku-nextjs.ts
CHANGED
|
@@ -30,13 +30,13 @@ export const nextjs = (program: Command): void => {
|
|
|
30
30
|
program
|
|
31
31
|
.command('nextjs')
|
|
32
32
|
.description('generate nextjs wrapper')
|
|
33
|
-
.option('
|
|
33
|
+
.option('--pikku-config-type', 'The type of your pikku config object')
|
|
34
34
|
.option(
|
|
35
|
-
'
|
|
35
|
+
'--singleton-services-factory-type',
|
|
36
36
|
'The type of your singleton services factory'
|
|
37
37
|
)
|
|
38
38
|
.option(
|
|
39
|
-
'
|
|
39
|
+
'--session-services-factory-type',
|
|
40
40
|
'The type of your session services factory'
|
|
41
41
|
)
|
|
42
42
|
.option('-c | --config <string>', 'The path to pikku cli config file')
|
package/cli.schema.json
CHANGED
|
@@ -199,6 +199,9 @@
|
|
|
199
199
|
"functionsMetaFile": {
|
|
200
200
|
"type": "string"
|
|
201
201
|
},
|
|
202
|
+
"functionsMetaMinFile": {
|
|
203
|
+
"type": "string"
|
|
204
|
+
},
|
|
202
205
|
"httpMapDeclarationFile": {
|
|
203
206
|
"type": "string"
|
|
204
207
|
},
|
|
@@ -316,6 +319,7 @@
|
|
|
316
319
|
"filters",
|
|
317
320
|
"functionsFile",
|
|
318
321
|
"functionsMetaFile",
|
|
322
|
+
"functionsMetaMinFile",
|
|
319
323
|
"httpMapDeclarationFile",
|
|
320
324
|
"httpWiringMetaFile",
|
|
321
325
|
"httpWiringsFile",
|
package/dist/bin/pikku-all.js
CHANGED
|
@@ -11,7 +11,7 @@ import chokidar from 'chokidar';
|
|
|
11
11
|
import { pikkuFunctions } from '../src/wirings/functions/pikku-command-functions.js';
|
|
12
12
|
import { pikkuServices } from '../src/wirings/functions/pikku-command-services.js';
|
|
13
13
|
import { pikkuRPC } from '../src/wirings/rpc/pikku-command-rpc.js';
|
|
14
|
-
import {
|
|
14
|
+
import { pikkuRPCExposedMap, pikkuRPCInternalMap, } from '../src/wirings/rpc/pikku-command-rpc-map.js';
|
|
15
15
|
import { pikkuQueue } from '../src/wirings/queue/pikku-command-queue.js';
|
|
16
16
|
import { pikkuQueueMap } from '../src/wirings/queue/pikku-command-queue-map.js';
|
|
17
17
|
import { pikkuFetch } from '../src/wirings/fetch/index.js';
|
|
@@ -26,7 +26,10 @@ import { pikkuMCPJSON } from '../src/wirings/mcp/pikku-command-mcp-json.js';
|
|
|
26
26
|
import { pikkuNext } from '../src/runtimes/nextjs/pikku-command-nextjs.js';
|
|
27
27
|
const generateBootstrapFile = async (logger, cliConfig, bootstrapFile, specificImports, schemas) => {
|
|
28
28
|
// Common imports that every bootstrap file needs
|
|
29
|
-
const commonImports = [
|
|
29
|
+
const commonImports = [
|
|
30
|
+
cliConfig.functionsMetaMinFile,
|
|
31
|
+
cliConfig.functionsFile,
|
|
32
|
+
];
|
|
30
33
|
// Add schema if it exists
|
|
31
34
|
if (schemas) {
|
|
32
35
|
commonImports.push(`${cliConfig.schemaDirectory}/register.gen.ts`);
|
|
@@ -61,7 +64,8 @@ const runAll = async (logger, cliConfig, options) => {
|
|
|
61
64
|
// Generate services map
|
|
62
65
|
await pikkuServices(logger, cliConfig, visitState);
|
|
63
66
|
await pikkuRPC(logger, cliConfig, visitState);
|
|
64
|
-
await
|
|
67
|
+
await pikkuRPCInternalMap(logger, cliConfig, visitState);
|
|
68
|
+
await pikkuRPCExposedMap(logger, cliConfig, visitState);
|
|
65
69
|
await pikkuRPCClient(logger, cliConfig);
|
|
66
70
|
allImports.push(cliConfig.rpcWiringMetaFile);
|
|
67
71
|
const schemas = await pikkuSchemas(logger, cliConfig, visitState);
|
|
@@ -177,9 +181,9 @@ export const all = (program) => {
|
|
|
177
181
|
program
|
|
178
182
|
.command('all', { isDefault: true })
|
|
179
183
|
.description('Generate all the files used by pikku')
|
|
180
|
-
.option('
|
|
181
|
-
.option('
|
|
182
|
-
.option('
|
|
184
|
+
.option('--pikku-config-type', 'The type of your pikku config object')
|
|
185
|
+
.option('--singleton-services-factory-type', 'The type of your singleton services factory')
|
|
186
|
+
.option('--session-services-factory-type', 'The type of your session services factory')
|
|
183
187
|
.option('-c | --config <string>', 'The path to pikku cli config file')
|
|
184
188
|
.option('-t | --tags <tags...>', 'Which tags to filter by')
|
|
185
189
|
.option('--types <types...>', 'Which types to filter by (http, channel, queue, scheduler, rpc, mcp)')
|
package/dist/bin/pikku-nextjs.js
CHANGED
|
@@ -16,9 +16,9 @@ export const nextjs = (program) => {
|
|
|
16
16
|
program
|
|
17
17
|
.command('nextjs')
|
|
18
18
|
.description('generate nextjs wrapper')
|
|
19
|
-
.option('
|
|
20
|
-
.option('
|
|
21
|
-
.option('
|
|
19
|
+
.option('--pikku-config-type', 'The type of your pikku config object')
|
|
20
|
+
.option('--singleton-services-factory-type', 'The type of your singleton services factory')
|
|
21
|
+
.option('--session-services-factory-type', 'The type of your session services factory')
|
|
22
22
|
.option('-c | --config <string>', 'The path to pikku cli config file')
|
|
23
23
|
.action(action);
|
|
24
24
|
};
|
|
@@ -7,12 +7,15 @@ export interface PikkuCLICoreOutputFiles {
|
|
|
7
7
|
typesDeclarationFile: string;
|
|
8
8
|
functionsFile: string;
|
|
9
9
|
functionsMetaFile: string;
|
|
10
|
+
functionsMetaMinFile: string;
|
|
10
11
|
httpWiringsFile: string;
|
|
11
12
|
httpWiringMetaFile: string;
|
|
12
13
|
httpMapDeclarationFile: string;
|
|
13
14
|
channelsWiringFile: string;
|
|
14
15
|
channelsWiringMetaFile: string;
|
|
15
16
|
channelsMapDeclarationFile: string;
|
|
17
|
+
rpcInternalWiringMetaFile: string;
|
|
18
|
+
rpcInternalMapDeclarationFile: string;
|
|
16
19
|
rpcWiringMetaFile: string;
|
|
17
20
|
rpcMapDeclarationFile: string;
|
|
18
21
|
schedulersWiringFile: string;
|
|
@@ -61,7 +61,8 @@ const _getPikkuCLIConfig = async (configFile = undefined, requiredFields, filter
|
|
|
61
61
|
const functionDir = join(result.outDir, 'function');
|
|
62
62
|
const httpDir = join(result.outDir, 'http');
|
|
63
63
|
const channelDir = join(result.outDir, 'channel');
|
|
64
|
-
const
|
|
64
|
+
const internalRPCDirectory = join(result.outDir, 'rpc-internal');
|
|
65
|
+
const externalRPCDirectory = join(result.outDir, 'rpc');
|
|
65
66
|
const schedulerDir = join(result.outDir, 'scheduler');
|
|
66
67
|
const queueDir = join(result.outDir, 'queue');
|
|
67
68
|
const mcpDir = join(result.outDir, 'mcp');
|
|
@@ -76,6 +77,9 @@ const _getPikkuCLIConfig = async (configFile = undefined, requiredFields, filter
|
|
|
76
77
|
if (!result.functionsMetaFile) {
|
|
77
78
|
result.functionsMetaFile = join(functionDir, 'pikku-functions-meta.gen.ts');
|
|
78
79
|
}
|
|
80
|
+
if (!result.functionsMetaMinFile) {
|
|
81
|
+
result.functionsMetaMinFile = join(functionDir, 'pikku-functions-meta.min.gen.ts');
|
|
82
|
+
}
|
|
79
83
|
if (!result.typesDeclarationFile) {
|
|
80
84
|
result.typesDeclarationFile = join(result.outDir, 'pikku-types.gen.ts');
|
|
81
85
|
}
|
|
@@ -99,12 +103,19 @@ const _getPikkuCLIConfig = async (configFile = undefined, requiredFields, filter
|
|
|
99
103
|
if (!result.channelsMapDeclarationFile) {
|
|
100
104
|
result.channelsMapDeclarationFile = join(channelDir, 'pikku-channels-map.gen.d.ts');
|
|
101
105
|
}
|
|
102
|
-
//
|
|
106
|
+
// Internal
|
|
107
|
+
if (!result.rpcInternalWiringMetaFile) {
|
|
108
|
+
result.rpcInternalWiringMetaFile = join(internalRPCDirectory, 'pikku-rpc-wirings-meta.internal.gen.ts');
|
|
109
|
+
}
|
|
110
|
+
if (!result.rpcInternalMapDeclarationFile) {
|
|
111
|
+
result.rpcInternalMapDeclarationFile = join(internalRPCDirectory, 'pikku-rpc-wirings-map.internal.gen.d.ts');
|
|
112
|
+
}
|
|
113
|
+
// External
|
|
103
114
|
if (!result.rpcWiringMetaFile) {
|
|
104
|
-
result.rpcWiringMetaFile = join(
|
|
115
|
+
result.rpcWiringMetaFile = join(externalRPCDirectory, 'pikku-rpc-wirings-meta.gen.ts');
|
|
105
116
|
}
|
|
106
117
|
if (!result.rpcMapDeclarationFile) {
|
|
107
|
-
result.rpcMapDeclarationFile = join(
|
|
118
|
+
result.rpcMapDeclarationFile = join(externalRPCDirectory, 'pikku-rpc-wirings-map.gen.d.ts');
|
|
108
119
|
}
|
|
109
120
|
// Scheduler
|
|
110
121
|
if (!result.schedulersWiringFile) {
|
|
@@ -2,7 +2,68 @@ 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
|
+
let originalName, uniqueName, path;
|
|
6
|
+
try {
|
|
7
|
+
const typeMeta = typesMap.getTypeMeta(requiredType);
|
|
8
|
+
originalName = typeMeta.originalName;
|
|
9
|
+
uniqueName = typeMeta.uniqueName;
|
|
10
|
+
path = typeMeta.path;
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
// Handle missing types by trying to find a suitable import path
|
|
14
|
+
// Look through all existing types in the map to find a path that might contain this type
|
|
15
|
+
let foundPath = null;
|
|
16
|
+
// Get all unique paths from the typesMap
|
|
17
|
+
const allPaths = new Set();
|
|
18
|
+
typesMap.customTypes.forEach(({ type, references }) => {
|
|
19
|
+
references.forEach((ref) => {
|
|
20
|
+
try {
|
|
21
|
+
const refMeta = typesMap.getTypeMeta(ref);
|
|
22
|
+
if (refMeta.path) {
|
|
23
|
+
allPaths.add(refMeta.path);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Continue
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
// Also check direct types in the map
|
|
32
|
+
try {
|
|
33
|
+
const mapEntries = typesMap.map?.entries?.() || [];
|
|
34
|
+
for (const [_, typeMeta] of mapEntries) {
|
|
35
|
+
if (typeMeta.path) {
|
|
36
|
+
allPaths.add(typeMeta.path);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// Continue
|
|
42
|
+
}
|
|
43
|
+
// For PascalCase types, prefer paths that look like type definition files
|
|
44
|
+
if (/^[A-Z]/.test(requiredType)) {
|
|
45
|
+
for (const candidatePath of allPaths) {
|
|
46
|
+
if (candidatePath.includes('types') ||
|
|
47
|
+
candidatePath.includes('.d.')) {
|
|
48
|
+
foundPath = candidatePath;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// If no types file found, use the first available path
|
|
53
|
+
if (!foundPath && allPaths.size > 0) {
|
|
54
|
+
foundPath = Array.from(allPaths)[0] || null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (foundPath) {
|
|
58
|
+
originalName = requiredType;
|
|
59
|
+
uniqueName = requiredType;
|
|
60
|
+
path = foundPath;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// No suitable path found, skip
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
6
67
|
if (!path) {
|
|
7
68
|
// This is a custom type that exists in file, so we don't need to import it
|
|
8
69
|
return;
|
|
@@ -6,7 +6,7 @@ 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 { CorePikkuPermission,
|
|
9
|
+
import { CorePikkuFunctionConfig, CorePikkuPermission, CorePikkuMiddleware, addHTTPMiddleware } from '@pikku/core'
|
|
10
10
|
import { CorePikkuFunction, CorePikkuFunctionSessionless } from '@pikku/core/function'
|
|
11
11
|
import { CoreHTTPFunctionWiring, AssertHTTPWiringParams, wireHTTP as wireHTTPCore } from '@pikku/core/http'
|
|
12
12
|
import { CoreScheduledTask, wireScheduler as wireSchedulerCore } from '@pikku/core/scheduler'
|
|
@@ -34,7 +34,7 @@ export type PikkuPermission<In = unknown, RequiredServices extends ${singletonSe
|
|
|
34
34
|
*
|
|
35
35
|
* @template RequiredServices - The services required for this middleware
|
|
36
36
|
*/
|
|
37
|
-
export type
|
|
37
|
+
export type PikkuMiddleware<RequiredServices extends ${singletonServicesTypeName} = ${singletonServicesTypeName}> = CorePikkuMiddleware<RequiredServices, ${userSessionTypeName}>
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* A sessionless API function that doesn't require user authentication.
|
|
@@ -51,7 +51,7 @@ type PikkuFunctionSessionless<
|
|
|
51
51
|
Out = never,
|
|
52
52
|
ChannelData = null, // null means optional channel
|
|
53
53
|
MCPData = null, // null means optional MCP
|
|
54
|
-
RequiredServices extends Services = Services &
|
|
54
|
+
RequiredServices extends Services = Omit<Services, 'rpc'> &
|
|
55
55
|
{ rpc: TypedPikkuRPC } & (
|
|
56
56
|
[ChannelData] extends [null]
|
|
57
57
|
? { channel?: PikkuChannel<unknown, Out> } // Optional channel
|
|
@@ -77,7 +77,7 @@ type PikkuFunction<
|
|
|
77
77
|
Out = never,
|
|
78
78
|
ChannelData = null, // null means optional channel
|
|
79
79
|
MCPData = null, // null means optional MCP
|
|
80
|
-
RequiredServices extends Services = Services &
|
|
80
|
+
RequiredServices extends Services = Omit<Services, 'rpc'> &
|
|
81
81
|
{ rpc: TypedPikkuRPC } & (
|
|
82
82
|
[ChannelData] extends [null]
|
|
83
83
|
? { channel?: PikkuChannel<unknown, Out> } // Optional channel
|
|
@@ -96,7 +96,7 @@ type PikkuFunction<
|
|
|
96
96
|
* @template Out - Output type for the HTTP wiring
|
|
97
97
|
* @template Route - String literal type for the HTTP path (e.g., "/users/:id")
|
|
98
98
|
*/
|
|
99
|
-
type HTTPWiring<In, Out, Route extends string> = CoreHTTPFunctionWiring<In, Out, Route, PikkuFunction<In, Out>, PikkuFunctionSessionless<In, Out>, PikkuPermission<In>,
|
|
99
|
+
type HTTPWiring<In, Out, Route extends string> = CoreHTTPFunctionWiring<In, Out, Route, PikkuFunction<In, Out>, PikkuFunctionSessionless<In, Out>, PikkuPermission<In>, PikkuMiddleware>
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
102
|
* Type definition for WebSocket channels with typed data exchange.
|
|
@@ -166,16 +166,7 @@ type MCPPromptWiring<In> = CoreMCPPrompt<PikkuFunctionSessionless<In, MCPPromptR
|
|
|
166
166
|
export const pikkuFunc = <In, Out = unknown>(
|
|
167
167
|
func:
|
|
168
168
|
| PikkuFunction<In, Out>
|
|
169
|
-
|
|
|
170
|
-
func: PikkuFunction<In, Out>
|
|
171
|
-
auth?: true
|
|
172
|
-
name?: string
|
|
173
|
-
}
|
|
174
|
-
| {
|
|
175
|
-
func: PikkuFunctionSessionless<In, Out>
|
|
176
|
-
auth: false
|
|
177
|
-
name?: string
|
|
178
|
-
}
|
|
169
|
+
| CorePikkuFunctionConfig<PikkuFunction<In, Out>, PikkuPermission<In>>
|
|
179
170
|
) => {
|
|
180
171
|
return typeof func === 'function' ? func : func.func
|
|
181
172
|
}
|
|
@@ -203,10 +194,7 @@ export const pikkuFunc = <In, Out = unknown>(
|
|
|
203
194
|
export const pikkuSessionlessFunc = <In, Out = unknown>(
|
|
204
195
|
func:
|
|
205
196
|
| PikkuFunctionSessionless<In, Out>
|
|
206
|
-
|
|
|
207
|
-
func: PikkuFunctionSessionless<In, Out>
|
|
208
|
-
name?: string
|
|
209
|
-
}
|
|
197
|
+
| CorePikkuFunctionConfig<PikkuFunctionSessionless<In, Out>, PikkuPermission<In>>
|
|
210
198
|
) => {
|
|
211
199
|
return typeof func === 'function' ? func : func.func
|
|
212
200
|
}
|
|
@@ -293,10 +281,7 @@ export const pikkuChannelDisconnectionFunc = <ChannelData = unknown>(
|
|
|
293
281
|
export const pikkuChannelFunc = <In = unknown, Out = unknown, ChannelData = unknown>(
|
|
294
282
|
func:
|
|
295
283
|
| PikkuFunctionSessionless<In, Out, ChannelData>
|
|
296
|
-
|
|
|
297
|
-
func: PikkuFunctionSessionless<In, Out, ChannelData>
|
|
298
|
-
name?: string
|
|
299
|
-
}
|
|
284
|
+
| CorePikkuFunctionConfig<PikkuFunction<In, Out, ChannelData>, PikkuPermission<In>>
|
|
300
285
|
) => {
|
|
301
286
|
return typeof func === 'function' ? func : func.func
|
|
302
287
|
}
|
|
@@ -320,10 +305,7 @@ export const pikkuChannelFunc = <In = unknown, Out = unknown, ChannelData = unkn
|
|
|
320
305
|
export const pikkuVoidFunc = (
|
|
321
306
|
func:
|
|
322
307
|
| PikkuFunctionSessionless<void, void>
|
|
323
|
-
|
|
|
324
|
-
func: PikkuFunctionSessionless<void, void>
|
|
325
|
-
name?: string
|
|
326
|
-
}
|
|
308
|
+
| CorePikkuFunctionConfig<PikkuFunction<void, void>, PikkuPermission<void>>
|
|
327
309
|
) => {
|
|
328
310
|
return typeof func === 'function' ? func : func.func
|
|
329
311
|
}
|
|
@@ -341,6 +323,27 @@ export const wireChannel = <ChannelData, Channel extends string>(
|
|
|
341
323
|
wireChannelCore(channel as any) // TODO
|
|
342
324
|
}
|
|
343
325
|
|
|
326
|
+
/**
|
|
327
|
+
* Registers middleware either globally or for a specific route.
|
|
328
|
+
*
|
|
329
|
+
* When a string route pattern is provided along with middleware, the middleware
|
|
330
|
+
* is applied only to that route. Otherwise, if an array is provided, it is treated
|
|
331
|
+
* as global middleware (applied to all routes).
|
|
332
|
+
*
|
|
333
|
+
* @param routeOrMiddleware - Either a global middleware array or a route pattern string
|
|
334
|
+
* @param middleware - The middleware array to apply when a route pattern is specified
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* \`\`\`typescript
|
|
338
|
+
* // Add global middleware
|
|
339
|
+
* addHTTPMiddleware([authMiddleware, loggingMiddleware])
|
|
340
|
+
*
|
|
341
|
+
* // Add route-specific middleware
|
|
342
|
+
* addHTTPMiddleware('/api/admin/*', [adminAuthMiddleware])
|
|
343
|
+
* \`\`\`
|
|
344
|
+
*/
|
|
345
|
+
export { addHTTPMiddleware }
|
|
346
|
+
|
|
344
347
|
/**
|
|
345
348
|
* Registers an HTTP wiring with the Pikku framework.
|
|
346
349
|
*
|
package/dist/src/utils.js
CHANGED
|
@@ -206,8 +206,30 @@ export function generateCustomTypes(typesMap, requiredTypes) {
|
|
|
206
206
|
${Array.from(typesMap.customTypes.entries())
|
|
207
207
|
.map(([name, { type, references }]) => {
|
|
208
208
|
references.forEach((name) => {
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
requiredTypes.add(name);
|
|
210
|
+
});
|
|
211
|
+
// Extract type names from the type string that might not be in references
|
|
212
|
+
const typeString = type;
|
|
213
|
+
// Use regex to extract potential type names (PascalCase identifiers)
|
|
214
|
+
const typeNameRegex = /\b[A-Z][a-zA-Z0-9]*\b/g;
|
|
215
|
+
const potentialTypes = typeString.match(typeNameRegex) || [];
|
|
216
|
+
potentialTypes.forEach((typeName) => {
|
|
217
|
+
// Skip string literals and common keywords
|
|
218
|
+
if (typeString.includes(`"${typeName}"`) ||
|
|
219
|
+
['Pick', 'Omit', 'Partial', 'Required', 'Record', 'Readonly'].includes(typeName)) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
// Try to find this type in the typesMap and add it if found
|
|
223
|
+
try {
|
|
224
|
+
const typeMeta = typesMap.getTypeMeta(typeName);
|
|
225
|
+
if (typeMeta.path) {
|
|
226
|
+
requiredTypes.add(typeName);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch (e) {
|
|
230
|
+
// Type not found in map, but add it anyway for fallback resolution
|
|
231
|
+
requiredTypes.add(typeName);
|
|
232
|
+
}
|
|
211
233
|
});
|
|
212
234
|
return `export type ${name} = ${type}`;
|
|
213
235
|
})
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { getFileImportRelativePath, getPikkuFilesAndMethods, logCommandInfoAndTime, writeFileInDir, } from '../../utils.js';
|
|
2
2
|
import { serializePikkuTypes } from '../../serialize-pikku-types.js';
|
|
3
|
-
export const pikkuFunctionTypes = async (logger, { typesDeclarationFile: typesFile, packageMappings,
|
|
3
|
+
export const pikkuFunctionTypes = async (logger, { typesDeclarationFile: typesFile, packageMappings, rpcInternalMapDeclarationFile, }, visitState, options = {}) => {
|
|
4
4
|
return await logCommandInfoAndTime(logger, 'Creating api types', 'Created api types', [false], async () => {
|
|
5
5
|
const { userSessionType, sessionServicesType, singletonServicesType } = await getPikkuFilesAndMethods(logger, visitState, packageMappings, typesFile, options, {
|
|
6
6
|
userSessionType: true,
|
|
7
7
|
sessionServiceType: true,
|
|
8
8
|
singletonServicesType: true,
|
|
9
9
|
});
|
|
10
|
-
const content = serializePikkuTypes(`import type { ${userSessionType.type} } from '${getFileImportRelativePath(typesFile, userSessionType.typePath, packageMappings)}'`, userSessionType.type, `import type { ${singletonServicesType.type} } from '${getFileImportRelativePath(typesFile, singletonServicesType.typePath, packageMappings)}'`, singletonServicesType.type, `import type { ${sessionServicesType.type} } from '${getFileImportRelativePath(typesFile, sessionServicesType.typePath, packageMappings)}'`, `import type { TypedPikkuRPC } from '${getFileImportRelativePath(typesFile,
|
|
10
|
+
const content = serializePikkuTypes(`import type { ${userSessionType.type} } from '${getFileImportRelativePath(typesFile, userSessionType.typePath, packageMappings)}'`, userSessionType.type, `import type { ${singletonServicesType.type} } from '${getFileImportRelativePath(typesFile, singletonServicesType.typePath, packageMappings)}'`, singletonServicesType.type, `import type { ${sessionServicesType.type} } from '${getFileImportRelativePath(typesFile, sessionServicesType.typePath, packageMappings)}'`, `import type { TypedPikkuRPC } from '${getFileImportRelativePath(typesFile, rpcInternalMapDeclarationFile, packageMappings)}'`);
|
|
11
11
|
await writeFileInDir(logger, typesFile, content);
|
|
12
12
|
});
|
|
13
13
|
};
|
|
@@ -1,6 +1,2 @@
|
|
|
1
1
|
import { PikkuCommand } from '../../types.js';
|
|
2
|
-
export declare const serializeFunctionImports: (outputPath: string, functionsMap: Map<string, {
|
|
3
|
-
path: string;
|
|
4
|
-
exportedName: string;
|
|
5
|
-
}>, packageMappings?: Record<string, string>) => string;
|
|
6
2
|
export declare const pikkuFunctions: PikkuCommand;
|
|
@@ -1,35 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
`/* Import and register RPCs */`,
|
|
5
|
-
`import { addFunction } from '@pikku/core'`,
|
|
6
|
-
];
|
|
7
|
-
const serializedRegistrations = [];
|
|
8
|
-
// Sort by function name for consistent output
|
|
9
|
-
const sortedEntries = Array.from(functionsMap.entries()).sort((a, b) => a[0].localeCompare(b[0]));
|
|
10
|
-
for (const [name, { path, exportedName }] of sortedEntries) {
|
|
11
|
-
const filePath = getFileImportRelativePath(outputPath, path, packageMappings);
|
|
12
|
-
// For directly exported functions, we can just import and register them
|
|
13
|
-
if (name === exportedName) {
|
|
14
|
-
serializedImports.push(`import { ${exportedName} } from '${filePath}'`);
|
|
15
|
-
serializedRegistrations.push(`addFunction('${name}', { func: ${exportedName} })`);
|
|
16
|
-
}
|
|
17
|
-
// For renamed functions, we need to import and alias them
|
|
18
|
-
else {
|
|
19
|
-
serializedImports.push(`import { ${exportedName} as ${name} } from '${filePath}'`);
|
|
20
|
-
serializedRegistrations.push(`addFunction('${name}', ${name})`);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
// Add a blank line between imports and registrations
|
|
24
|
-
if (serializedImports.length > 0 && serializedRegistrations.length > 0) {
|
|
25
|
-
serializedImports.push('');
|
|
26
|
-
}
|
|
27
|
-
// Combine the imports and registrations
|
|
28
|
-
return [...serializedImports, ...serializedRegistrations].join('\n');
|
|
29
|
-
};
|
|
30
|
-
export const pikkuFunctions = async (logger, { functionsMetaFile, functionsFile, packageMappings }, { functions }) => {
|
|
1
|
+
import { logCommandInfoAndTime, writeFileInDir } from '../../utils.js';
|
|
2
|
+
import { generateRuntimeMeta, serializeFunctionImports, } from './serialize-function-imports.js';
|
|
3
|
+
export const pikkuFunctions = async (logger, { functionsMetaFile, functionsMetaMinFile, functionsFile, packageMappings }, { functions, rpc }) => {
|
|
31
4
|
return await logCommandInfoAndTime(logger, 'Serializing Pikku functions', 'Serialized Pikku functions', [false], async () => {
|
|
32
|
-
|
|
5
|
+
// Generate full metadata
|
|
33
6
|
await writeFileInDir(logger, functionsMetaFile, `import { pikkuState } from '@pikku/core'\npikkuState('function', 'meta', ${JSON.stringify(functions.meta, null, 2)})`);
|
|
7
|
+
// Generate minimal metadata (runtime)
|
|
8
|
+
const runtimeMeta = generateRuntimeMeta(functions.meta);
|
|
9
|
+
await writeFileInDir(logger, functionsMetaMinFile, `import { pikkuState } from '@pikku/core'\npikkuState('function', 'meta', ${JSON.stringify(runtimeMeta, null, 2)})`);
|
|
10
|
+
if (rpc.exposedFiles.size > 0 || rpc.internalFiles.size > 0) {
|
|
11
|
+
await writeFileInDir(logger, functionsFile, serializeFunctionImports(functionsFile, rpc.internalFiles, functions.meta, packageMappings));
|
|
12
|
+
}
|
|
34
13
|
});
|
|
35
14
|
};
|
|
@@ -60,7 +60,7 @@ export const serializeServicesMap = (functionsMetaData, middlewareServices = [],
|
|
|
60
60
|
return code;
|
|
61
61
|
};
|
|
62
62
|
export const pikkuServices = async (logger, cliConfig, visitState) => {
|
|
63
|
-
return await logCommandInfoAndTime(logger, 'Generating Pikku services map', 'Generated Pikku services map', [
|
|
63
|
+
return await logCommandInfoAndTime(logger, 'Generating Pikku services map', 'Generated Pikku services map', [false], async () => {
|
|
64
64
|
const { sessionServicesType, singletonServicesType } = await getPikkuFilesAndMethods(logger, visitState, cliConfig.packageMappings, cliConfig.typesDeclarationFile, {}, {
|
|
65
65
|
sessionServiceType: true,
|
|
66
66
|
singletonServicesType: true,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { getFileImportRelativePath, getPikkuFilesAndMethods, logCommandInfoAndTime, writeFileInDir, } from '../../utils.js';
|
|
2
2
|
import { serializePikkuTypes } from '../../serialize-pikku-types.js';
|
|
3
|
-
export const pikkuFunctionTypes = async (logger, { typesDeclarationFile: typesFile, packageMappings,
|
|
3
|
+
export const pikkuFunctionTypes = async (logger, { typesDeclarationFile: typesFile, packageMappings, rpcInternalMapDeclarationFile, }, visitState, options = {}) => {
|
|
4
4
|
return await logCommandInfoAndTime(logger, 'Creating api types', 'Created api types', [false], async () => {
|
|
5
5
|
const { userSessionType, sessionServicesType, singletonServicesType } = await getPikkuFilesAndMethods(logger, visitState, packageMappings, typesFile, options, {
|
|
6
6
|
userSessionType: true,
|
|
7
7
|
sessionServiceType: true,
|
|
8
8
|
singletonServicesType: true,
|
|
9
9
|
});
|
|
10
|
-
const content = serializePikkuTypes(`import type { ${userSessionType.type} } from '${getFileImportRelativePath(typesFile, userSessionType.typePath, packageMappings)}'`, userSessionType.type, `import type { ${singletonServicesType.type} } from '${getFileImportRelativePath(typesFile, singletonServicesType.typePath, packageMappings)}'`, singletonServicesType.type, `import type { ${sessionServicesType.type} } from '${getFileImportRelativePath(typesFile, sessionServicesType.typePath, packageMappings)}'`, `import type { TypedPikkuRPC } from '${getFileImportRelativePath(typesFile,
|
|
10
|
+
const content = serializePikkuTypes(`import type { ${userSessionType.type} } from '${getFileImportRelativePath(typesFile, userSessionType.typePath, packageMappings)}'`, userSessionType.type, `import type { ${singletonServicesType.type} } from '${getFileImportRelativePath(typesFile, singletonServicesType.typePath, packageMappings)}'`, singletonServicesType.type, `import type { ${sessionServicesType.type} } from '${getFileImportRelativePath(typesFile, sessionServicesType.typePath, packageMappings)}'`, `import type { TypedPikkuRPC } from '${getFileImportRelativePath(typesFile, rpcInternalMapDeclarationFile, packageMappings)}'`);
|
|
11
11
|
await writeFileInDir(logger, typesFile, content);
|
|
12
12
|
});
|
|
13
13
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { FunctionsMeta, FunctionsRuntimeMeta } from '@pikku/core';
|
|
2
|
+
export declare const serializeFunctionImports: (outputPath: string, functionsMap: Map<string, {
|
|
3
|
+
path: string;
|
|
4
|
+
exportedName: string;
|
|
5
|
+
}>, functionsMeta: FunctionsMeta, packageMappings?: Record<string, string>) => string;
|
|
6
|
+
export declare const generateRuntimeMeta: (functions: FunctionsMeta) => FunctionsRuntimeMeta;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getFileImportRelativePath } from '../../utils.js';
|
|
2
|
+
export const serializeFunctionImports = (outputPath, functionsMap, functionsMeta, packageMappings = {}) => {
|
|
3
|
+
const serializedImports = [
|
|
4
|
+
`/* Import and register functions used by RPCs */`,
|
|
5
|
+
`import { addFunction } from '@pikku/core'`,
|
|
6
|
+
];
|
|
7
|
+
const serializedRegistrations = [];
|
|
8
|
+
// Sort by function name for consistent output
|
|
9
|
+
const sortedEntries = Array.from(functionsMap.entries()).sort((a, b) => a[0].localeCompare(b[0]));
|
|
10
|
+
for (const [name, { path, exportedName }] of sortedEntries) {
|
|
11
|
+
const filePath = getFileImportRelativePath(outputPath, path, packageMappings);
|
|
12
|
+
// Find the function metadata to check if it's a direct function
|
|
13
|
+
// The functionsMeta is keyed by the function name (exported name)
|
|
14
|
+
const funcMeta = functionsMeta[name];
|
|
15
|
+
const isDirectFunction = funcMeta?.isDirectFunction ?? false;
|
|
16
|
+
// For directly exported functions, we can just import and register them
|
|
17
|
+
if (name === exportedName) {
|
|
18
|
+
serializedImports.push(`import { ${exportedName} } from '${filePath}'`);
|
|
19
|
+
if (isDirectFunction) {
|
|
20
|
+
// Direct function: pikkuFunc(fn) - needs to be wrapped
|
|
21
|
+
serializedRegistrations.push(`addFunction('${name}', { func: ${exportedName} })`);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
// Object format: pikkuFunc({ func: fn }) - can be used directly
|
|
25
|
+
serializedRegistrations.push(`addFunction('${name}', ${exportedName} as any) // TODO`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// For renamed functions, we need to import and alias them
|
|
29
|
+
else {
|
|
30
|
+
serializedImports.push(`import { ${exportedName} as ${name} } from '${filePath}'`);
|
|
31
|
+
if (isDirectFunction) {
|
|
32
|
+
// Direct function: pikkuFunc(fn) - needs to be wrapped
|
|
33
|
+
serializedRegistrations.push(`addFunction('${name}', { func: ${name} })`);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Object format: pikkuFunc({ func: fn }) - can be used directly
|
|
37
|
+
serializedRegistrations.push(`addFunction('${name}', ${name} as any) // TODO`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Add a blank line between imports and registrations
|
|
42
|
+
if (serializedImports.length > 0 && serializedRegistrations.length > 0) {
|
|
43
|
+
serializedImports.push('');
|
|
44
|
+
}
|
|
45
|
+
// Combine the imports and registrations
|
|
46
|
+
return [...serializedImports, ...serializedRegistrations].join('\n');
|
|
47
|
+
};
|
|
48
|
+
export const generateRuntimeMeta = (functions) => {
|
|
49
|
+
const runtimeMeta = {};
|
|
50
|
+
for (const [key, { pikkuFuncName, inputSchemaName, outputSchemaName, expose },] of Object.entries(functions)) {
|
|
51
|
+
runtimeMeta[key] = {
|
|
52
|
+
pikkuFuncName,
|
|
53
|
+
inputSchemaName,
|
|
54
|
+
outputSchemaName,
|
|
55
|
+
expose,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return runtimeMeta;
|
|
59
|
+
};
|