@pikku/cli 0.10.0 → 0.10.2
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/.pikku/channel/pikku-channel-types.gen.ts +4 -3
- package/.pikku/channel/pikku-channels-map.gen.d.ts +2 -2
- package/.pikku/channel/pikku-channels-meta.gen.ts +1 -1
- package/.pikku/channel/pikku-channels.gen.ts +1 -1
- package/.pikku/cli/pikku-cli-types.gen.ts +23 -1
- package/.pikku/cli/pikku-cli-wirings-meta.gen.ts +4 -115
- package/.pikku/cli/pikku-cli-wirings.gen.ts +2 -3
- package/.pikku/function/pikku-function-types.gen.ts +1 -1
- package/.pikku/function/pikku-functions-meta.gen.ts +156 -138
- package/.pikku/function/pikku-functions-meta.min.gen.ts +37 -32
- package/.pikku/function/pikku-functions.gen.ts +1 -1
- package/.pikku/http/pikku-http-types.gen.ts +1 -1
- package/.pikku/http/pikku-http-wirings-map.gen.d.ts +2 -2
- package/.pikku/http/pikku-http-wirings-meta.gen.ts +1 -1
- package/.pikku/http/pikku-http-wirings.gen.ts +1 -1
- package/.pikku/mcp/pikku-mcp-types.gen.ts +1 -1
- package/.pikku/mcp/pikku-mcp-wirings-meta.gen.ts +1 -1
- package/.pikku/mcp/pikku-mcp-wirings.gen.ts +1 -1
- package/.pikku/pikku-bootstrap.gen.ts +1 -1
- package/.pikku/pikku-services.gen.ts +16 -12
- package/.pikku/pikku-types.gen.ts +1 -1
- package/.pikku/pikku-websocket.gen.ts +15 -1
- package/.pikku/queue/pikku-queue-types.gen.ts +1 -1
- package/.pikku/queue/pikku-queue-workers-wirings-map.gen.d.ts +2 -2
- package/.pikku/queue/pikku-queue-workers-wirings-meta.gen.ts +1 -1
- package/.pikku/queue/pikku-queue-workers-wirings.gen.ts +1 -1
- package/.pikku/rpc/pikku-rpc-wirings-map.gen.d.ts +2 -2
- package/.pikku/rpc/pikku-rpc-wirings-map.internal.gen.d.ts +10 -9
- package/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.ts +9 -8
- package/.pikku/scheduler/pikku-scheduler-types.gen.ts +1 -1
- package/.pikku/scheduler/pikku-schedulers-wirings-meta.gen.ts +1 -1
- package/.pikku/scheduler/pikku-schedulers-wirings.gen.ts +1 -1
- package/.pikku/schemas/register.gen.ts +5 -5
- package/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
- package/.pikku/schemas/schemas/PikkuChannelsOutput.schema.json +1 -1
- package/.pikku/schemas/schemas/PikkuSchemasOutput.schema.json +1 -1
- package/CHANGELOG.md +58 -0
- package/bin/pikku.ts +30 -21
- package/cli.schema.json +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +4 -3
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/channel/pikku-channels-meta.gen.js +1 -1
- package/dist/.pikku/channel/pikku-channels.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channels.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +18 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.js +20 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +4 -115
- package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -2
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -2
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +156 -138
- package/dist/.pikku/function/pikku-functions-meta.min.gen.js +37 -32
- package/dist/.pikku/function/pikku-functions.gen.js +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
- package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
- package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-wirings.gen.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-wirings-meta.gen.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-wirings.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-wirings.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
- package/dist/.pikku/pikku-services.gen.d.ts +9 -6
- package/dist/.pikku/pikku-services.gen.js +8 -2
- package/dist/.pikku/pikku-types.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.js +1 -1
- package/dist/.pikku/pikku-websocket.gen.d.ts +15 -1
- package/dist/.pikku/pikku-websocket.gen.js +15 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +9 -8
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
- package/dist/.pikku/scheduler/pikku-schedulers-wirings-meta.gen.js +1 -1
- package/dist/.pikku/scheduler/pikku-schedulers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-schedulers-wirings.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +3 -3
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuChannelsOutput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuSchemasOutput.schema.json +1 -1
- package/dist/bin/pikku.js +24 -19
- package/dist/src/cli.wiring.js +107 -99
- package/dist/src/functions/commands/all.js +31 -2
- package/dist/src/functions/commands/bootstrap.d.ts +1 -0
- package/dist/src/functions/commands/bootstrap.js +23 -0
- package/dist/src/functions/runtimes/nextjs/serialize-nextjs-backend-wrapper.js +46 -2
- package/dist/src/functions/wirings/channels/serialize-channel-types.js +3 -2
- package/dist/src/functions/wirings/channels/serialize-websocket-wrapper.js +14 -0
- package/dist/src/functions/wirings/cli/pikku-command-cli-entry.js +4 -4
- package/dist/src/functions/wirings/cli/serialize-channel-cli-client.js +24 -4
- package/dist/src/functions/wirings/cli/serialize-channel-cli.js +32 -7
- package/dist/src/functions/wirings/cli/serialize-cli-types.js +22 -0
- package/dist/src/functions/wirings/functions/pikku-command-services.d.ts +1 -1
- package/dist/src/functions/wirings/functions/pikku-command-services.js +54 -26
- package/dist/src/functions/wirings/functions/schemas.js +2 -2
- package/dist/src/functions/wirings/http/pikku-command-openapi.js +1 -1
- package/dist/src/functions/wirings/middleware/pikku-command-middleware.js +3 -10
- package/dist/src/middleware/log-command-info-and-time.d.ts +1 -1
- package/dist/src/middleware/log-command-info-and-time.js +8 -5
- package/dist/src/services/cli-logger.service.d.ts +7 -2
- package/dist/src/services/cli-logger.service.js +16 -4
- package/dist/src/services.js +77 -12
- package/dist/src/utils/check-required-types.js +11 -1
- package/dist/src/utils/command-summary.d.ts +43 -0
- package/dist/src/utils/command-summary.js +73 -0
- package/dist/src/utils/file-writer.js +2 -2
- package/dist/src/utils/pikku-cli-config.js +28 -0
- package/dist/src/utils/schema-generator.d.ts +2 -2
- package/dist/src/utils/schema-generator.js +3 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -4
- package/pikku.config.json +5 -2
- package/src/cli.wiring.ts +106 -101
- package/src/functions/commands/all.ts +38 -2
- package/src/functions/commands/bootstrap.ts +27 -0
- package/src/functions/runtimes/nextjs/serialize-nextjs-backend-wrapper.ts +46 -2
- package/src/functions/wirings/channels/serialize-channel-types.ts +3 -2
- package/src/functions/wirings/channels/serialize-websocket-wrapper.ts +14 -0
- package/src/functions/wirings/cli/pikku-command-cli-entry.ts +4 -4
- package/src/functions/wirings/cli/serialize-channel-cli-client.ts +24 -4
- package/src/functions/wirings/cli/serialize-channel-cli.ts +40 -8
- package/src/functions/wirings/cli/serialize-cli-types.ts +22 -0
- package/src/functions/wirings/functions/pikku-command-services.ts +57 -28
- package/src/functions/wirings/functions/schemas.ts +4 -3
- package/src/functions/wirings/http/pikku-command-openapi.ts +2 -1
- package/src/functions/wirings/middleware/pikku-command-middleware.ts +11 -22
- package/src/middleware/log-command-info-and-time.ts +8 -5
- package/src/services/cli-logger.service.ts +20 -5
- package/src/services.ts +86 -11
- package/src/utils/check-required-types.ts +16 -1
- package/src/utils/command-summary.ts +101 -0
- package/src/utils/file-writer.ts +2 -2
- package/src/utils/pikku-cli-config.ts +28 -0
- package/src/utils/schema-generator.ts +5 -4
- package/types/application-types.d.ts +5 -1
- package/types/config.d.ts +16 -6
- package/.pikku/cli/pikku-cli-channel.gen.ts +0 -34
- package/.pikku/cli/pikku-cli-client.gen.ts +0 -43
- package/.pikku/cli/pikku-cli.gen.ts +0 -41
- package/dist/.pikku/cli/pikku-cli-channel.gen.d.ts +0 -1
- package/dist/.pikku/cli/pikku-cli-channel.gen.js +0 -33
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +0 -10
- package/dist/.pikku/cli/pikku-cli-client.gen.js +0 -34
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +0 -10
- package/dist/.pikku/cli/pikku-cli.gen.js +0 -38
|
@@ -2,8 +2,10 @@ import { existsSync } from 'fs';
|
|
|
2
2
|
import { pikkuVoidFunc } from '../../../.pikku/pikku-types.gen.js';
|
|
3
3
|
import { getFileImportRelativePath } from '../../utils/file-import-path.js';
|
|
4
4
|
import { writeFileInDir } from '../../utils/file-writer.js';
|
|
5
|
+
import { CommandSummary } from '../../utils/command-summary.js';
|
|
5
6
|
export const all = pikkuVoidFunc({
|
|
6
7
|
func: async ({ logger, config, rpc, getInspectorState }) => {
|
|
8
|
+
const summary = new CommandSummary('all');
|
|
7
9
|
const allImports = [];
|
|
8
10
|
let typesDeclarationFileExists = true;
|
|
9
11
|
if (!existsSync(config.typesDeclarationFile)) {
|
|
@@ -12,7 +14,7 @@ export const all = pikkuVoidFunc({
|
|
|
12
14
|
await rpc.invoke('pikkuFunctionTypes', null);
|
|
13
15
|
// This is needed since the wireHTTP function will add the routes to the visitState
|
|
14
16
|
if (!typesDeclarationFileExists) {
|
|
15
|
-
logger.
|
|
17
|
+
logger.debug(`• Type file first created, inspecting again...`);
|
|
16
18
|
await getInspectorState(true);
|
|
17
19
|
}
|
|
18
20
|
// Generate wiring-specific type files for tree-shaking
|
|
@@ -97,7 +99,7 @@ export const all = pikkuVoidFunc({
|
|
|
97
99
|
await rpc.invoke('pikkuNext', null);
|
|
98
100
|
}
|
|
99
101
|
if (config.openAPI) {
|
|
100
|
-
logger.
|
|
102
|
+
logger.debug(`• OpenAPI requires a reinspection to pickup new generated types..`);
|
|
101
103
|
await getInspectorState(true);
|
|
102
104
|
await rpc.invoke('pikkuOpenAPI', null);
|
|
103
105
|
}
|
|
@@ -106,6 +108,33 @@ export const all = pikkuVoidFunc({
|
|
|
106
108
|
.map((to) => `import '${getFileImportRelativePath(config.bootstrapFile, to, config.packageMappings)}'`)
|
|
107
109
|
.sort((to) => (to.includes('meta') ? -1 : 1)) // Ensure meta files are at the top
|
|
108
110
|
.join('\n'));
|
|
111
|
+
// Get final inspector state and collect stats for summary
|
|
112
|
+
const state = await getInspectorState();
|
|
113
|
+
if (state.http?.meta)
|
|
114
|
+
summary.set('httpRoutes', Object.keys(state.http.meta).length);
|
|
115
|
+
if (state.channels?.meta)
|
|
116
|
+
summary.set('channels', Object.keys(state.channels.meta).length);
|
|
117
|
+
if (state.scheduledTasks?.meta)
|
|
118
|
+
summary.set('scheduledTasks', Object.keys(state.scheduledTasks.meta).length);
|
|
119
|
+
if (state.queueWorkers?.meta)
|
|
120
|
+
summary.set('queueWorkers', Object.keys(state.queueWorkers.meta).length);
|
|
121
|
+
if (state.mcpEndpoints) {
|
|
122
|
+
const mcpTotal = Object.keys(state.mcpEndpoints.toolsMeta || {}).length +
|
|
123
|
+
Object.keys(state.mcpEndpoints.resourcesMeta || {}).length +
|
|
124
|
+
Object.keys(state.mcpEndpoints.promptsMeta || {}).length;
|
|
125
|
+
if (mcpTotal > 0)
|
|
126
|
+
summary.set('mcpEndpoints', mcpTotal);
|
|
127
|
+
}
|
|
128
|
+
if (state.cli?.meta) {
|
|
129
|
+
// Count total CLI commands across all programs
|
|
130
|
+
const totalCommands = Object.values(state.cli.meta).reduce((sum, program) => sum + (program.commands?.length || 0), 0);
|
|
131
|
+
if (totalCommands > 0)
|
|
132
|
+
summary.set('cliCommands', totalCommands);
|
|
133
|
+
}
|
|
134
|
+
// Display summary (unless in silent mode)
|
|
135
|
+
if (!logger.isSilent()) {
|
|
136
|
+
console.log(summary.format());
|
|
137
|
+
}
|
|
109
138
|
// Check for critical errors and exit if any were logged
|
|
110
139
|
if (logger.hasCriticalErrors()) {
|
|
111
140
|
process.exit(1);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const bootstrap: any;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { pikkuVoidFunc } from '../../../.pikku/pikku-types.gen.js';
|
|
2
|
+
export const bootstrap = pikkuVoidFunc({
|
|
3
|
+
func: async ({ logger, config, rpc, getInspectorState }) => {
|
|
4
|
+
// Initialize inspector state in bootstrap mode with core types only
|
|
5
|
+
// This allows bootstrap to run immediately without inspecting the codebase
|
|
6
|
+
// All subsequent RPC commands will use this cached state
|
|
7
|
+
await getInspectorState(false, false, true);
|
|
8
|
+
await rpc.invoke('pikkuFunctionTypes', null);
|
|
9
|
+
// Generate wiring-specific type files for tree-shaking
|
|
10
|
+
// These use the bootstrap mode state with core types
|
|
11
|
+
await rpc.invoke('pikkuFunctionTypesSplit', null);
|
|
12
|
+
await rpc.invoke('pikkuHTTPTypes', null);
|
|
13
|
+
await rpc.invoke('pikkuChannelTypes', null);
|
|
14
|
+
await rpc.invoke('pikkuSchedulerTypes', null);
|
|
15
|
+
await rpc.invoke('pikkuQueueTypes', null);
|
|
16
|
+
await rpc.invoke('pikkuMCPTypes', null);
|
|
17
|
+
await rpc.invoke('pikkuCLITypes', null);
|
|
18
|
+
// Check for critical errors and exit if any were logged
|
|
19
|
+
if (logger.hasCriticalErrors()) {
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
export const serializeNextJsBackendWrapper = (bootstrapPath, routesMapPath, configImport, singleServicesFactoryImport, sessionServicesImport) => {
|
|
2
2
|
return `'server-only'
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
/**
|
|
5
5
|
* This file provides a wrapper around the PikkuNextJS class to allow for methods to be type checked against your routes.
|
|
6
6
|
* It ensures type safety for route handling methods when integrating with the @pikku/core framework.
|
|
7
7
|
*/
|
|
8
8
|
import { PikkuNextJS } from '@pikku/next'
|
|
9
|
+
import { NextRequest } from 'next/server.js'
|
|
9
10
|
import type { HTTPWiringsMap, HTTPWiringHandlerOf, HTTPWiringsWithMethod } from '${routesMapPath}'
|
|
10
11
|
|
|
12
|
+
type RouteContext = { params: Promise<Record<string, string | string[]>> }
|
|
13
|
+
|
|
11
14
|
${configImport}
|
|
12
15
|
${singleServicesFactoryImport}
|
|
13
16
|
${sessionServicesImport}
|
|
@@ -15,6 +18,11 @@ ${sessionServicesImport}
|
|
|
15
18
|
import '${bootstrapPath}'
|
|
16
19
|
|
|
17
20
|
let _pikku: PikkuNextJS | undefined
|
|
21
|
+
let _removeAPIPrefix = true
|
|
22
|
+
|
|
23
|
+
export const removeAPIPrefix = (enable: boolean) => {
|
|
24
|
+
_removeAPIPrefix = enable
|
|
25
|
+
}
|
|
18
26
|
|
|
19
27
|
/**
|
|
20
28
|
* Initializes and returns an instance of PikkuNextJS with helper methods for handling route requests.
|
|
@@ -172,8 +180,44 @@ export const pikku = (_options?: any) => {
|
|
|
172
180
|
patch: dynamicPatch,
|
|
173
181
|
del: dynamicDel,
|
|
174
182
|
staticGet,
|
|
175
|
-
staticPost
|
|
183
|
+
staticPost,
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Pre-bound API request handler for Next.js App Router route handlers.
|
|
189
|
+
* Use this to directly export route handlers without losing context.
|
|
190
|
+
*
|
|
191
|
+
* @param req - The Next.js request object.
|
|
192
|
+
* @param context - Next.js route context (unused by Pikku, but required by Next.js signature).
|
|
193
|
+
* @returns A promise that resolves to a Next.js Response object.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* export const GET = pikkuAPIRequest
|
|
197
|
+
* export const POST = pikkuAPIRequest
|
|
198
|
+
*/
|
|
199
|
+
export const pikkuAPIRequest = (
|
|
200
|
+
req: NextRequest,
|
|
201
|
+
context: RouteContext
|
|
202
|
+
): Promise<Response> => {
|
|
203
|
+
if (!_pikku) {
|
|
204
|
+
_pikku = new PikkuNextJS(
|
|
205
|
+
createConfig as any,
|
|
206
|
+
createSingletonServices as any,
|
|
207
|
+
createSessionServices
|
|
208
|
+
)
|
|
209
|
+
}
|
|
210
|
+
if (_removeAPIPrefix) {
|
|
211
|
+
const url = new URL(req.url)
|
|
212
|
+
url.pathname = url.pathname.replace(/^\\/api/, '') || '/'
|
|
213
|
+
req = new NextRequest(url.toString(), {
|
|
214
|
+
method: req.method,
|
|
215
|
+
headers: req.headers,
|
|
216
|
+
body: req.body,
|
|
217
|
+
duplex: 'half',
|
|
218
|
+
} as any)
|
|
176
219
|
}
|
|
220
|
+
return _pikku.apiRequest(req)
|
|
177
221
|
}
|
|
178
222
|
`;
|
|
179
223
|
};
|
|
@@ -10,11 +10,12 @@ export const serializeChannelTypes = (functionTypesImportPath) => {
|
|
|
10
10
|
import { CoreChannel, wireChannel as wireChannelCore } from '@pikku/core/channel'
|
|
11
11
|
import { CorePikkuFunctionConfig } from '@pikku/core'
|
|
12
12
|
import { AssertHTTPWiringParams } from '@pikku/core/http'
|
|
13
|
-
import type { PikkuFunctionSessionless, PikkuPermission, PikkuMiddleware } from '${functionTypesImportPath}'
|
|
13
|
+
import type { PikkuFunction, PikkuFunctionSessionless, PikkuPermission, PikkuMiddleware } from '${functionTypesImportPath}'
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Type definition for WebSocket channels with typed data exchange.
|
|
17
17
|
* Supports connection, disconnection, and message handling.
|
|
18
|
+
* Accepts both session-based (PikkuFunction) and sessionless (PikkuFunctionSessionless) functions.
|
|
18
19
|
*
|
|
19
20
|
* @template ChannelData - Type of data exchanged through the channel
|
|
20
21
|
* @template Channel - String literal type for the channel name
|
|
@@ -24,7 +25,7 @@ type ChannelWiring<ChannelData, Channel extends string> = CoreChannel<
|
|
|
24
25
|
Channel,
|
|
25
26
|
CorePikkuFunctionConfig<PikkuFunctionSessionless<void, any, ChannelData>, PikkuPermission<void>, PikkuMiddleware>,
|
|
26
27
|
CorePikkuFunctionConfig<PikkuFunctionSessionless<void, void, ChannelData>, PikkuPermission<void>, PikkuMiddleware>,
|
|
27
|
-
CorePikkuFunctionConfig<PikkuFunctionSessionless<any, any, ChannelData>, PikkuPermission<any>, PikkuMiddleware>,
|
|
28
|
+
CorePikkuFunctionConfig<PikkuFunctionSessionless<any, any, ChannelData> | PikkuFunction<any, any, ChannelData>, PikkuPermission<any>, PikkuMiddleware>,
|
|
28
29
|
PikkuPermission,
|
|
29
30
|
PikkuMiddleware
|
|
30
31
|
>
|
|
@@ -26,6 +26,20 @@ class PikkuWebSocketRoute<Channel extends keyof ChannelsMap, Route extends keyof
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Type-safe WebSocket wrapper for Pikku channels.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Browser usage
|
|
34
|
+
* const ws = new WebSocket('ws://localhost:3000')
|
|
35
|
+
* const pikkuWS = new PikkuWebSocket<'events'>(ws)
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Node.js usage
|
|
39
|
+
* import WebSocket from 'ws'
|
|
40
|
+
* const ws = new WebSocket('ws://localhost:3000')
|
|
41
|
+
* const pikkuWS = new PikkuWebSocket<'events'>(ws)
|
|
42
|
+
*/
|
|
29
43
|
export class PikkuWebSocket<Channel extends keyof ChannelsMap, EventHubTopics extends Record<string, any> = {}> extends CorePikkuWebsocket {
|
|
30
44
|
/**
|
|
31
45
|
* Send a message to a specific route and method.
|
|
@@ -35,8 +35,8 @@ export const pikkuCLIEntry = pikkuSessionlessFunc({
|
|
|
35
35
|
for (const entrypointConfig of configs) {
|
|
36
36
|
// Normalize entrypoint config to get type
|
|
37
37
|
const entrypointType = typeof entrypointConfig === 'string'
|
|
38
|
-
? '
|
|
39
|
-
: entrypointConfig.type || '
|
|
38
|
+
? 'local'
|
|
39
|
+
: entrypointConfig.type || 'local';
|
|
40
40
|
// Handle channel type entrypoint
|
|
41
41
|
if (entrypointType === 'channel') {
|
|
42
42
|
if (typeof entrypointConfig === 'string' ||
|
|
@@ -85,10 +85,10 @@ export const pikkuCLIEntry = pikkuSessionlessFunc({
|
|
|
85
85
|
}
|
|
86
86
|
continue;
|
|
87
87
|
}
|
|
88
|
-
// Handle CLI type entrypoint (default)
|
|
88
|
+
// Handle local CLI type entrypoint (default)
|
|
89
89
|
const entrypointPath = typeof entrypointConfig === 'string'
|
|
90
90
|
? entrypointConfig
|
|
91
|
-
: entrypointConfig.type === '
|
|
91
|
+
: entrypointConfig.type === 'local'
|
|
92
92
|
? entrypointConfig.path
|
|
93
93
|
: undefined;
|
|
94
94
|
if (!entrypointPath) {
|
|
@@ -102,8 +102,27 @@ export async function ${capitalizedName}CLIClient(
|
|
|
102
102
|
url: string,
|
|
103
103
|
args?: string[]
|
|
104
104
|
): Promise<void> {
|
|
105
|
+
// Get WebSocket implementation (browser or Node.js)
|
|
106
|
+
let WebSocketImpl: any
|
|
107
|
+
if (typeof WebSocket !== 'undefined') {
|
|
108
|
+
WebSocketImpl = WebSocket
|
|
109
|
+
} else {
|
|
110
|
+
// Node.js environment - dynamically import 'ws'
|
|
111
|
+
try {
|
|
112
|
+
const wsModule = await import('ws')
|
|
113
|
+
WebSocketImpl = wsModule.default
|
|
114
|
+
} catch (e) {
|
|
115
|
+
throw new Error(
|
|
116
|
+
'No WebSocket implementation found. In Node.js environments, you need to:\\n' +
|
|
117
|
+
'1. Install the "ws" package: npm install ws\\n' +
|
|
118
|
+
'Learn more: https://www.npmjs.com/package/ws'
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
105
123
|
// Create WebSocket connection
|
|
106
|
-
const
|
|
124
|
+
const ws = new WebSocketImpl(url) as WebSocket
|
|
125
|
+
const pikkuWS = new CorePikkuWebsocket(ws)
|
|
107
126
|
|
|
108
127
|
// Register renderers for CLI commands
|
|
109
128
|
const renderers = ${renderersMap}
|
|
@@ -121,10 +140,11 @@ export default ${capitalizedName}CLIClient
|
|
|
121
140
|
|
|
122
141
|
// For direct execution (if this file is run directly)
|
|
123
142
|
if (import.meta.url === \`file://\${process.argv[1]}\`) {
|
|
124
|
-
const url = process.env.PIKKU_WS_URL || 'ws://localhost:
|
|
143
|
+
const url = process.env.PIKKU_WS_URL || 'ws://localhost:4002${finalChannelRoute}'
|
|
125
144
|
${capitalizedName}CLIClient(url, process.argv.slice(2)).catch(error => {
|
|
126
|
-
console.error('Fatal error:', error
|
|
127
|
-
|
|
145
|
+
console.error('Fatal channel CLI error:', error)
|
|
146
|
+
// TODO: We get an error code even when it exists cleanly, investigate
|
|
147
|
+
// process.exit(1)
|
|
128
148
|
})
|
|
129
149
|
}
|
|
130
150
|
`;
|
|
@@ -24,12 +24,6 @@ export function serializeChannelCLI(programName, programMeta, channelFile, funct
|
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
collectCommands(programMeta.commands);
|
|
27
|
-
// Generate the wireChannel call
|
|
28
|
-
const commandEntries = Object.entries(commandMap)
|
|
29
|
-
.map(([commandKey, { pikkuFuncName }]) => {
|
|
30
|
-
return ` '${commandKey}': ${pikkuFuncName}`;
|
|
31
|
-
})
|
|
32
|
-
.join(',\n');
|
|
33
27
|
// Generate imports from function file locations
|
|
34
28
|
const funcNames = [
|
|
35
29
|
...new Set(Object.values(commandMap).map((v) => v.pikkuFuncName)),
|
|
@@ -46,19 +40,50 @@ export function serializeChannelCLI(programName, programMeta, channelFile, funct
|
|
|
46
40
|
.join('\n');
|
|
47
41
|
// Get relative path to channel types file
|
|
48
42
|
const channelTypesPath = getFileImportRelativePath(channelFile, channelTypesFile, packageMappings);
|
|
43
|
+
// Get relative path to function types file
|
|
44
|
+
const functionTypesPath = getFileImportRelativePath(channelFile, functionTypesFile, packageMappings);
|
|
49
45
|
return `/**
|
|
50
46
|
* WebSocket channel backend for '${programName}' CLI commands
|
|
51
47
|
*/
|
|
52
48
|
import { wireChannel } from '${channelTypesPath}'
|
|
49
|
+
import { pikkuMiddleware } from '${functionTypesPath}'
|
|
53
50
|
${imports}
|
|
54
51
|
|
|
52
|
+
// Middleware to close the channel after CLI command completes
|
|
53
|
+
const cliCloseOnComplete = pikkuMiddleware(async (services, { channel }, next) => {
|
|
54
|
+
const closeChannel = () => {
|
|
55
|
+
setTimeout(async () => {
|
|
56
|
+
try {
|
|
57
|
+
// This gives time for the response to be sent before closing
|
|
58
|
+
await channel?.close()
|
|
59
|
+
} catch (err) {
|
|
60
|
+
// Ignore errors on close
|
|
61
|
+
}
|
|
62
|
+
}, 200)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const result = await next()
|
|
67
|
+
closeChannel()
|
|
68
|
+
return result
|
|
69
|
+
} catch (error) {
|
|
70
|
+
closeChannel()
|
|
71
|
+
throw error
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
|
|
55
75
|
wireChannel({
|
|
56
76
|
name: '${finalChannelName}',
|
|
57
77
|
route: '${finalChannelRoute}',
|
|
58
78
|
auth: false,
|
|
59
79
|
onMessageWiring: {
|
|
60
80
|
command: {
|
|
61
|
-
${
|
|
81
|
+
${Object.entries(commandMap)
|
|
82
|
+
.map(([commandKey, { pikkuFuncName }]) => ` '${commandKey}': {
|
|
83
|
+
func: ${pikkuFuncName},
|
|
84
|
+
middleware: [cliCloseOnComplete],
|
|
85
|
+
}`)
|
|
86
|
+
.join(',\n')}
|
|
62
87
|
}
|
|
63
88
|
},
|
|
64
89
|
tags: ['cli', '${programName}']
|
|
@@ -24,6 +24,28 @@ ${userSessionTypeName !== 'Session' ? `type Session = ${userSessionTypeName}` :
|
|
|
24
24
|
*/
|
|
25
25
|
type PikkuCLIRender<Data, RequiredServices extends SingletonServices = SingletonServices> = CorePikkuCLIRender<Data, RequiredServices, Session>
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Creates a type-safe CLI renderer with access to your application's singleton services.
|
|
29
|
+
* The renderer receives the full singleton services and output data to format and display results.
|
|
30
|
+
*
|
|
31
|
+
* @template Data - The output data type from the CLI command
|
|
32
|
+
* @template RequiredServices - The minimum services required for type checking (defaults to SingletonServices)
|
|
33
|
+
* @param render - Function that receives singleton services and data to render output
|
|
34
|
+
* @returns A CLI renderer configuration
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* \`\`\`typescript
|
|
38
|
+
* const myRenderer = pikkuCLIRender<MyData>(({ logger }, data) => {
|
|
39
|
+
* logger.info(data.message)
|
|
40
|
+
* })
|
|
41
|
+
* \`\`\`
|
|
42
|
+
*/
|
|
43
|
+
export const pikkuCLIRender = <Data, RequiredServices extends SingletonServices = SingletonServices>(
|
|
44
|
+
render: (services: SingletonServices, data: Data) => void | Promise<void>
|
|
45
|
+
): PikkuCLIRender<Data, RequiredServices> => {
|
|
46
|
+
return render as any
|
|
47
|
+
}
|
|
48
|
+
|
|
27
49
|
/**
|
|
28
50
|
* CLI command configuration with project-specific types.
|
|
29
51
|
* Uses CoreCLICommandConfig from @pikku/core with local middleware and render types.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const serializeServicesMap: (requiredServices: Set<string>, forceRequiredServices: string[] | undefined, servicesImport: string, sessionServicesImport: string) => string;
|
|
1
|
+
export declare const serializeServicesMap: (allSingletonServices: string[], allSessionServices: string[], requiredServices: Set<string>, forceRequiredServices: string[] | undefined, servicesImport: string, sessionServicesImport: string) => string;
|
|
2
2
|
export declare const pikkuServices: any;
|
|
@@ -3,7 +3,7 @@ import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
|
|
|
3
3
|
import { checkRequiredTypes } from '../../../utils/check-required-types.js';
|
|
4
4
|
import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
5
5
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
6
|
-
export const serializeServicesMap = (requiredServices, forceRequiredServices = [], servicesImport, sessionServicesImport) => {
|
|
6
|
+
export const serializeServicesMap = (allSingletonServices, allSessionServices, requiredServices, forceRequiredServices = [], servicesImport, sessionServicesImport) => {
|
|
7
7
|
// Use pre-aggregated services from inspector state
|
|
8
8
|
// This includes services from:
|
|
9
9
|
// - Wired functions (HTTP, channels, queues, schedulers, MCP, CLI, RPC)
|
|
@@ -11,45 +11,73 @@ export const serializeServicesMap = (requiredServices, forceRequiredServices = [
|
|
|
11
11
|
// - Permissions used by wired functions
|
|
12
12
|
// - Session factories
|
|
13
13
|
const usedServices = new Set(requiredServices);
|
|
14
|
-
// Internal services that are created internally
|
|
15
|
-
|
|
14
|
+
// Internal services that are created internally by the framework (PikkuInteraction)
|
|
15
|
+
// These should not appear in the services maps
|
|
16
|
+
const internalServices = new Set([
|
|
17
|
+
'rpc',
|
|
18
|
+
'mcp',
|
|
19
|
+
'channel',
|
|
20
|
+
'userSession',
|
|
21
|
+
'cli',
|
|
22
|
+
'http',
|
|
23
|
+
'queue',
|
|
24
|
+
'scheduledTask',
|
|
25
|
+
]);
|
|
16
26
|
// Add force-required services that might not be detected from function inspection
|
|
17
27
|
forceRequiredServices.forEach((service) => {
|
|
18
28
|
if (!internalServices.has(service)) {
|
|
19
29
|
usedServices.add(service);
|
|
20
30
|
}
|
|
21
31
|
});
|
|
22
|
-
// Create a map of services with true for all needed services
|
|
23
|
-
const servicesMap = Object.fromEntries(Array.from(usedServices)
|
|
24
|
-
.sort()
|
|
25
|
-
.map((service) => [service, true]));
|
|
26
|
-
// Generate the TypeScript code
|
|
27
|
-
const serviceKeys = Object.keys(servicesMap).sort();
|
|
28
32
|
// Services that are always required internally by the framework
|
|
29
33
|
const defaultServices = ['config', 'logger', 'variables', 'schema'];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
//
|
|
34
|
+
defaultServices.forEach((service) => usedServices.add(service));
|
|
35
|
+
// Create singleton services map: all singleton services with true/false based on usage
|
|
36
|
+
const singletonServicesMap = {};
|
|
37
|
+
allSingletonServices.forEach((service) => {
|
|
38
|
+
singletonServicesMap[service] = usedServices.has(service);
|
|
39
|
+
});
|
|
40
|
+
// Create session services map: all session services with true/false based on usage
|
|
41
|
+
// Exclude internal framework services (PikkuInteraction)
|
|
42
|
+
const sessionServicesMap = {};
|
|
43
|
+
allSessionServices.forEach((service) => {
|
|
44
|
+
if (!internalServices.has(service)) {
|
|
45
|
+
sessionServicesMap[service] = usedServices.has(service);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
// Get all required service names (those marked as true)
|
|
49
|
+
const requiredSingletonServiceNames = Object.keys(singletonServicesMap)
|
|
50
|
+
.filter((key) => singletonServicesMap[key])
|
|
51
|
+
.sort();
|
|
52
|
+
const requiredSessionServiceNames = Object.keys(sessionServicesMap)
|
|
53
|
+
.filter((key) => sessionServicesMap[key])
|
|
54
|
+
.sort();
|
|
37
55
|
const code = [
|
|
38
56
|
servicesImport,
|
|
39
57
|
sessionServicesImport,
|
|
40
|
-
"import type { PikkuInteraction } from '@pikku/core'",
|
|
41
58
|
'',
|
|
42
|
-
'
|
|
43
|
-
|
|
59
|
+
'// Singleton services map: true if required, false if available but unused',
|
|
60
|
+
'export const requiredSingletonServices = {',
|
|
61
|
+
...Object.keys(singletonServicesMap)
|
|
62
|
+
.sort()
|
|
63
|
+
.map((service) => ` '${service}': ${singletonServicesMap[service]},`),
|
|
64
|
+
'} as const',
|
|
65
|
+
'',
|
|
66
|
+
'// Session services map: true if required, false if available but unused',
|
|
67
|
+
'export const requiredSessionServices = {',
|
|
68
|
+
...Object.keys(sessionServicesMap)
|
|
69
|
+
.sort()
|
|
70
|
+
.map((service) => ` '${service}': ${sessionServicesMap[service]},`),
|
|
44
71
|
'} as const',
|
|
45
72
|
'',
|
|
46
|
-
'//
|
|
47
|
-
|
|
48
|
-
|
|
73
|
+
'// Type exports',
|
|
74
|
+
requiredSingletonServiceNames.length > 0
|
|
75
|
+
? `export type RequiredSingletonServices = Pick<SingletonServices, ${requiredSingletonServiceNames.map((key) => `'${key}'`).join(' | ')}> & Partial<Omit<SingletonServices, ${requiredSingletonServiceNames.map((key) => `'${key}'`).join(' | ')}>>`
|
|
76
|
+
: 'export type RequiredSingletonServices = Partial<SingletonServices>',
|
|
49
77
|
'',
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
78
|
+
requiredSessionServiceNames.length > 0
|
|
79
|
+
? `export type RequiredSessionServices = Pick<Services, ${requiredSessionServiceNames.map((key) => `'${key}'`).join(' | ')}> & Partial<Omit<Services, ${requiredSessionServiceNames.map((key) => `'${key}'`).join(' | ')}>>`
|
|
80
|
+
: 'export type RequiredSessionServices = Partial<Services>',
|
|
53
81
|
'',
|
|
54
82
|
].join('\n');
|
|
55
83
|
return code;
|
|
@@ -68,7 +96,7 @@ export const pikkuServices = pikkuSessionlessFunc({
|
|
|
68
96
|
}
|
|
69
97
|
const servicesImport = `import type { ${singletonServicesType.type} } from '${getFileImportRelativePath(config.typesDeclarationFile, singletonServicesType.typePath, config.packageMappings)}'`;
|
|
70
98
|
const sessionServicesImport = `import type { ${sessionServicesType.type} } from '${getFileImportRelativePath(config.typesDeclarationFile, sessionServicesType.typePath, config.packageMappings)}'`;
|
|
71
|
-
const servicesCode = serializeServicesMap(visitState.serviceAggregation.requiredServices, config.forceRequiredServices, servicesImport, sessionServicesImport);
|
|
99
|
+
const servicesCode = serializeServicesMap(visitState.serviceAggregation.allSingletonServices, visitState.serviceAggregation.allSessionServices, visitState.serviceAggregation.requiredServices, config.forceRequiredServices, servicesImport, sessionServicesImport);
|
|
72
100
|
await writeFileInDir(logger, config.servicesFile, servicesCode);
|
|
73
101
|
},
|
|
74
102
|
middleware: [
|
|
@@ -7,8 +7,8 @@ import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-
|
|
|
7
7
|
export const pikkuSchemas = pikkuSessionlessFunc({
|
|
8
8
|
func: async ({ logger, config, getInspectorState }) => {
|
|
9
9
|
const visitState = await getInspectorState();
|
|
10
|
-
const schemas = await generateSchemas(logger, config.tsconfig, visitState.functions.typesMap, visitState.functions.meta, visitState.http.meta, config.schemasFromTypes);
|
|
11
|
-
await saveSchemas(logger, config.schemaDirectory, schemas, visitState.functions.typesMap, visitState.functions.meta, config.
|
|
10
|
+
const schemas = await generateSchemas(logger, config.tsconfig, visitState.functions.typesMap, visitState.functions.meta, visitState.http.meta, config.schemasFromTypes, config.schema?.additionalProperties);
|
|
11
|
+
await saveSchemas(logger, config.schemaDirectory, schemas, visitState.functions.typesMap, visitState.functions.meta, config.schemasFromTypes, config.schema?.supportsImportAttributes);
|
|
12
12
|
return true;
|
|
13
13
|
},
|
|
14
14
|
middleware: [
|
|
@@ -16,7 +16,7 @@ export const pikkuOpenAPI = pikkuSessionlessFunc({
|
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
const { http, functions } = await getInspectorState();
|
|
19
|
-
const schemas = await generateSchemas(logger, tsconfig, functions.typesMap, functions.meta, http.meta, schemasFromTypes);
|
|
19
|
+
const schemas = await generateSchemas(logger, tsconfig, functions.typesMap, functions.meta, http.meta, schemasFromTypes, config.schema?.additionalProperties);
|
|
20
20
|
const openAPISpec = await generateOpenAPISpec(logger, functions.meta, http.meta, schemas, openAPI.additionalInfo);
|
|
21
21
|
if (openAPI.outputFile.endsWith('.json')) {
|
|
22
22
|
await writeFileInDir(logger, openAPI.outputFile, JSON.stringify(openAPISpec, null, 2), { ignoreModifyComment: true });
|
|
@@ -9,20 +9,13 @@ export const pikkuMiddleware = pikkuSessionlessFunc({
|
|
|
9
9
|
const { middleware } = state;
|
|
10
10
|
const { middlewareFile, packageMappings } = config;
|
|
11
11
|
let filesGenerated = false;
|
|
12
|
-
// Check if there are any middleware
|
|
13
|
-
const hasHTTPFactories = Array.from(state.http.routeMiddleware.values()).some((meta) => meta.exportName && meta.isFactory);
|
|
14
|
-
const hasTagFactories = Array.from(state.middleware.tagMiddleware.values()).some((meta) => meta.exportName && meta.isFactory);
|
|
15
|
-
const hasFactories = hasHTTPFactories || hasTagFactories;
|
|
16
|
-
// Generate middleware imports file if there are factories
|
|
17
|
-
if (hasFactories) {
|
|
18
|
-
await writeFileInDir(logger, middlewareFile, serializeMiddlewareImports(middlewareFile, middleware, state.http, packageMappings));
|
|
19
|
-
filesGenerated = true;
|
|
20
|
-
}
|
|
21
|
-
// Generate middleware groups metadata file
|
|
12
|
+
// Check if there are any middleware groups
|
|
22
13
|
const hasHTTPGroups = state.http.routeMiddleware.size > 0;
|
|
23
14
|
const hasTagGroups = state.middleware.tagMiddleware.size > 0;
|
|
24
15
|
if (hasHTTPGroups || hasTagGroups) {
|
|
25
16
|
await writeFileInDir(logger, config.middlewareGroupsMetaFile, serializeMiddlewareGroupsMeta(state));
|
|
17
|
+
// Always generate middleware imports file when groups exist (even if empty)
|
|
18
|
+
await writeFileInDir(logger, middlewareFile, serializeMiddlewareImports(middlewareFile, middleware, state.http, packageMappings));
|
|
26
19
|
filesGenerated = true;
|
|
27
20
|
}
|
|
28
21
|
return filesGenerated;
|
|
@@ -7,7 +7,7 @@ export interface LogCommandInfoOptions {
|
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Middleware to log command execution timing and status
|
|
10
|
-
*
|
|
10
|
+
* Uses debug level so it only shows with --verbose flag
|
|
11
11
|
*/
|
|
12
12
|
export declare const logCommandInfoAndTime: ({ commandStart, commandEnd, }: LogCommandInfoOptions) => PikkuMiddleware;
|
|
13
13
|
export {};
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Middleware to log command execution timing and status
|
|
3
|
-
*
|
|
3
|
+
* Uses debug level so it only shows with --verbose flag
|
|
4
4
|
*/
|
|
5
5
|
export const logCommandInfoAndTime = ({ commandStart, commandEnd, }) => {
|
|
6
6
|
return async ({ logger }, _interaction, next) => {
|
|
7
|
-
// Log start
|
|
7
|
+
// Log start (debug level - only shows with --verbose)
|
|
8
8
|
const start = Date.now();
|
|
9
|
-
logger.
|
|
9
|
+
logger.debug(`• ${commandStart}...`);
|
|
10
10
|
// Execute the function
|
|
11
11
|
await next();
|
|
12
|
-
// Log completion
|
|
13
|
-
logger.
|
|
12
|
+
// Log completion (debug level - only shows with --verbose)
|
|
13
|
+
logger.debug({
|
|
14
|
+
type: 'success',
|
|
15
|
+
message: `✓ ${commandEnd} in ${Date.now() - start}ms.`,
|
|
16
|
+
});
|
|
14
17
|
};
|
|
15
18
|
};
|
|
@@ -9,15 +9,20 @@ export declare class CLILogger implements Logger {
|
|
|
9
9
|
silent?: boolean;
|
|
10
10
|
});
|
|
11
11
|
setLevel(level: LogLevel): void;
|
|
12
|
+
setSilent(silent: boolean): void;
|
|
13
|
+
isSilent(): boolean;
|
|
12
14
|
info(message: string | {
|
|
13
15
|
message: string;
|
|
14
16
|
type?: string;
|
|
15
17
|
}): void;
|
|
16
18
|
error(message: string): void;
|
|
17
19
|
warn(message: string): void;
|
|
18
|
-
debug(message: string
|
|
20
|
+
debug(message: string | {
|
|
21
|
+
message: string;
|
|
22
|
+
type?: string;
|
|
23
|
+
}): void;
|
|
19
24
|
critical(code: ErrorCode, message: string): void;
|
|
20
25
|
hasCriticalErrors(): boolean;
|
|
21
|
-
|
|
26
|
+
logLogo(): void;
|
|
22
27
|
private primary;
|
|
23
28
|
}
|