@portel/photon 1.11.0 → 1.13.0
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/README.md +81 -72
- package/dist/auto-ui/beam/photon-management.d.ts.map +1 -1
- package/dist/auto-ui/beam/photon-management.js +5 -0
- package/dist/auto-ui/beam/photon-management.js.map +1 -1
- package/dist/auto-ui/beam/routes/api-browse.d.ts +1 -2
- package/dist/auto-ui/beam/routes/api-browse.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-browse.js +140 -191
- package/dist/auto-ui/beam/routes/api-browse.js.map +1 -1
- package/dist/auto-ui/beam/routes/api-config.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-config.js +44 -1
- package/dist/auto-ui/beam/routes/api-config.js.map +1 -1
- package/dist/auto-ui/beam.d.ts.map +1 -1
- package/dist/auto-ui/beam.js +994 -34
- package/dist/auto-ui/beam.js.map +1 -1
- package/dist/auto-ui/frontend/index.html +83 -60
- package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
- package/dist/auto-ui/streamable-http-transport.js +53 -12
- package/dist/auto-ui/streamable-http-transport.js.map +1 -1
- package/dist/auto-ui/types.d.ts +28 -1
- package/dist/auto-ui/types.d.ts.map +1 -1
- package/dist/auto-ui/types.js +23 -0
- package/dist/auto-ui/types.js.map +1 -1
- package/dist/beam.bundle.js +2894 -329
- package/dist/beam.bundle.js.map +4 -4
- package/dist/cli/commands/build.d.ts +3 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +339 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/package-app.d.ts.map +1 -1
- package/dist/cli/commands/package-app.js +116 -35
- package/dist/cli/commands/package-app.js.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +2 -0
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/context-store.d.ts +5 -0
- package/dist/context-store.d.ts.map +1 -1
- package/dist/context-store.js +9 -0
- package/dist/context-store.js.map +1 -1
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +81 -0
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/protocol.d.ts +3 -1
- package/dist/daemon/protocol.d.ts.map +1 -1
- package/dist/daemon/protocol.js +1 -1
- package/dist/daemon/protocol.js.map +1 -1
- package/dist/daemon/server.js +513 -18
- package/dist/daemon/server.js.map +1 -1
- package/dist/embedded-runtime.d.ts +38 -0
- package/dist/embedded-runtime.d.ts.map +1 -0
- package/dist/embedded-runtime.js +326 -0
- package/dist/embedded-runtime.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +38 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +455 -15
- package/dist/loader.js.map +1 -1
- package/dist/photon-cli-runner.d.ts +22 -0
- package/dist/photon-cli-runner.d.ts.map +1 -1
- package/dist/photon-cli-runner.js +244 -12
- package/dist/photon-cli-runner.js.map +1 -1
- package/dist/photon-doc-extractor.d.ts +6 -0
- package/dist/photon-doc-extractor.d.ts.map +1 -1
- package/dist/photon-doc-extractor.js +22 -0
- package/dist/photon-doc-extractor.js.map +1 -1
- package/dist/photons/tunnel.photon.d.ts +5 -9
- package/dist/photons/tunnel.photon.d.ts.map +1 -1
- package/dist/photons/tunnel.photon.js +36 -96
- package/dist/photons/tunnel.photon.js.map +1 -1
- package/dist/photons/tunnel.photon.ts +40 -112
- package/dist/server.d.ts +30 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +155 -10
- package/dist/server.js.map +1 -1
- package/dist/test-runner.d.ts +13 -1
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +529 -122
- package/dist/test-runner.js.map +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +10 -2
- package/dist/version.js.map +1 -1
- package/package.json +23 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuGpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QA8TpD"}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
import ora from 'ora';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { printError } from '../../cli-formatter.js';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { SchemaExtractor } from '@portel/photon-core';
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
/**
|
|
11
|
+
* Recursively resolve all @photon dependencies starting from a root source file.
|
|
12
|
+
* Returns a flat list of unique dependencies (by file path).
|
|
13
|
+
*/
|
|
14
|
+
function resolvePhotonDeps(sourceCode, sourceFilePath, baseDir, visited = new Set()) {
|
|
15
|
+
const extractor = new SchemaExtractor();
|
|
16
|
+
const deps = extractor.extractPhotonDependencies(sourceCode);
|
|
17
|
+
const result = [];
|
|
18
|
+
for (const dep of deps) {
|
|
19
|
+
// Resolve the file path based on source type
|
|
20
|
+
let resolvedPath = null;
|
|
21
|
+
if (dep.sourceType === 'local') {
|
|
22
|
+
// Relative or absolute path
|
|
23
|
+
if (dep.source.startsWith('./') || dep.source.startsWith('../')) {
|
|
24
|
+
resolvedPath = path.resolve(path.dirname(sourceFilePath), dep.source);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
resolvedPath = path.resolve(dep.source);
|
|
28
|
+
}
|
|
29
|
+
// Ensure .photon.ts extension
|
|
30
|
+
if (!resolvedPath.endsWith('.photon.ts') && !resolvedPath.endsWith('.ts')) {
|
|
31
|
+
resolvedPath += '.photon.ts';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else if (dep.sourceType === 'marketplace') {
|
|
35
|
+
// Search common locations for marketplace photons
|
|
36
|
+
const slug = dep.source
|
|
37
|
+
.replace(/\.photon\.ts$/, '')
|
|
38
|
+
.replace(/\.photon$/, '')
|
|
39
|
+
.replace(/\.ts$/, '');
|
|
40
|
+
const fileName = `${slug}.photon.ts`;
|
|
41
|
+
const candidates = [
|
|
42
|
+
path.resolve(path.dirname(sourceFilePath), fileName),
|
|
43
|
+
path.resolve(path.dirname(sourceFilePath), 'photons', fileName),
|
|
44
|
+
path.join(baseDir, fileName),
|
|
45
|
+
path.join(baseDir, 'photons', fileName),
|
|
46
|
+
path.join(baseDir, 'marketplace', fileName),
|
|
47
|
+
];
|
|
48
|
+
for (const candidate of candidates) {
|
|
49
|
+
if (fs.existsSync(candidate)) {
|
|
50
|
+
resolvedPath = candidate;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!resolvedPath || !fs.existsSync(resolvedPath)) {
|
|
56
|
+
// Can't resolve — will be warned about separately
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
resolvedPath = fs.realpathSync(resolvedPath);
|
|
60
|
+
if (visited.has(resolvedPath)) {
|
|
61
|
+
continue; // Already processed (circular dep protection)
|
|
62
|
+
}
|
|
63
|
+
visited.add(resolvedPath);
|
|
64
|
+
const depSource = fs.readFileSync(resolvedPath, 'utf-8');
|
|
65
|
+
result.push({
|
|
66
|
+
name: dep.name,
|
|
67
|
+
source: dep.source,
|
|
68
|
+
filePath: resolvedPath,
|
|
69
|
+
sourceCode: depSource,
|
|
70
|
+
});
|
|
71
|
+
// Recurse into transitive dependencies
|
|
72
|
+
const transitive = resolvePhotonDeps(depSource, resolvedPath, baseDir, visited);
|
|
73
|
+
result.push(...transitive);
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
export function registerBuildCommand(program) {
|
|
78
|
+
program
|
|
79
|
+
.command('build')
|
|
80
|
+
.description('Compile a photon into a standalone executable binary')
|
|
81
|
+
.argument('<file>', 'Path to the .photon.ts file')
|
|
82
|
+
.option('-o, --outfile <name>', 'Name of the output binary')
|
|
83
|
+
.option('-t, --target <target>', 'Bun compilation target (e.g. bun-linux-x64, bun-darwin-arm64, bun-windows-x64)')
|
|
84
|
+
.action(async (file, options) => {
|
|
85
|
+
const spinner = ora(`Preparing standalone build for ${file}...`).start();
|
|
86
|
+
const workingDir = process.cwd();
|
|
87
|
+
const photonPath = path.resolve(workingDir, file);
|
|
88
|
+
if (!fs.existsSync(photonPath)) {
|
|
89
|
+
spinner.fail(`File not found: ${photonPath}`);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
// Check that bun is available
|
|
93
|
+
try {
|
|
94
|
+
const { execSync } = await import('child_process');
|
|
95
|
+
execSync('bun --version', { stdio: 'ignore' });
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
spinner.fail('Bun is required for compilation. Install it: https://bun.sh');
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
// Read the source code to embed in the binary
|
|
102
|
+
const sourceCode = fs.readFileSync(photonPath, 'utf-8');
|
|
103
|
+
// Resolve @photon dependencies recursively
|
|
104
|
+
const baseDir = path.join(process.env.HOME || '~', '.photon');
|
|
105
|
+
const photonDeps = resolvePhotonDeps(sourceCode, photonPath, baseDir);
|
|
106
|
+
if (photonDeps.length > 0) {
|
|
107
|
+
spinner.info(`Bundling ${photonDeps.length} @photon dependenc${photonDeps.length === 1 ? 'y' : 'ies'}:`);
|
|
108
|
+
for (const dep of photonDeps) {
|
|
109
|
+
console.log(chalk.cyan(` 📦 ${dep.name} → ${path.basename(dep.filePath)}`));
|
|
110
|
+
}
|
|
111
|
+
console.log();
|
|
112
|
+
spinner.start('Continuing build...');
|
|
113
|
+
}
|
|
114
|
+
// Detect unbundleable dependencies and warn
|
|
115
|
+
const warnings = [];
|
|
116
|
+
// Check all sources (main + deps) for @mcp and @cli tags
|
|
117
|
+
const allSources = [sourceCode, ...photonDeps.map((d) => d.sourceCode)];
|
|
118
|
+
for (const src of allSources) {
|
|
119
|
+
for (const match of src.matchAll(/@mcp\s+(\S+)/g)) {
|
|
120
|
+
warnings.push(`@mcp dependency "${match[1]}" — external MCP server, must be installed separately`);
|
|
121
|
+
}
|
|
122
|
+
for (const match of src.matchAll(/@cli\s+(\S+)/g)) {
|
|
123
|
+
warnings.push(`@cli dependency "${match[1]}" — external CLI tool, must be available on target system`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Check for unresolved @photon deps (ones we couldn't find on disk)
|
|
127
|
+
const extractor = new SchemaExtractor();
|
|
128
|
+
const declaredDeps = extractor.extractPhotonDependencies(sourceCode);
|
|
129
|
+
for (const dep of declaredDeps) {
|
|
130
|
+
const resolved = photonDeps.find((d) => d.name === dep.name);
|
|
131
|
+
if (!resolved) {
|
|
132
|
+
warnings.push(`@photon dependency "${dep.name}" (from ${dep.source}) — could not be resolved, must be available at runtime`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (warnings.length > 0) {
|
|
136
|
+
spinner.warn('External dependencies detected (not bundled):');
|
|
137
|
+
for (const w of warnings) {
|
|
138
|
+
console.log(chalk.yellow(` ⚠ ${w}`));
|
|
139
|
+
}
|
|
140
|
+
console.log();
|
|
141
|
+
spinner.start('Continuing build...');
|
|
142
|
+
}
|
|
143
|
+
// Generate a unique temporary entrypoint file
|
|
144
|
+
const tempEntrypointName = `.photon-build-${Date.now()}.ts`;
|
|
145
|
+
const tempEntrypointPath = path.join(workingDir, tempEntrypointName);
|
|
146
|
+
// Determine outfile name
|
|
147
|
+
let outfile = options.outfile;
|
|
148
|
+
if (!outfile) {
|
|
149
|
+
const basename = path.basename(file, '.photon.ts');
|
|
150
|
+
outfile = basename.endsWith('.photon.js') ? path.basename(file, '.photon.js') : basename;
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
// Relative import path for the photon module
|
|
154
|
+
let relativePhotonPath = path.relative(workingDir, photonPath);
|
|
155
|
+
if (!relativePhotonPath.startsWith('.')) {
|
|
156
|
+
relativePhotonPath = `./${relativePhotonPath}`;
|
|
157
|
+
}
|
|
158
|
+
// Escape source for embedding as a template literal
|
|
159
|
+
const escapeForTemplateLiteral = (src) => src.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$');
|
|
160
|
+
const escapedSource = escapeForTemplateLiteral(sourceCode);
|
|
161
|
+
// Resolve the photon runtime package path for the entrypoint import.
|
|
162
|
+
const photonPkgDir = path.resolve(__dirname, '..', '..'); // dist/ -> package root
|
|
163
|
+
let photonImportPath = path.relative(workingDir, path.join(photonPkgDir, 'index.js'));
|
|
164
|
+
if (!photonImportPath.startsWith('.')) {
|
|
165
|
+
photonImportPath = `./${photonImportPath}`;
|
|
166
|
+
}
|
|
167
|
+
// Generate import statements for each @photon dependency
|
|
168
|
+
const depImports = [];
|
|
169
|
+
const depMapEntries = [];
|
|
170
|
+
for (let i = 0; i < photonDeps.length; i++) {
|
|
171
|
+
const dep = photonDeps[i];
|
|
172
|
+
const varName = `__dep${i}`;
|
|
173
|
+
let depImportPath = path.relative(workingDir, dep.filePath);
|
|
174
|
+
if (!depImportPath.startsWith('.')) {
|
|
175
|
+
depImportPath = `./${depImportPath}`;
|
|
176
|
+
}
|
|
177
|
+
depImports.push(`import * as ${varName} from '${depImportPath}';`);
|
|
178
|
+
const escapedDepSource = escapeForTemplateLiteral(dep.sourceCode);
|
|
179
|
+
depMapEntries.push(` deps.set('${dep.name}', { module: ${varName}, source: \`${escapedDepSource}\`, filePath: ${JSON.stringify(dep.filePath)} });`);
|
|
180
|
+
// Also register by source name for fallback matching
|
|
181
|
+
if (dep.source !== dep.name) {
|
|
182
|
+
depMapEntries.push(` deps.set('${dep.source}', { module: ${varName}, source: \`${escapedDepSource}\`, filePath: ${JSON.stringify(dep.filePath)} });`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const depImportsBlock = depImports.length > 0 ? depImports.join('\n') + '\n' : '';
|
|
186
|
+
const depMapBlock = depMapEntries.length > 0
|
|
187
|
+
? `\nfunction buildDependencyMap() {\n const deps = new Map();\n${depMapEntries.join('\n')}\n return deps;\n}\n`
|
|
188
|
+
: '';
|
|
189
|
+
const depMapArg = depMapEntries.length > 0 ? `\n preloadedDependencies: buildDependencyMap(),` : '';
|
|
190
|
+
// Build a symlink routing map for the entrypoint:
|
|
191
|
+
// When invoked via a symlink named after a bundled dep, serve that dep instead.
|
|
192
|
+
const symlinkEntries = [];
|
|
193
|
+
for (let i = 0; i < photonDeps.length; i++) {
|
|
194
|
+
const dep = photonDeps[i];
|
|
195
|
+
const varName = `__dep${i}`;
|
|
196
|
+
const escapedDepSource = escapeForTemplateLiteral(dep.sourceCode);
|
|
197
|
+
// Extract the photon name from the file (e.g., "whatsapp" from "whatsapp.photon.ts")
|
|
198
|
+
const depPhotonName = path.basename(dep.filePath, '.photon.ts').replace('.photon', '');
|
|
199
|
+
symlinkEntries.push(` '${depPhotonName}': { module: ${varName}, source: \`${escapedDepSource}\`, filePath: ${JSON.stringify(dep.filePath)} },`);
|
|
200
|
+
// Also map by the dependency variable name if different
|
|
201
|
+
if (dep.name !== depPhotonName) {
|
|
202
|
+
symlinkEntries.push(` '${dep.name}': { module: ${varName}, source: \`${escapedDepSource}\`, filePath: ${JSON.stringify(dep.filePath)} },`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const symlinkMapBlock = symlinkEntries.length > 0
|
|
206
|
+
? `\nconst BUNDLED_PHOTONS: Record<string, { module: any; source: string; filePath: string }> = {\n${symlinkEntries.join('\n')}\n};\n`
|
|
207
|
+
: '\nconst BUNDLED_PHOTONS: Record<string, { module: any; source: string; filePath: string }> = {};\n';
|
|
208
|
+
// Symlink routing logic: detect which photon to serve based on executable name
|
|
209
|
+
const symlinkRoutingCode = `
|
|
210
|
+
// Detect if invoked via a symlink to serve a bundled dependency.
|
|
211
|
+
// Bun compiled binaries don't preserve argv[0] for symlinks, but
|
|
212
|
+
// $_ (set by shells) contains the actual invocation path including symlink name.
|
|
213
|
+
const __path = await import('path');
|
|
214
|
+
const invokedAs = __path.default.basename(process.env._ || process.execPath);
|
|
215
|
+
const bundled = BUNDLED_PHOTONS[invokedAs];
|
|
216
|
+
const activeModule = bundled ? bundled.module : photonModule;
|
|
217
|
+
const activeSource = bundled ? bundled.source : EMBEDDED_SOURCE;
|
|
218
|
+
const activeFilePath = bundled ? bundled.filePath : ${JSON.stringify(photonPath)};
|
|
219
|
+
`;
|
|
220
|
+
const entrypointCode = `import { PhotonServer, EmbeddedRuntime } from '${photonImportPath}';
|
|
221
|
+
import * as photonModule from '${relativePhotonPath}';
|
|
222
|
+
${depImportsBlock}
|
|
223
|
+
const EMBEDDED_SOURCE = \`${escapedSource}\`;
|
|
224
|
+
${depMapBlock}${symlinkMapBlock}
|
|
225
|
+
async function main() {
|
|
226
|
+
const args = process.argv.slice(2);
|
|
227
|
+
const command = args[0] || 'mcp';
|
|
228
|
+
|
|
229
|
+
let port: number | undefined;
|
|
230
|
+
if (command === 'sse') {
|
|
231
|
+
port = args[1] ? parseInt(args[1], 10) : undefined;
|
|
232
|
+
}
|
|
233
|
+
${symlinkRoutingCode}
|
|
234
|
+
// Start embedded runtime (in-process broker + scheduler)
|
|
235
|
+
const runtime = new EmbeddedRuntime();
|
|
236
|
+
runtime.start();
|
|
237
|
+
|
|
238
|
+
const server = new PhotonServer({
|
|
239
|
+
filePath: activeFilePath,
|
|
240
|
+
transport: command === 'sse' ? 'sse' : 'stdio',
|
|
241
|
+
port,
|
|
242
|
+
preloadedModule: activeModule,
|
|
243
|
+
embeddedSource: activeSource,${depMapArg}
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
await server.start();
|
|
247
|
+
|
|
248
|
+
// Register @scheduled/@cron jobs from the loaded photon
|
|
249
|
+
if (server.getLoadedPhoton()) {
|
|
250
|
+
runtime.registerScheduledJobs(server.getLoadedPhoton()!, server.getLoader());
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
main().catch(err => {
|
|
255
|
+
console.error('Fatal error:', err.message || err);
|
|
256
|
+
process.exit(1);
|
|
257
|
+
});
|
|
258
|
+
`;
|
|
259
|
+
fs.writeFileSync(tempEntrypointPath, entrypointCode, 'utf-8');
|
|
260
|
+
spinner.text = 'Compiling executable with Bun...';
|
|
261
|
+
// Prepare bun build arguments
|
|
262
|
+
const buildArgs = ['build', tempEntrypointPath, '--compile', '--outfile', outfile];
|
|
263
|
+
if (options.target) {
|
|
264
|
+
buildArgs.push('--target', options.target);
|
|
265
|
+
}
|
|
266
|
+
const buildProcess = spawn('bun', buildArgs, {
|
|
267
|
+
cwd: workingDir,
|
|
268
|
+
stdio: 'pipe',
|
|
269
|
+
});
|
|
270
|
+
let stdoutData = '';
|
|
271
|
+
let stderrData = '';
|
|
272
|
+
buildProcess.stdout.on('data', (data) => {
|
|
273
|
+
stdoutData += data.toString();
|
|
274
|
+
});
|
|
275
|
+
buildProcess.stderr.on('data', (data) => {
|
|
276
|
+
stderrData += data.toString();
|
|
277
|
+
});
|
|
278
|
+
await new Promise((resolve, reject) => {
|
|
279
|
+
buildProcess.on('close', (code) => {
|
|
280
|
+
if (code === 0) {
|
|
281
|
+
resolve();
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
reject(new Error(`Bun compilation failed with exit code ${code}\n\n${stderrData || stdoutData}`));
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
buildProcess.on('error', reject);
|
|
288
|
+
});
|
|
289
|
+
// Get file size for display
|
|
290
|
+
const stat = fs.statSync(outfile);
|
|
291
|
+
const sizeMB = (stat.size / 1024 / 1024).toFixed(1);
|
|
292
|
+
spinner.succeed(`Compiled: ${chalk.green(chalk.bold(outfile))} (${sizeMB} MB)`);
|
|
293
|
+
// Create symlinks for bundled @photon dependencies
|
|
294
|
+
if (photonDeps.length > 0) {
|
|
295
|
+
const outDir = path.dirname(path.resolve(outfile));
|
|
296
|
+
const outBase = path.resolve(outfile);
|
|
297
|
+
const createdLinks = [];
|
|
298
|
+
const seenNames = new Set();
|
|
299
|
+
for (const dep of photonDeps) {
|
|
300
|
+
const depName = path.basename(dep.filePath, '.photon.ts').replace('.photon', '');
|
|
301
|
+
if (seenNames.has(depName) || depName === path.basename(outfile))
|
|
302
|
+
continue;
|
|
303
|
+
seenNames.add(depName);
|
|
304
|
+
const linkPath = path.join(outDir, depName);
|
|
305
|
+
try {
|
|
306
|
+
if (fs.existsSync(linkPath))
|
|
307
|
+
fs.unlinkSync(linkPath);
|
|
308
|
+
fs.symlinkSync(outBase, linkPath);
|
|
309
|
+
createdLinks.push(depName);
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
// Symlink creation may fail on some filesystems — non-fatal
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (createdLinks.length > 0) {
|
|
316
|
+
console.log(`\n${chalk.dim('Symlinks (each serves the bundled photon as its own MCP server):')}`);
|
|
317
|
+
for (const name of createdLinks) {
|
|
318
|
+
console.log(` ${chalk.cyan(name)} → ${outfile}`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
console.log(`\nUsage:`);
|
|
323
|
+
console.log(` ./${outfile} MCP server (stdio)`);
|
|
324
|
+
console.log(` ./${outfile} sse MCP server (HTTP/SSE)`);
|
|
325
|
+
}
|
|
326
|
+
catch (err) {
|
|
327
|
+
spinner.fail('Build failed');
|
|
328
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
329
|
+
process.exit(1);
|
|
330
|
+
}
|
|
331
|
+
finally {
|
|
332
|
+
// Clean up the temporary entrypoint file
|
|
333
|
+
if (fs.existsSync(tempEntrypointPath)) {
|
|
334
|
+
fs.unlinkSync(tempEntrypointPath);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-app.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/package-app.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"package-app.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/package-app.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuOpC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiGhE"}
|
|
@@ -14,44 +14,56 @@ function toClassName(name) {
|
|
|
14
14
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
15
15
|
.join('');
|
|
16
16
|
}
|
|
17
|
-
function generateBashLauncherScript(name,
|
|
17
|
+
function generateBashLauncherScript(name, version, startPort, openCmd) {
|
|
18
18
|
const endPort = startPort + 9;
|
|
19
19
|
return `#!/usr/bin/env bash
|
|
20
|
-
# Launcher for ${name} — auto-starts beam and opens PWA
|
|
20
|
+
# Launcher for ${name} — auto-starts beam and opens as PWA
|
|
21
21
|
set -e
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
PHOTON="${name}"
|
|
24
|
+
VERSION="${version}"
|
|
24
25
|
START_PORT=${startPort}
|
|
25
26
|
END_PORT=${endPort}
|
|
26
27
|
OPEN_CMD="${openCmd}"
|
|
27
28
|
|
|
28
|
-
#
|
|
29
|
+
# Detect package runner: bunx > pnpx > npx
|
|
30
|
+
if command -v bunx &>/dev/null; then
|
|
31
|
+
RUNNER="bunx @portel/photon@$VERSION"
|
|
32
|
+
elif command -v pnpx &>/dev/null; then
|
|
33
|
+
RUNNER="pnpx @portel/photon@$VERSION"
|
|
34
|
+
elif command -v npx &>/dev/null; then
|
|
35
|
+
RUNNER="npx -y @portel/photon@$VERSION"
|
|
36
|
+
else
|
|
37
|
+
echo "Error: no package runner found (npx, pnpx, or bunx required)"
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Scan ports for an existing beam already serving this photon
|
|
29
42
|
for port in $(seq $START_PORT $END_PORT); do
|
|
30
43
|
RESP=$(curl -s --max-time 2 "http://localhost:\${port}/api/diagnostics" 2>/dev/null || true)
|
|
31
44
|
if [ -n "$RESP" ]; then
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
# Check if this beam has our photon loaded
|
|
46
|
+
echo "$RESP" | grep -q "\\"name\\":\\"$PHOTON\\"" 2>/dev/null && {
|
|
47
|
+
# Beam already running with this photon — skip browser open (client likely connected)
|
|
35
48
|
exit 0
|
|
36
|
-
|
|
49
|
+
}
|
|
37
50
|
fi
|
|
38
51
|
done
|
|
39
52
|
|
|
40
|
-
# No existing beam found — start one
|
|
41
|
-
|
|
53
|
+
# No existing beam found — start one (--no-open: we handle browser launch ourselves)
|
|
54
|
+
$RUNNER $PHOTON --no-open --port=$START_PORT &
|
|
42
55
|
BEAM_PID=$!
|
|
43
56
|
|
|
44
|
-
# Poll until beam is ready (up to 30s)
|
|
57
|
+
# Poll until beam is ready (up to 30s), then open browser
|
|
45
58
|
WAITED=0
|
|
46
59
|
while [ $WAITED -lt 30 ]; do
|
|
47
60
|
for port in $(seq $START_PORT $END_PORT); do
|
|
48
61
|
RESP=$(curl -s --max-time 1 "http://localhost:\${port}/api/diagnostics" 2>/dev/null || true)
|
|
49
62
|
if [ -n "$RESP" ]; then
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
$OPEN_CMD "http://localhost:\${port}"
|
|
63
|
+
echo "$RESP" | grep -q "\\"name\\":\\"$PHOTON\\"" 2>/dev/null && {
|
|
64
|
+
$OPEN_CMD "http://localhost:\${port}/#$PHOTON?focus=1"
|
|
53
65
|
exit 0
|
|
54
|
-
|
|
66
|
+
}
|
|
55
67
|
fi
|
|
56
68
|
done
|
|
57
69
|
sleep 1
|
|
@@ -84,31 +96,40 @@ function generateInfoPlist(name, className) {
|
|
|
84
96
|
</dict>
|
|
85
97
|
</plist>`;
|
|
86
98
|
}
|
|
87
|
-
function generateWindowsBat(name,
|
|
99
|
+
function generateWindowsBat(name, version, startPort) {
|
|
88
100
|
const endPort = startPort + 9;
|
|
89
101
|
return `@echo off
|
|
90
|
-
REM Launcher for ${name} — auto-starts beam and opens PWA
|
|
102
|
+
REM Launcher for ${name} — auto-starts beam and opens as PWA
|
|
91
103
|
setlocal enabledelayedexpansion
|
|
92
104
|
|
|
93
|
-
set "
|
|
105
|
+
set "PHOTON=${name}"
|
|
106
|
+
set "VERSION=${version}"
|
|
94
107
|
set START_PORT=${startPort}
|
|
95
108
|
set END_PORT=${endPort}
|
|
96
109
|
|
|
97
|
-
REM
|
|
110
|
+
REM Detect package runner: bunx > pnpx > npx
|
|
111
|
+
where bunx >nul 2>&1 && set "RUNNER=bunx @portel/photon@%VERSION%" && goto :found_runner
|
|
112
|
+
where pnpx >nul 2>&1 && set "RUNNER=pnpx @portel/photon@%VERSION%" && goto :found_runner
|
|
113
|
+
where npx >nul 2>&1 && set "RUNNER=npx -y @portel/photon@%VERSION%" && goto :found_runner
|
|
114
|
+
echo Error: no package runner found (npx, pnpx, or bunx required)
|
|
115
|
+
exit /b 1
|
|
116
|
+
:found_runner
|
|
117
|
+
|
|
118
|
+
REM Scan ports for an existing beam serving this photon
|
|
98
119
|
for /L %%p in (%START_PORT%,1,%END_PORT%) do (
|
|
99
120
|
for /f "delims=" %%r in ('curl -s --max-time 2 "http://localhost:%%p/api/diagnostics" 2^>nul') do (
|
|
100
|
-
echo %%r | findstr /c:"%
|
|
121
|
+
echo %%r | findstr /c:"%PHOTON%" >nul 2>&1
|
|
101
122
|
if !errorlevel! equ 0 (
|
|
102
|
-
|
|
123
|
+
REM Beam already running with this photon — skip browser open
|
|
103
124
|
exit /b 0
|
|
104
125
|
)
|
|
105
126
|
)
|
|
106
127
|
)
|
|
107
128
|
|
|
108
129
|
REM No existing beam found — start one
|
|
109
|
-
start /b
|
|
130
|
+
start /b %RUNNER% %PHOTON% --no-open --port=%START_PORT%
|
|
110
131
|
|
|
111
|
-
REM Poll until beam is ready (up to 30s)
|
|
132
|
+
REM Poll until beam is ready (up to 30s), then open browser
|
|
112
133
|
set WAITED=0
|
|
113
134
|
:poll
|
|
114
135
|
if %WAITED% geq 30 (
|
|
@@ -117,9 +138,9 @@ if %WAITED% geq 30 (
|
|
|
117
138
|
)
|
|
118
139
|
for /L %%p in (%START_PORT%,1,%END_PORT%) do (
|
|
119
140
|
for /f "delims=" %%r in ('curl -s --max-time 1 "http://localhost:%%p/api/diagnostics" 2^>nul') do (
|
|
120
|
-
echo %%r | findstr /c:"%
|
|
141
|
+
echo %%r | findstr /c:"%PHOTON%" >nul 2>&1
|
|
121
142
|
if !errorlevel! equ 0 (
|
|
122
|
-
start "" "http://localhost:%%p"
|
|
143
|
+
start "" "http://localhost:%%p/#%PHOTON%?focus=1"
|
|
123
144
|
exit /b 0
|
|
124
145
|
)
|
|
125
146
|
)
|
|
@@ -129,20 +150,20 @@ set /a WAITED+=1
|
|
|
129
150
|
goto poll
|
|
130
151
|
`;
|
|
131
152
|
}
|
|
132
|
-
async function generateMacOSApp(name, className,
|
|
153
|
+
async function generateMacOSApp(name, className, version, startPort, outputDir) {
|
|
133
154
|
const appDir = path.join(outputDir, `${className}.app`);
|
|
134
155
|
const contentsDir = path.join(appDir, 'Contents');
|
|
135
156
|
const macosDir = path.join(contentsDir, 'MacOS');
|
|
136
157
|
await fs.mkdir(macosDir, { recursive: true });
|
|
137
158
|
await fs.writeFile(path.join(contentsDir, 'Info.plist'), generateInfoPlist(name, className));
|
|
138
|
-
const script = generateBashLauncherScript(name,
|
|
159
|
+
const script = generateBashLauncherScript(name, version, startPort, 'open');
|
|
139
160
|
await fs.writeFile(path.join(macosDir, 'launch'), script, { mode: 0o755 });
|
|
140
161
|
return appDir;
|
|
141
162
|
}
|
|
142
|
-
async function generateLinuxLauncher(name,
|
|
163
|
+
async function generateLinuxLauncher(name, version, startPort, outputDir) {
|
|
143
164
|
const shPath = path.join(outputDir, `${name}.sh`);
|
|
144
165
|
const desktopPath = path.join(outputDir, `${name}.desktop`);
|
|
145
|
-
const script = generateBashLauncherScript(name,
|
|
166
|
+
const script = generateBashLauncherScript(name, version, startPort, 'xdg-open');
|
|
146
167
|
await fs.writeFile(shPath, script, { mode: 0o755 });
|
|
147
168
|
const desktop = `[Desktop Entry]
|
|
148
169
|
Type=Application
|
|
@@ -154,11 +175,30 @@ Categories=Utility;
|
|
|
154
175
|
await fs.writeFile(desktopPath, desktop);
|
|
155
176
|
return [shPath, desktopPath];
|
|
156
177
|
}
|
|
157
|
-
async function generateWindowsLauncher(name,
|
|
178
|
+
async function generateWindowsLauncher(name, version, startPort, outputDir) {
|
|
158
179
|
const batPath = path.join(outputDir, `${name}.bat`);
|
|
159
|
-
await fs.writeFile(batPath, generateWindowsBat(name,
|
|
180
|
+
await fs.writeFile(batPath, generateWindowsBat(name, version, startPort));
|
|
160
181
|
return batPath;
|
|
161
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Check if a photon directory contains an app photon (main() + @ui).
|
|
185
|
+
* Reads .ts/.js source files and looks for class-level @ui asset declaration
|
|
186
|
+
* and a main() method linked to that UI.
|
|
187
|
+
*/
|
|
188
|
+
async function checkIsAppPhoton(photonDir) {
|
|
189
|
+
const entries = await fs.readdir(photonDir);
|
|
190
|
+
const sourceFiles = entries.filter((f) => /\.(ts|js)$/.test(f) && !f.endsWith('.d.ts'));
|
|
191
|
+
for (const file of sourceFiles) {
|
|
192
|
+
const content = await fs.readFile(path.join(photonDir, file), 'utf-8');
|
|
193
|
+
// Check for class-level @ui asset declaration (e.g. @ui my-view ./ui/view.html)
|
|
194
|
+
const hasClassUi = /@ui\s+\S+\s+\S+/.test(content);
|
|
195
|
+
// Check for a main method
|
|
196
|
+
const hasMain = /(?:async\s+)?main\s*\(/.test(content);
|
|
197
|
+
if (hasClassUi && hasMain)
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
162
202
|
export function registerPackageAppCommand(program) {
|
|
163
203
|
program
|
|
164
204
|
.command('package')
|
|
@@ -176,16 +216,57 @@ export function registerPackageAppCommand(program) {
|
|
|
176
216
|
console.error(`Error: photon directory not found: ${photonDir}`);
|
|
177
217
|
process.exit(1);
|
|
178
218
|
}
|
|
219
|
+
// Validate that the photon is an app (has main() method + @ui)
|
|
220
|
+
const isApp = await checkIsAppPhoton(photonDir);
|
|
221
|
+
if (!isApp) {
|
|
222
|
+
console.error(`Error: "${name}" is not an app photon.\n` +
|
|
223
|
+
`Only photons with a main() method and a linked @ui can be packaged as PWA apps.`);
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
// Get the current photon runtime version to pin in launchers
|
|
227
|
+
const { PHOTON_VERSION } = await import('../../version.js');
|
|
179
228
|
const className = toClassName(name);
|
|
180
|
-
console.log(`\n📦 Packaging ${name}...\n`);
|
|
229
|
+
console.log(`\n📦 Packaging ${name} (runtime v${PHOTON_VERSION})...\n`);
|
|
181
230
|
await fs.mkdir(outputDir, { recursive: true });
|
|
182
231
|
// Generate all platform launchers
|
|
183
|
-
const macAppPath = await generateMacOSApp(name, className,
|
|
184
|
-
const [linuxShPath, linuxDesktopPath] = await generateLinuxLauncher(name,
|
|
185
|
-
const winBatPath = await generateWindowsLauncher(name,
|
|
232
|
+
const macAppPath = await generateMacOSApp(name, className, PHOTON_VERSION, startPort, outputDir);
|
|
233
|
+
const [linuxShPath, linuxDesktopPath] = await generateLinuxLauncher(name, PHOTON_VERSION, startPort, outputDir);
|
|
234
|
+
const winBatPath = await generateWindowsLauncher(name, PHOTON_VERSION, startPort, outputDir);
|
|
186
235
|
console.log(` ✓ macOS ${macAppPath}`);
|
|
187
236
|
console.log(` ✓ Linux ${linuxShPath}, ${path.basename(linuxDesktopPath)}`);
|
|
188
237
|
console.log(` ✓ Windows ${winBatPath}`);
|
|
238
|
+
// Write pwa.json to record this PWA instance configuration
|
|
239
|
+
try {
|
|
240
|
+
const pwaConfigPath = path.join(workingDir, 'pwa.json');
|
|
241
|
+
let config = { instances: [] };
|
|
242
|
+
try {
|
|
243
|
+
const raw = await fs.readFile(pwaConfigPath, 'utf-8');
|
|
244
|
+
config = JSON.parse(raw);
|
|
245
|
+
if (!Array.isArray(config.instances))
|
|
246
|
+
config.instances = [];
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
// File doesn't exist yet — use default
|
|
250
|
+
}
|
|
251
|
+
// Deduplicate by port + photon name
|
|
252
|
+
const exists = config.instances.some((i) => i.port === startPort && i.photon === name);
|
|
253
|
+
if (!exists) {
|
|
254
|
+
config.instances.push({
|
|
255
|
+
port: startPort,
|
|
256
|
+
photon: name,
|
|
257
|
+
version: PHOTON_VERSION,
|
|
258
|
+
createdAt: new Date().toISOString(),
|
|
259
|
+
});
|
|
260
|
+
await fs.writeFile(pwaConfigPath, JSON.stringify(config, null, 2));
|
|
261
|
+
console.log(` ✓ pwa.json PWA configured (port ${startPort})`);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
console.log(` ✓ pwa.json Already configured`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
console.error(` ⚠ pwa.json ${err.message || 'Failed to write'}`);
|
|
269
|
+
}
|
|
189
270
|
console.log();
|
|
190
271
|
});
|
|
191
272
|
}
|