@pikku/cli 0.12.15 → 0.12.16
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/cli.schema.json +1 -1
- package/console-app/assets/index-CzMWJFqj.js +700 -0
- package/console-app/index.html +1 -1
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +16 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +68 -5
- package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
- package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +16 -19
- package/dist/.pikku/function/pikku-function-types.gen.js +15 -19
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +190 -107
- package/dist/.pikku/function/pikku-functions.gen.js +6 -2
- 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-meta.gen.json +18 -1
- package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +2 -2
- package/dist/.pikku/http/pikku-http-wirings.gen.js +3 -3
- 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/pikku-bootstrap.gen.d.ts +3 -10
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -18
- package/dist/.pikku/pikku-meta-service.gen.d.ts +7 -0
- package/dist/.pikku/pikku-meta-service.gen.js +9 -0
- package/dist/.pikku/pikku-services.gen.d.ts +2 -1
- package/dist/.pikku/pikku-services.gen.js +1 -0
- package/dist/.pikku/pikku-types.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.js +1 -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/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +5 -1
- 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/schemas/register.gen.js +15 -7
- package/dist/.pikku/schemas/schemas/DeployApplyInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/DeployPlanInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuNewAddonInput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuWorkflowRoutesOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/RemoteRPCHandlerInput.schema.json +1 -0
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +3 -24
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -14
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/src/cli.wiring.js +63 -4
- package/dist/src/deploy/analyzer/analyzer.d.ts +16 -0
- package/dist/src/deploy/analyzer/analyzer.js +557 -0
- package/dist/src/deploy/analyzer/index.d.ts +3 -0
- package/dist/src/deploy/analyzer/index.js +1 -0
- package/dist/src/deploy/analyzer/manifest.d.ts +112 -0
- package/dist/src/deploy/analyzer/manifest.js +8 -0
- package/dist/src/deploy/build-pipeline.d.ts +39 -0
- package/dist/src/deploy/build-pipeline.js +209 -0
- package/dist/src/deploy/bundler/bundler.d.ts +30 -0
- package/dist/src/deploy/bundler/bundler.js +196 -0
- package/dist/src/deploy/bundler/dep-extractor.d.ts +35 -0
- package/dist/src/deploy/bundler/dep-extractor.js +213 -0
- package/dist/src/deploy/bundler/index.d.ts +3 -0
- package/dist/src/deploy/bundler/index.js +2 -0
- package/dist/src/deploy/bundler/types.d.ts +21 -0
- package/dist/src/deploy/bundler/types.js +5 -0
- package/dist/src/deploy/codegen/index.d.ts +2 -0
- package/dist/src/deploy/codegen/index.js +1 -0
- package/dist/src/deploy/codegen/per-unit-codegen.d.ts +44 -0
- package/dist/src/deploy/codegen/per-unit-codegen.js +216 -0
- package/dist/src/deploy/plan/executor.d.ts +9 -0
- package/dist/src/deploy/plan/executor.js +49 -0
- package/dist/src/deploy/plan/formatter.d.ts +4 -0
- package/dist/src/deploy/plan/formatter.js +114 -0
- package/dist/src/deploy/plan/index.d.ts +5 -0
- package/dist/src/deploy/plan/index.js +3 -0
- package/dist/src/deploy/plan/planner.d.ts +4 -0
- package/dist/src/deploy/plan/planner.js +220 -0
- package/dist/src/deploy/plan/provider.d.ts +30 -0
- package/dist/src/deploy/plan/provider.js +1 -0
- package/dist/src/deploy/plan/types.d.ts +29 -0
- package/dist/src/deploy/plan/types.js +1 -0
- package/dist/src/deploy/provider-adapter.d.ts +111 -0
- package/dist/src/deploy/provider-adapter.js +10 -0
- package/dist/src/functions/commands/all.js +6 -2
- package/dist/src/functions/commands/deploy-apply.d.ts +22 -0
- package/dist/src/functions/commands/deploy-apply.js +206 -0
- package/dist/src/functions/commands/deploy-info.d.ts +1 -0
- package/dist/src/functions/commands/deploy-info.js +122 -0
- package/dist/src/functions/commands/deploy-plan.d.ts +10 -0
- package/dist/src/functions/commands/deploy-plan.js +96 -0
- package/dist/src/functions/commands/enable.js +1 -1
- package/dist/src/functions/commands/new-addon.d.ts +3 -0
- package/dist/src/functions/commands/new-addon.js +68 -2
- package/dist/src/functions/commands/pikku-command-bootstrap.js +30 -20
- package/dist/src/functions/runtimes/nextjs/pikku-command-nextjs.js +7 -3
- package/dist/src/functions/wirings/ai-agent/pikku-command-ai-agent.js +7 -5
- package/dist/src/functions/wirings/channels/pikku-channels.js +3 -0
- package/dist/src/functions/wirings/channels/pikku-command-channels.js +3 -0
- package/dist/src/functions/wirings/cli/pikku-command-cli.js +3 -0
- package/dist/src/functions/wirings/cli/serialize-channel-cli.js +2 -2
- package/dist/src/functions/wirings/console/serialize-console-functions.js +2 -2
- package/dist/src/functions/wirings/functions/pikku-command-services.d.ts +1 -1
- package/dist/src/functions/wirings/functions/pikku-command-services.js +9 -2
- package/dist/src/functions/wirings/functions/serialize-function-imports.js +5 -3
- package/dist/src/functions/wirings/functions/serialize-function-types.js +17 -19
- package/dist/src/functions/wirings/http/pikku-command-http-routes.js +3 -0
- package/dist/src/functions/wirings/http/pikku-http-routes.js +3 -0
- package/dist/src/functions/wirings/mcp/pikku-command-mcp.js +6 -0
- package/dist/src/functions/wirings/package/pikku-command-package.js +1 -1
- package/dist/src/functions/wirings/package/serialize-package.d.ts +1 -1
- package/dist/src/functions/wirings/package/serialize-package.js +5 -2
- package/dist/src/functions/wirings/queue/pikku-command-queue.js +4 -0
- package/dist/src/functions/wirings/queue/pikku-queue.js +4 -0
- package/dist/src/functions/wirings/queue/serialize-queue-map.js +4 -1
- package/dist/src/functions/wirings/rpc/pikku-command-rpc.js +10 -3
- package/dist/src/functions/wirings/rpc/serialize-public-rpc.js +5 -27
- package/dist/src/functions/wirings/rpc/serialize-remote-rpc.js +11 -14
- package/dist/src/functions/wirings/rpc/serialize-rpc-wrapper.js +28 -3
- package/dist/src/functions/wirings/rpc/serialize-typed-rpc-map.js +15 -5
- package/dist/src/functions/wirings/scheduler/pikku-command-scheduler.js +4 -0
- package/dist/src/functions/wirings/workflow/pikku-command-workflow-routes.d.ts +1 -0
- package/dist/src/functions/wirings/workflow/pikku-command-workflow-routes.js +21 -0
- package/dist/src/functions/wirings/workflow/pikku-command-workflow.js +10 -9
- package/dist/src/functions/wirings/workflow/serialize-workflow-map.d.ts +6 -1
- package/dist/src/functions/wirings/workflow/serialize-workflow-map.js +42 -5
- package/dist/src/functions/wirings/workflow/serialize-workflow-registration.d.ts +1 -1
- package/dist/src/functions/wirings/workflow/serialize-workflow-registration.js +3 -2
- package/dist/src/functions/wirings/workflow/serialize-workflow-routes.d.ts +4 -0
- package/dist/src/functions/wirings/workflow/serialize-workflow-routes.js +139 -0
- package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +4 -51
- package/dist/src/scaffold/rpc-remote.gen.d.ts +10 -0
- package/dist/src/scaffold/rpc-remote.gen.js +22 -0
- package/dist/src/services.js +12 -7
- package/dist/src/utils/pikku-cli-config.d.ts +1 -1
- package/dist/src/utils/pikku-cli-config.js +30 -28
- package/dist/src/utils/strip-verbose-meta.js +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -4
- package/console-app/assets/index-robZPL3O.js +0 -672
- package/dist/src/functions/wirings/workflow/serialize-workflow-workers.d.ts +0 -4
- package/dist/src/functions/wirings/workflow/serialize-workflow-workers.js +0 -47
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { basename, join, relative } from 'node:path';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { pikkuSessionlessFunc } from '#pikku';
|
|
4
|
+
import { runBuildPipeline } from '../../deploy/build-pipeline.js';
|
|
5
|
+
function toRelativeImport(fromDir, toFile) {
|
|
6
|
+
let rel = relative(fromDir, toFile).replace(/\\/g, '/');
|
|
7
|
+
if (!rel.startsWith('.'))
|
|
8
|
+
rel = `./${rel}`;
|
|
9
|
+
return rel.replace(/\.ts$/, '.js');
|
|
10
|
+
}
|
|
11
|
+
export function getEntryContext(unitDir, pikkuDir, unit, inspectorState) {
|
|
12
|
+
const bootstrapRelative = relative(unitDir, join(pikkuDir, 'pikku-bootstrap.gen.js'));
|
|
13
|
+
const bootstrapPath = bootstrapRelative.startsWith('./') || bootstrapRelative.startsWith('../')
|
|
14
|
+
? bootstrapRelative
|
|
15
|
+
: `./${bootstrapRelative}`;
|
|
16
|
+
const { pikkuConfigFactory, singletonServicesFactory, singletonServicesType, } = inspectorState.filesAndMethods;
|
|
17
|
+
if (!pikkuConfigFactory || !singletonServicesFactory) {
|
|
18
|
+
throw new Error('Cannot generate deploy entries: createConfig and createSingletonServices must be defined in your project');
|
|
19
|
+
}
|
|
20
|
+
const configRelative = toRelativeImport(unitDir, pikkuConfigFactory.file);
|
|
21
|
+
const servicesRelative = toRelativeImport(unitDir, singletonServicesFactory.file);
|
|
22
|
+
const singletonServicesImport = singletonServicesType
|
|
23
|
+
? `import type { ${singletonServicesType.type} } from '${toRelativeImport(unitDir, singletonServicesType.typePath)}'`
|
|
24
|
+
: '';
|
|
25
|
+
const servicesType = singletonServicesType
|
|
26
|
+
? `Partial<${singletonServicesType.type}>`
|
|
27
|
+
: 'Record<string, unknown>';
|
|
28
|
+
return {
|
|
29
|
+
unit,
|
|
30
|
+
unitDir,
|
|
31
|
+
bootstrapPath,
|
|
32
|
+
configImport: `import { ${pikkuConfigFactory.variable} } from '${configRelative}'`,
|
|
33
|
+
configVar: pikkuConfigFactory.variable,
|
|
34
|
+
servicesImport: `import { ${singletonServicesFactory.variable} } from '${servicesRelative}'`,
|
|
35
|
+
servicesVar: singletonServicesFactory.variable,
|
|
36
|
+
singletonServicesImport,
|
|
37
|
+
servicesType,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function sanitizeProjectId(raw) {
|
|
41
|
+
return (raw
|
|
42
|
+
.toLowerCase()
|
|
43
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
44
|
+
.replace(/-+/g, '-')
|
|
45
|
+
.replace(/^-|-$/g, '') || 'pikku-project');
|
|
46
|
+
}
|
|
47
|
+
async function resolveProjectId(projectDir) {
|
|
48
|
+
try {
|
|
49
|
+
const pkg = JSON.parse(await readFile(join(projectDir, 'package.json'), 'utf-8'));
|
|
50
|
+
if (pkg.name) {
|
|
51
|
+
const name = pkg.name.replace(/^@[^/]+\//, '');
|
|
52
|
+
return sanitizeProjectId(name);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
const err = e;
|
|
57
|
+
if (err?.code !== 'ENOENT') {
|
|
58
|
+
console.warn(`Warning: failed to read package.json: ${err?.message ?? e}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return sanitizeProjectId(basename(projectDir));
|
|
62
|
+
}
|
|
63
|
+
export async function resolveProvider(config, providerName) {
|
|
64
|
+
const name = providerName ?? config?.deploy?.defaultProvider ?? 'cloudflare';
|
|
65
|
+
const providers = config?.deploy?.providers ?? {
|
|
66
|
+
cloudflare: '@pikku/deploy-cloudflare',
|
|
67
|
+
serverless: '@pikku/deploy-serverless',
|
|
68
|
+
azure: '@pikku/deploy-azure',
|
|
69
|
+
standalone: '@pikku/deploy-standalone',
|
|
70
|
+
};
|
|
71
|
+
const packageName = providers[name];
|
|
72
|
+
if (!packageName) {
|
|
73
|
+
throw new Error(`Unknown deploy provider: '${name}'. Available: ${Object.keys(providers).join(', ')}`);
|
|
74
|
+
}
|
|
75
|
+
const adapterExportName = name.charAt(0).toUpperCase() + name.slice(1) + 'ProviderAdapter';
|
|
76
|
+
try {
|
|
77
|
+
const mod = await import(packageName);
|
|
78
|
+
if (typeof mod.createAdapter === 'function') {
|
|
79
|
+
return mod.createAdapter();
|
|
80
|
+
}
|
|
81
|
+
if (typeof mod[adapterExportName] === 'function') {
|
|
82
|
+
return new mod[adapterExportName]();
|
|
83
|
+
}
|
|
84
|
+
throw new Error(`Deploy provider '${packageName}' does not export createAdapter() or ${adapterExportName}`);
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
const err = e;
|
|
88
|
+
if (err?.code === 'ERR_MODULE_NOT_FOUND' ||
|
|
89
|
+
err?.code === 'MODULE_NOT_FOUND') {
|
|
90
|
+
throw new Error(`Deploy provider '${packageName}' is not installed. Run: yarn add ${packageName}`);
|
|
91
|
+
}
|
|
92
|
+
throw e;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const ANSI = {
|
|
96
|
+
green: '\x1b[32m',
|
|
97
|
+
red: '\x1b[31m',
|
|
98
|
+
bold: '\x1b[1m',
|
|
99
|
+
reset: '\x1b[0m',
|
|
100
|
+
};
|
|
101
|
+
async function writeResultFile(resultFile, result) {
|
|
102
|
+
if (resultFile) {
|
|
103
|
+
const { writeFile } = await import('node:fs/promises');
|
|
104
|
+
await writeFile(resultFile, JSON.stringify(result, null, 2), 'utf-8');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async function runDeploy(provider, providerDir, logger, resultFile) {
|
|
108
|
+
if (typeof provider.deploy !== 'function') {
|
|
109
|
+
logger.error(`Provider '${provider.name}' does not support deploy.`);
|
|
110
|
+
await writeResultFile(resultFile, {
|
|
111
|
+
success: false,
|
|
112
|
+
errors: [{ step: 'provider', error: 'No deploy support' }],
|
|
113
|
+
});
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
logger.info(`Deploying via ${provider.name}...`);
|
|
117
|
+
let deployResult;
|
|
118
|
+
try {
|
|
119
|
+
deployResult = await provider.deploy({
|
|
120
|
+
buildDir: providerDir,
|
|
121
|
+
logger,
|
|
122
|
+
onProgress: (_step, _detail) => {
|
|
123
|
+
process.stdout.write(` ${ANSI.green}done${ANSI.reset}\n`);
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
129
|
+
deployResult = {
|
|
130
|
+
success: false,
|
|
131
|
+
errors: [{ step: 'deploy', error: message }],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
await writeResultFile(resultFile, deployResult);
|
|
135
|
+
console.log('');
|
|
136
|
+
if (deployResult.success) {
|
|
137
|
+
logger.info(`${ANSI.green}${ANSI.bold}Deployment complete.${ANSI.reset}`);
|
|
138
|
+
logger.info(` ${deployResult.workersDeployed?.length ?? 0} units deployed, ${deployResult.resourcesCreated?.length ?? 0} resources created`);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
logger.error(`Deployment finished with ${deployResult.errors.length} error(s):`);
|
|
142
|
+
for (const e of deployResult.errors) {
|
|
143
|
+
logger.error(` ${e.step}: ${e.error}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
export const deployApply = pikkuSessionlessFunc({
|
|
148
|
+
func: async ({ logger, config, getInspectorState }, data) => {
|
|
149
|
+
const projectDir = config.rootDir;
|
|
150
|
+
const provider = await resolveProvider(config, data?.provider);
|
|
151
|
+
const fromPlan = data?.fromPlan ?? false;
|
|
152
|
+
const resultFile = data?.resultFile;
|
|
153
|
+
if (fromPlan) {
|
|
154
|
+
// Skip build pipeline — deploy from existing plan output
|
|
155
|
+
const { join } = await import('node:path');
|
|
156
|
+
const { existsSync } = await import('node:fs');
|
|
157
|
+
const providerDir = join(projectDir, '.deploy', provider.deployDirName);
|
|
158
|
+
const infraPath = join(providerDir, 'infra.json');
|
|
159
|
+
if (!existsSync(infraPath)) {
|
|
160
|
+
logger.error(`No plan found at ${providerDir}. Run 'pikku deploy plan' first.`);
|
|
161
|
+
await writeResultFile(resultFile, {
|
|
162
|
+
success: false,
|
|
163
|
+
errors: [{ step: 'plan', error: 'No plan found' }],
|
|
164
|
+
});
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
await runDeploy(provider, providerDir, logger, resultFile);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
// Full build + deploy pipeline
|
|
171
|
+
const inspectorState = await getInspectorState(true);
|
|
172
|
+
const projectId = await resolveProjectId(projectDir);
|
|
173
|
+
const buildResult = await runBuildPipeline({
|
|
174
|
+
projectDir,
|
|
175
|
+
projectId,
|
|
176
|
+
provider,
|
|
177
|
+
inspectorState,
|
|
178
|
+
serverlessIncompatible: config.deploy?.serverlessIncompatible,
|
|
179
|
+
getEntryContext,
|
|
180
|
+
logger,
|
|
181
|
+
});
|
|
182
|
+
if (buildResult.manifest.units.length === 0) {
|
|
183
|
+
logger.info('No deployment units found. Nothing to deploy.');
|
|
184
|
+
await writeResultFile(resultFile, {
|
|
185
|
+
success: true,
|
|
186
|
+
workersDeployed: [],
|
|
187
|
+
resourcesCreated: [],
|
|
188
|
+
errors: [],
|
|
189
|
+
});
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const { providerDir, bundled } = buildResult;
|
|
193
|
+
if (typeof provider.deploy === 'function') {
|
|
194
|
+
await runDeploy(provider, providerDir, logger, resultFile);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
logger.info(`${ANSI.green}${ANSI.bold}Build complete.${ANSI.reset}`);
|
|
198
|
+
logger.info(` ${bundled.length} functions bundled to ${ANSI.bold}${providerDir}${ANSI.reset}`);
|
|
199
|
+
await writeResultFile(resultFile, {
|
|
200
|
+
success: true,
|
|
201
|
+
buildOnly: true,
|
|
202
|
+
unitCount: bundled.length,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const deployInfo: import("#pikku").PikkuFunctionConfig<void, void, "session" | "rpc", import("#pikku").PikkuFunctionSessionless<void, void, "session" | "rpc", import("#pikku").Services> | import("#pikku").PikkuFunction<void, void, "session" | "rpc", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { basename, join } from 'node:path';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { pikkuVoidFunc } from '#pikku';
|
|
4
|
+
import { analyzeDeployment } from '../../deploy/analyzer/index.js';
|
|
5
|
+
const ANSI = {
|
|
6
|
+
green: '\x1b[32m',
|
|
7
|
+
blue: '\x1b[34m',
|
|
8
|
+
yellow: '\x1b[33m',
|
|
9
|
+
dim: '\x1b[2m',
|
|
10
|
+
bold: '\x1b[1m',
|
|
11
|
+
reset: '\x1b[0m',
|
|
12
|
+
};
|
|
13
|
+
const ROLE_COLORS = {
|
|
14
|
+
function: ANSI.blue,
|
|
15
|
+
mcp: '\x1b[35m', // magenta
|
|
16
|
+
agent: '\x1b[33m', // yellow
|
|
17
|
+
channel: ANSI.dim,
|
|
18
|
+
'workflow-step': '\x1b[34m',
|
|
19
|
+
workflow: '\x1b[34m',
|
|
20
|
+
};
|
|
21
|
+
function padRight(str, len) {
|
|
22
|
+
return str + ' '.repeat(Math.max(0, len - str.length));
|
|
23
|
+
}
|
|
24
|
+
function sanitizeProjectId(raw) {
|
|
25
|
+
return (raw
|
|
26
|
+
.toLowerCase()
|
|
27
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
28
|
+
.replace(/-+/g, '-')
|
|
29
|
+
.replace(/^-|-$/g, '') || 'pikku-project');
|
|
30
|
+
}
|
|
31
|
+
async function resolveProjectId(projectDir) {
|
|
32
|
+
try {
|
|
33
|
+
const pkg = JSON.parse(await readFile(join(projectDir, 'package.json'), 'utf-8'));
|
|
34
|
+
if (pkg.name) {
|
|
35
|
+
const name = pkg.name.replace(/^@[^/]+\//, '');
|
|
36
|
+
return sanitizeProjectId(name);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch { }
|
|
40
|
+
return sanitizeProjectId(basename(projectDir));
|
|
41
|
+
}
|
|
42
|
+
export const deployInfo = pikkuVoidFunc({
|
|
43
|
+
func: async ({ logger, config, getInspectorState }) => {
|
|
44
|
+
logger.info('Analyzing project...');
|
|
45
|
+
const inspectorState = await getInspectorState(true);
|
|
46
|
+
const projectId = await resolveProjectId(config.rootDir);
|
|
47
|
+
const manifest = analyzeDeployment(inspectorState, { projectId });
|
|
48
|
+
console.log('');
|
|
49
|
+
console.log(`${ANSI.bold}Project:${ANSI.reset} ${manifest.projectId}`);
|
|
50
|
+
console.log('');
|
|
51
|
+
// Units
|
|
52
|
+
console.log(`${ANSI.bold}Units (${manifest.units.length}):${ANSI.reset}`);
|
|
53
|
+
for (const u of manifest.units) {
|
|
54
|
+
const color = ROLE_COLORS[u.role] ?? ANSI.dim;
|
|
55
|
+
const fns = u.functionIds.join(', ');
|
|
56
|
+
console.log(` ${color}${padRight(u.role, 22)}${ANSI.reset} ${ANSI.bold}${padRight(u.name, 30)}${ANSI.reset} ${ANSI.dim}[${fns}]${ANSI.reset}`);
|
|
57
|
+
for (const handler of u.handlers) {
|
|
58
|
+
if (handler.type === 'fetch' && handler.routes.length > 0) {
|
|
59
|
+
for (const route of handler.routes) {
|
|
60
|
+
console.log(` ${ANSI.dim}${route.method} ${route.route}${ANSI.reset}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else if (handler.type === 'queue') {
|
|
64
|
+
console.log(` ${ANSI.dim}queue: ${handler.queueName}${ANSI.reset}`);
|
|
65
|
+
}
|
|
66
|
+
else if (handler.type === 'scheduled') {
|
|
67
|
+
console.log(` ${ANSI.dim}cron: ${handler.schedule}${ANSI.reset}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Queues
|
|
72
|
+
if (manifest.queues.length > 0) {
|
|
73
|
+
console.log('');
|
|
74
|
+
console.log(`${ANSI.bold}Queues (${manifest.queues.length}):${ANSI.reset}`);
|
|
75
|
+
for (const q of manifest.queues) {
|
|
76
|
+
console.log(` ${padRight(q.name, 30)} ${ANSI.dim}-> ${q.consumerUnit}${ANSI.reset}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Scheduled tasks
|
|
80
|
+
if (manifest.scheduledTasks.length > 0) {
|
|
81
|
+
console.log('');
|
|
82
|
+
console.log(`${ANSI.bold}Scheduled Tasks (${manifest.scheduledTasks.length}):${ANSI.reset}`);
|
|
83
|
+
for (const t of manifest.scheduledTasks) {
|
|
84
|
+
console.log(` ${padRight(t.name, 30)} ${ANSI.dim}${t.schedule} -> ${t.unitName}${ANSI.reset}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Channels
|
|
88
|
+
if (manifest.channels.length > 0) {
|
|
89
|
+
console.log('');
|
|
90
|
+
console.log(`${ANSI.bold}Channels (${manifest.channels.length}):${ANSI.reset}`);
|
|
91
|
+
for (const c of manifest.channels) {
|
|
92
|
+
console.log(` ${padRight(c.name, 30)} ${ANSI.dim}${c.route} -> ${c.unitName}${ANSI.reset}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Agents
|
|
96
|
+
if (manifest.agents.length > 0) {
|
|
97
|
+
console.log('');
|
|
98
|
+
console.log(`${ANSI.bold}Agents (${manifest.agents.length}):${ANSI.reset}`);
|
|
99
|
+
for (const a of manifest.agents) {
|
|
100
|
+
const tools = a.toolFunctionIds.join(', ');
|
|
101
|
+
console.log(` ${padRight(a.name, 30)} ${ANSI.dim}[${tools}]${ANSI.reset}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Secrets
|
|
105
|
+
if (manifest.secrets.length > 0) {
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log(`${ANSI.bold}Required Secrets (${manifest.secrets.length}):${ANSI.reset}`);
|
|
108
|
+
for (const s of manifest.secrets) {
|
|
109
|
+
console.log(` ${ANSI.yellow}${s.secretId}${ANSI.reset}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Variables
|
|
113
|
+
if (manifest.variables.length > 0) {
|
|
114
|
+
console.log('');
|
|
115
|
+
console.log(`${ANSI.bold}Variables (${manifest.variables.length}):${ANSI.reset}`);
|
|
116
|
+
for (const v of manifest.variables) {
|
|
117
|
+
console.log(` ${v.variableId}${ANSI.dim} (${v.displayName})${ANSI.reset}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
console.log('');
|
|
121
|
+
},
|
|
122
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const deployPlan: import("#pikku").PikkuFunctionConfig<{
|
|
2
|
+
resultFile?: string;
|
|
3
|
+
provider?: string;
|
|
4
|
+
}, void, "session" | "rpc", import("#pikku").PikkuFunctionSessionless<{
|
|
5
|
+
resultFile?: string;
|
|
6
|
+
provider?: string;
|
|
7
|
+
}, void, "session" | "rpc", import("#pikku").Services> | import("#pikku").PikkuFunction<{
|
|
8
|
+
resultFile?: string;
|
|
9
|
+
provider?: string;
|
|
10
|
+
}, void, "session" | "rpc", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { basename, join } from 'node:path';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { pikkuSessionlessFunc } from '#pikku';
|
|
4
|
+
import { generatePlan } from '../../deploy/plan/index.js';
|
|
5
|
+
import { formatPlan } from '../../deploy/plan/formatter.js';
|
|
6
|
+
import { runBuildPipeline } from '../../deploy/build-pipeline.js';
|
|
7
|
+
import { resolveProvider, getEntryContext } from './deploy-apply.js';
|
|
8
|
+
function sanitizeProjectId(raw) {
|
|
9
|
+
return (raw
|
|
10
|
+
.toLowerCase()
|
|
11
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
12
|
+
.replace(/-+/g, '-')
|
|
13
|
+
.replace(/^-|-$/g, '') || 'pikku-project');
|
|
14
|
+
}
|
|
15
|
+
async function resolveProjectId(projectDir) {
|
|
16
|
+
try {
|
|
17
|
+
const pkg = JSON.parse(await readFile(join(projectDir, 'package.json'), 'utf-8'));
|
|
18
|
+
if (pkg.name) {
|
|
19
|
+
const name = pkg.name.replace(/^@[^/]+\//, '');
|
|
20
|
+
return sanitizeProjectId(name);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch { }
|
|
24
|
+
return sanitizeProjectId(basename(projectDir));
|
|
25
|
+
}
|
|
26
|
+
function createEmptyProvider() {
|
|
27
|
+
return {
|
|
28
|
+
async getCurrentState() {
|
|
29
|
+
return {
|
|
30
|
+
units: [],
|
|
31
|
+
queues: [],
|
|
32
|
+
scheduledTasks: [],
|
|
33
|
+
secrets: [],
|
|
34
|
+
variables: {},
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
async applyChange() {
|
|
38
|
+
throw new Error('Plan mode — apply not available');
|
|
39
|
+
},
|
|
40
|
+
async hasActiveWork() {
|
|
41
|
+
return { active: false, pendingCount: 0 };
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export const deployPlan = pikkuSessionlessFunc({
|
|
46
|
+
func: async ({ logger, config, getInspectorState }, data) => {
|
|
47
|
+
const projectDir = config.rootDir;
|
|
48
|
+
const inspectorState = await getInspectorState(true);
|
|
49
|
+
const projectId = await resolveProjectId(projectDir);
|
|
50
|
+
const provider = await resolveProvider(config, data?.provider);
|
|
51
|
+
const result = await runBuildPipeline({
|
|
52
|
+
projectDir,
|
|
53
|
+
projectId,
|
|
54
|
+
provider,
|
|
55
|
+
inspectorState,
|
|
56
|
+
serverlessIncompatible: config.deploy?.serverlessIncompatible,
|
|
57
|
+
getEntryContext,
|
|
58
|
+
logger,
|
|
59
|
+
});
|
|
60
|
+
if (result.manifest.units.length === 0) {
|
|
61
|
+
logger.info('No deployment units found.');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// Show plan
|
|
65
|
+
const deployProvider = createEmptyProvider();
|
|
66
|
+
const currentState = await deployProvider.getCurrentState(result.manifest.projectId);
|
|
67
|
+
const plan = await generatePlan(result.manifest, currentState, deployProvider);
|
|
68
|
+
console.log('');
|
|
69
|
+
console.log(formatPlan(plan));
|
|
70
|
+
console.log('');
|
|
71
|
+
// Summary
|
|
72
|
+
let totalSize = 0;
|
|
73
|
+
for (const b of result.bundled)
|
|
74
|
+
totalSize += b.bundleSizeBytes;
|
|
75
|
+
const formatBytes = (bytes) => bytes < 1024
|
|
76
|
+
? `${bytes}B`
|
|
77
|
+
: bytes < 1024 * 1024
|
|
78
|
+
? `${(bytes / 1024).toFixed(1)}KB`
|
|
79
|
+
: `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
80
|
+
logger.info(`${result.bundled.length} workers bundled (${formatBytes(totalSize)} total)`);
|
|
81
|
+
logger.info(`Output: ${result.providerDir}`);
|
|
82
|
+
// Write result file if --result-file is set (used by Fabric build pipeline)
|
|
83
|
+
const resultFile = data?.resultFile;
|
|
84
|
+
if (resultFile) {
|
|
85
|
+
const { writeFile } = await import('node:fs/promises');
|
|
86
|
+
await writeFile(resultFile, JSON.stringify({
|
|
87
|
+
success: result.bundleErrors.length === 0,
|
|
88
|
+
providerDir: result.providerDir,
|
|
89
|
+
unitCount: result.bundled.length,
|
|
90
|
+
totalSizeBytes: totalSize,
|
|
91
|
+
errors: result.bundleErrors,
|
|
92
|
+
manifest: result.manifest,
|
|
93
|
+
}, null, 2), 'utf-8');
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
});
|
|
@@ -8,7 +8,7 @@ const FEATURE_DEFAULTS = {
|
|
|
8
8
|
workflow: 'auth',
|
|
9
9
|
};
|
|
10
10
|
async function enableFeature(feature, logger, config, data) {
|
|
11
|
-
const noAuth = data?.
|
|
11
|
+
const noAuth = data?.noAuth ?? false;
|
|
12
12
|
const configPath = join(config.configDir, 'pikku.config.json');
|
|
13
13
|
const raw = await readFile(configPath, 'utf-8');
|
|
14
14
|
const json = JSON.parse(raw);
|
|
@@ -11,6 +11,7 @@ export declare const pikkuNewAddon: import("#pikku").PikkuFunctionConfig<{
|
|
|
11
11
|
test?: boolean;
|
|
12
12
|
openapi?: string;
|
|
13
13
|
mcp?: boolean;
|
|
14
|
+
camelCase?: boolean;
|
|
14
15
|
}, void, "session" | "rpc", import("#pikku").PikkuFunctionSessionless<{
|
|
15
16
|
name: string;
|
|
16
17
|
displayName?: string;
|
|
@@ -24,6 +25,7 @@ export declare const pikkuNewAddon: import("#pikku").PikkuFunctionConfig<{
|
|
|
24
25
|
test?: boolean;
|
|
25
26
|
openapi?: string;
|
|
26
27
|
mcp?: boolean;
|
|
28
|
+
camelCase?: boolean;
|
|
27
29
|
}, void, "session" | "rpc", import("#pikku").Services> | import("#pikku").PikkuFunction<{
|
|
28
30
|
name: string;
|
|
29
31
|
displayName?: string;
|
|
@@ -37,4 +39,5 @@ export declare const pikkuNewAddon: import("#pikku").PikkuFunctionConfig<{
|
|
|
37
39
|
test?: boolean;
|
|
38
40
|
openapi?: string;
|
|
39
41
|
mcp?: boolean;
|
|
42
|
+
camelCase?: boolean;
|
|
40
43
|
}, void, "session" | "rpc", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -5,7 +5,7 @@ import { createEmptyManifest, saveManifest, } from '../../utils/contract-version
|
|
|
5
5
|
import { pikkuSessionlessFunc } from '#pikku';
|
|
6
6
|
import { parseOpenAPISpec, computeContractHash, generateAddonFromOpenAPI, } from '@pikku/openapi-parser';
|
|
7
7
|
function toCamelCase(str) {
|
|
8
|
-
return str.replace(/-([a-
|
|
8
|
+
return str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
9
9
|
}
|
|
10
10
|
function toPascalCase(str) {
|
|
11
11
|
const camel = toCamelCase(str);
|
|
@@ -14,6 +14,69 @@ function toPascalCase(str) {
|
|
|
14
14
|
function toScreamingSnake(str) {
|
|
15
15
|
return str.replace(/-/g, '_').toUpperCase();
|
|
16
16
|
}
|
|
17
|
+
const TLD_SEGMENTS = new Set([
|
|
18
|
+
'com',
|
|
19
|
+
'io',
|
|
20
|
+
'org',
|
|
21
|
+
'net',
|
|
22
|
+
'co',
|
|
23
|
+
'dev',
|
|
24
|
+
'app',
|
|
25
|
+
'us',
|
|
26
|
+
'uk',
|
|
27
|
+
'eu',
|
|
28
|
+
'de',
|
|
29
|
+
'fr',
|
|
30
|
+
'nl',
|
|
31
|
+
'ch',
|
|
32
|
+
'ca',
|
|
33
|
+
'au',
|
|
34
|
+
'gov',
|
|
35
|
+
'edu',
|
|
36
|
+
'local',
|
|
37
|
+
'cloud',
|
|
38
|
+
'ai',
|
|
39
|
+
'fm',
|
|
40
|
+
'tv',
|
|
41
|
+
'me',
|
|
42
|
+
'cc',
|
|
43
|
+
'info',
|
|
44
|
+
'biz',
|
|
45
|
+
'xyz',
|
|
46
|
+
'tech',
|
|
47
|
+
'space',
|
|
48
|
+
'online',
|
|
49
|
+
'site',
|
|
50
|
+
'store',
|
|
51
|
+
'ac',
|
|
52
|
+
'int',
|
|
53
|
+
'mil',
|
|
54
|
+
'ninja',
|
|
55
|
+
'guru',
|
|
56
|
+
]);
|
|
57
|
+
function sanitizeAddonName(raw) {
|
|
58
|
+
const dotParts = raw.toLowerCase().split('.');
|
|
59
|
+
const kept = [];
|
|
60
|
+
for (const part of dotParts) {
|
|
61
|
+
const clean = part.replace(/^-|-$/g, '');
|
|
62
|
+
if (TLD_SEGMENTS.has(clean))
|
|
63
|
+
continue;
|
|
64
|
+
const hyphenIdx = part.indexOf('-');
|
|
65
|
+
if (hyphenIdx > 0 && TLD_SEGMENTS.has(part.slice(0, hyphenIdx))) {
|
|
66
|
+
kept.push(part.slice(hyphenIdx + 1));
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
kept.push(part);
|
|
70
|
+
}
|
|
71
|
+
let name = kept
|
|
72
|
+
.join('-')
|
|
73
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
74
|
+
.replace(/-+/g, '-')
|
|
75
|
+
.replace(/^-|-$/g, '');
|
|
76
|
+
if (name && /^[0-9]/.test(name))
|
|
77
|
+
name = `x${name}`;
|
|
78
|
+
return name || raw;
|
|
79
|
+
}
|
|
17
80
|
function getAddonFiles(vars, flags) {
|
|
18
81
|
const { name, camelName, pascalName, screamingName, displayName, description, category, } = vars;
|
|
19
82
|
const files = {};
|
|
@@ -700,7 +763,8 @@ async function writeFiles(baseDir, files) {
|
|
|
700
763
|
return written;
|
|
701
764
|
}
|
|
702
765
|
export const pikkuNewAddon = pikkuSessionlessFunc({
|
|
703
|
-
func: async ({ logger, config }, { name, displayName, description, category = 'General', dir, secret = false, variable = false, oauth = false, credential, test = true, openapi, mcp = false, }) => {
|
|
766
|
+
func: async ({ logger, config }, { name, displayName, description, category = 'General', dir, secret = false, variable = false, oauth = false, credential, test = true, openapi, mcp = false, camelCase = false, }) => {
|
|
767
|
+
name = sanitizeAddonName(name);
|
|
704
768
|
if (!/^[a-z][a-z0-9_-]*$/.test(name)) {
|
|
705
769
|
logger.error(`Invalid addon name "${name}": must start with a lowercase letter and contain only lowercase alphanumerics, hyphens, and underscores`);
|
|
706
770
|
process.exit(1);
|
|
@@ -747,6 +811,7 @@ export const pikkuNewAddon = pikkuSessionlessFunc({
|
|
|
747
811
|
secret: (secret || effectiveOAuth) && !credentialType,
|
|
748
812
|
credential: credentialType,
|
|
749
813
|
mcp,
|
|
814
|
+
camelCase,
|
|
750
815
|
});
|
|
751
816
|
Object.assign(addonFiles, openapiFiles);
|
|
752
817
|
// Inject openapi metadata into pikku.config.json
|
|
@@ -757,6 +822,7 @@ export const pikkuNewAddon = pikkuSessionlessFunc({
|
|
|
757
822
|
config.addon.openapi = {
|
|
758
823
|
version: spec.info.version,
|
|
759
824
|
hash: computeContractHash(spec),
|
|
825
|
+
...(camelCase ? { camelCase: true } : {}),
|
|
760
826
|
};
|
|
761
827
|
addonFiles['pikku.config.json'] = JSON.stringify(config, null, 2);
|
|
762
828
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { join, dirname } from 'node:path';
|
|
1
2
|
import { pikkuSessionlessFunc } from '#pikku';
|
|
2
3
|
import { getFileImportRelativePath } from '../../utils/file-import-path.js';
|
|
3
4
|
import { writeFileInDir } from '../../utils/file-writer.js';
|
|
@@ -13,26 +14,35 @@ export const pikkuBootstrap = pikkuSessionlessFunc({
|
|
|
13
14
|
const wireAddonFileImports = Array.from(stateBeforeBootstrap.rpc?.wireAddonFiles ?? []).map((to) => `import '${getFileImportRelativePath(config.bootstrapFile, to, config.packageMappings)}'`);
|
|
14
15
|
const localImports = allImports.map((to) => `import '${getFileImportRelativePath(config.bootstrapFile, to, config.packageMappings)}'`);
|
|
15
16
|
const addonImports = addonBootstraps.map((packagePath) => `import '${packagePath}'`);
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
17
|
+
const outDir = dirname(config.bootstrapFile);
|
|
18
|
+
const metaServiceFile = join(outDir, 'pikku-meta-service.gen.ts');
|
|
19
|
+
const escapedOutDir = outDir.replace(/\\/g, '/').replace(/'/g, "\\'");
|
|
20
|
+
const metaServiceContent = [
|
|
21
|
+
`import { LocalMetaService } from '@pikku/core/services/local-meta'`,
|
|
22
|
+
``,
|
|
23
|
+
`export class PikkuMetaService extends LocalMetaService {`,
|
|
24
|
+
` constructor() {`,
|
|
25
|
+
` super('${escapedOutDir}')`,
|
|
26
|
+
` }`,
|
|
27
|
+
`}`,
|
|
28
|
+
``,
|
|
29
|
+
].join('\n');
|
|
30
|
+
await writeFileInDir(logger, metaServiceFile, metaServiceContent);
|
|
31
|
+
const allBootstrapImports = [
|
|
32
|
+
...localImports,
|
|
33
|
+
...wireAddonFileImports,
|
|
34
|
+
...addonImports,
|
|
35
|
+
]
|
|
36
|
+
.sort((a, b) => {
|
|
37
|
+
const aMeta = a.includes('meta');
|
|
38
|
+
const bMeta = b.includes('meta');
|
|
39
|
+
if (aMeta && !bMeta)
|
|
40
|
+
return -1;
|
|
41
|
+
if (!aMeta && bMeta)
|
|
42
|
+
return 1;
|
|
43
|
+
return 0;
|
|
44
|
+
})
|
|
45
|
+
.join('\n');
|
|
36
46
|
await writeFileInDir(logger, config.bootstrapFile, allBootstrapImports);
|
|
37
47
|
},
|
|
38
48
|
});
|
|
@@ -35,10 +35,14 @@ export const pikkuNext = pikkuSessionlessFunc({
|
|
|
35
35
|
if (!pikkuConfigFactory || !singletonServicesFactory) {
|
|
36
36
|
throw new Error('Required types not found');
|
|
37
37
|
}
|
|
38
|
-
const
|
|
39
|
-
const
|
|
38
|
+
const configAlias = pikkuConfigFactory.variable === 'createConfig' ? '' : ' as createConfig';
|
|
39
|
+
const servicesAlias = singletonServicesFactory.variable === 'createSingletonServices'
|
|
40
|
+
? ''
|
|
41
|
+
: ' as createSingletonServices';
|
|
42
|
+
const pikkuConfigImport = `import { ${pikkuConfigFactory.variable}${configAlias} } from '${getFileImportRelativePath(nextBackendFile, pikkuConfigFactory.file, packageMappings)}'`;
|
|
43
|
+
const singletonServicesImport = `import { ${singletonServicesFactory.variable}${servicesAlias} } from '${getFileImportRelativePath(nextBackendFile, singletonServicesFactory.file, packageMappings)}'`;
|
|
40
44
|
const wireServicesImport = wireServicesFactory
|
|
41
|
-
? `import { ${wireServicesFactory.variable} as createWireServices } from '${getFileImportRelativePath(nextBackendFile, wireServicesFactory.file, packageMappings)}'`
|
|
45
|
+
? `import { ${wireServicesFactory.variable}${wireServicesFactory.variable === 'createWireServices' ? '' : ' as createWireServices'} } from '${getFileImportRelativePath(nextBackendFile, wireServicesFactory.file, packageMappings)}'`
|
|
42
46
|
: '';
|
|
43
47
|
const bootstrapPath = getFileImportRelativePath(nextBackendFile, config.bootstrapFile, packageMappings);
|
|
44
48
|
const routesMapDeclarationPath = getFileImportRelativePath(nextBackendFile, httpMapDeclarationFile, packageMappings);
|