@portel/photon 1.18.0 → 1.20.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/dist/auto-ui/beam/routes/api-browse.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-browse.js +16 -4
- package/dist/auto-ui/beam/routes/api-browse.js.map +1 -1
- package/dist/auto-ui/beam/routes/api-config.js +4 -4
- package/dist/auto-ui/beam/routes/api-config.js.map +1 -1
- package/dist/auto-ui/beam/routes/api-marketplace.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-marketplace.js +14 -1
- package/dist/auto-ui/beam/routes/api-marketplace.js.map +1 -1
- package/dist/auto-ui/beam.d.ts.map +1 -1
- package/dist/auto-ui/beam.js +196 -77
- package/dist/auto-ui/beam.js.map +1 -1
- package/dist/auto-ui/bridge/index.d.ts.map +1 -1
- package/dist/auto-ui/bridge/index.js +17 -0
- package/dist/auto-ui/bridge/index.js.map +1 -1
- package/dist/auto-ui/streamable-http-transport.d.ts +1 -0
- package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
- package/dist/auto-ui/streamable-http-transport.js +64 -16
- package/dist/auto-ui/streamable-http-transport.js.map +1 -1
- package/dist/auto-ui/types.d.ts +12 -0
- package/dist/auto-ui/types.d.ts.map +1 -1
- package/dist/auto-ui/types.js.map +1 -1
- package/dist/beam-form.bundle.js +49 -6
- package/dist/beam-form.bundle.js.map +2 -2
- package/dist/beam.bundle.js +2090 -512
- package/dist/beam.bundle.js.map +4 -4
- package/dist/capability-negotiator.d.ts +67 -0
- package/dist/capability-negotiator.d.ts.map +1 -0
- package/dist/capability-negotiator.js +104 -0
- package/dist/capability-negotiator.js.map +1 -0
- package/dist/channel-manager.d.ts +122 -0
- package/dist/channel-manager.d.ts.map +1 -0
- package/dist/channel-manager.js +266 -0
- package/dist/channel-manager.js.map +1 -0
- package/dist/claude-code-plugin.js +1 -1
- package/dist/cli/commands/beam.d.ts.map +1 -1
- package/dist/cli/commands/beam.js +8 -2
- package/dist/cli/commands/beam.js.map +1 -1
- package/dist/cli/commands/changelog.d.ts +9 -0
- package/dist/cli/commands/changelog.d.ts.map +1 -0
- package/dist/cli/commands/changelog.js +133 -0
- package/dist/cli/commands/changelog.js.map +1 -0
- package/dist/cli/commands/maker.d.ts.map +1 -1
- package/dist/cli/commands/maker.js +23 -2
- package/dist/cli/commands/maker.js.map +1 -1
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +53 -0
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/package.d.ts.map +1 -1
- package/dist/cli/commands/package.js +43 -9
- package/dist/cli/commands/package.js.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +1 -0
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/update.d.ts +3 -2
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +50 -43
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +16 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli-alias.js +1 -1
- package/dist/cli-alias.js.map +1 -1
- package/dist/context-store.d.ts +23 -33
- package/dist/context-store.d.ts.map +1 -1
- package/dist/context-store.js +147 -97
- package/dist/context-store.js.map +1 -1
- package/dist/context.d.ts +15 -10
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +37 -13
- package/dist/context.js.map +1 -1
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +12 -0
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/server.js +34 -51
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/worker-manager.d.ts.map +1 -1
- package/dist/daemon/worker-manager.js +21 -7
- package/dist/daemon/worker-manager.js.map +1 -1
- package/dist/data-migration.d.ts +27 -0
- package/dist/data-migration.d.ts.map +1 -0
- package/dist/data-migration.js +307 -0
- package/dist/data-migration.js.map +1 -0
- package/dist/editor-support/docblock-tag-catalog.d.ts.map +1 -1
- package/dist/editor-support/docblock-tag-catalog.js +6 -0
- package/dist/editor-support/docblock-tag-catalog.js.map +1 -1
- package/dist/loader.d.ts +13 -0
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +169 -22
- package/dist/loader.js.map +1 -1
- package/dist/marketplace-manager.d.ts +6 -0
- package/dist/marketplace-manager.d.ts.map +1 -1
- package/dist/marketplace-manager.js +185 -62
- package/dist/marketplace-manager.js.map +1 -1
- package/dist/namespace-migration.d.ts +1 -0
- package/dist/namespace-migration.d.ts.map +1 -1
- package/dist/namespace-migration.js +86 -0
- package/dist/namespace-migration.js.map +1 -1
- package/dist/photon-cli-runner.d.ts.map +1 -1
- package/dist/photon-cli-runner.js +47 -21
- package/dist/photon-cli-runner.js.map +1 -1
- package/dist/photon-doc-extractor.d.ts +1 -0
- package/dist/photon-doc-extractor.d.ts.map +1 -1
- package/dist/photon-doc-extractor.js +6 -0
- package/dist/photon-doc-extractor.js.map +1 -1
- package/dist/readme-syncer.d.ts.map +1 -1
- package/dist/readme-syncer.js +6 -1
- package/dist/readme-syncer.js.map +1 -1
- package/dist/resource-server.d.ts +105 -0
- package/dist/resource-server.d.ts.map +1 -0
- package/dist/resource-server.js +723 -0
- package/dist/resource-server.js.map +1 -0
- package/dist/serv/auth/jwt.d.ts +2 -0
- package/dist/serv/auth/jwt.d.ts.map +1 -1
- package/dist/serv/auth/jwt.js +11 -5
- package/dist/serv/auth/jwt.js.map +1 -1
- package/dist/serv/vault/token-vault.d.ts +2 -0
- package/dist/serv/vault/token-vault.d.ts.map +1 -1
- package/dist/serv/vault/token-vault.js +6 -0
- package/dist/serv/vault/token-vault.js.map +1 -1
- package/dist/server.d.ts +30 -119
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +252 -1122
- package/dist/server.js.map +1 -1
- package/dist/shared/audit.d.ts.map +1 -1
- package/dist/shared/audit.js +11 -4
- package/dist/shared/audit.js.map +1 -1
- package/dist/shared/security.d.ts +10 -0
- package/dist/shared/security.d.ts.map +1 -1
- package/dist/shared/security.js +27 -0
- package/dist/shared/security.js.map +1 -1
- package/dist/task-executor.d.ts +69 -0
- package/dist/task-executor.d.ts.map +1 -0
- package/dist/task-executor.js +182 -0
- package/dist/task-executor.js.map +1 -0
- package/dist/tasks/store.d.ts.map +1 -1
- package/dist/tasks/store.js +6 -2
- package/dist/tasks/store.js.map +1 -1
- package/dist/types/photon-instance.d.ts +50 -0
- package/dist/types/photon-instance.d.ts.map +1 -0
- package/dist/types/photon-instance.js +9 -0
- package/dist/types/photon-instance.js.map +1 -0
- package/dist/types/server-types.d.ts +61 -0
- package/dist/types/server-types.d.ts.map +1 -0
- package/dist/types/server-types.js +8 -0
- package/dist/types/server-types.js.map +1 -0
- package/dist/version-notify.d.ts +27 -0
- package/dist/version-notify.d.ts.map +1 -0
- package/dist/version-notify.js +142 -0
- package/dist/version-notify.js.map +1 -0
- package/package.json +3 -3
- package/dist/auto-ui/bridge/openai-shim.d.ts +0 -20
- package/dist/auto-ui/bridge/openai-shim.d.ts.map +0 -1
- package/dist/auto-ui/bridge/openai-shim.js +0 -231
- package/dist/auto-ui/bridge/openai-shim.js.map +0 -1
- package/dist/auto-ui/bridge/photon-app.d.ts +0 -162
- package/dist/auto-ui/bridge/photon-app.d.ts.map +0 -1
- package/dist/auto-ui/bridge/photon-app.js +0 -460
- package/dist/auto-ui/bridge/photon-app.js.map +0 -1
- package/dist/auto-ui/daemon-tools.d.ts +0 -45
- package/dist/auto-ui/daemon-tools.d.ts.map +0 -1
- package/dist/auto-ui/daemon-tools.js +0 -581
- package/dist/auto-ui/daemon-tools.js.map +0 -1
- package/dist/auto-ui/design-system/index.d.ts +0 -21
- package/dist/auto-ui/design-system/index.d.ts.map +0 -1
- package/dist/auto-ui/design-system/index.js +0 -27
- package/dist/auto-ui/design-system/index.js.map +0 -1
- package/dist/auto-ui/design-system/transaction-ui.d.ts +0 -70
- package/dist/auto-ui/design-system/transaction-ui.d.ts.map +0 -1
- package/dist/auto-ui/design-system/transaction-ui.js +0 -982
- package/dist/auto-ui/design-system/transaction-ui.js.map +0 -1
- package/dist/auto-ui/playground-server.d.ts +0 -7
- package/dist/auto-ui/playground-server.d.ts.map +0 -1
- package/dist/auto-ui/playground-server.js +0 -840
- package/dist/auto-ui/playground-server.js.map +0 -1
- package/dist/auto-ui/rendering/components.d.ts +0 -29
- package/dist/auto-ui/rendering/components.d.ts.map +0 -1
- package/dist/auto-ui/rendering/components.js +0 -1341
- package/dist/auto-ui/rendering/components.js.map +0 -1
- package/dist/auto-ui/rendering/field-analyzer.d.ts +0 -104
- package/dist/auto-ui/rendering/field-analyzer.d.ts.map +0 -1
- package/dist/auto-ui/rendering/field-analyzer.js +0 -447
- package/dist/auto-ui/rendering/field-analyzer.js.map +0 -1
- package/dist/auto-ui/rendering/field-renderers.d.ts +0 -64
- package/dist/auto-ui/rendering/field-renderers.d.ts.map +0 -1
- package/dist/auto-ui/rendering/field-renderers.js +0 -317
- package/dist/auto-ui/rendering/field-renderers.js.map +0 -1
- package/dist/auto-ui/rendering/index.d.ts +0 -28
- package/dist/auto-ui/rendering/index.d.ts.map +0 -1
- package/dist/auto-ui/rendering/index.js +0 -60
- package/dist/auto-ui/rendering/index.js.map +0 -1
- package/dist/auto-ui/rendering/layout-selector.d.ts +0 -60
- package/dist/auto-ui/rendering/layout-selector.d.ts.map +0 -1
- package/dist/auto-ui/rendering/layout-selector.js +0 -476
- package/dist/auto-ui/rendering/layout-selector.js.map +0 -1
- package/dist/markdown-utils.d.ts +0 -8
- package/dist/markdown-utils.d.ts.map +0 -1
- package/dist/markdown-utils.js +0 -64
- package/dist/markdown-utils.js.map +0 -1
- package/dist/mcp-client.d.ts +0 -9
- package/dist/mcp-client.d.ts.map +0 -1
- package/dist/mcp-client.js +0 -11
- package/dist/mcp-client.js.map +0 -1
- package/dist/mcp-elicitation.d.ts +0 -32
- package/dist/mcp-elicitation.d.ts.map +0 -1
- package/dist/mcp-elicitation.js +0 -26
- package/dist/mcp-elicitation.js.map +0 -1
- package/dist/photons/builder-compass.photon.d.ts +0 -167
- package/dist/photons/builder-compass.photon.d.ts.map +0 -1
- package/dist/photons/builder-compass.photon.js +0 -816
- package/dist/photons/builder-compass.photon.js.map +0 -1
- package/dist/photons/builder-compass.photon.ts +0 -1129
- package/dist/photons/docs/ui/docs.html +0 -441
- package/dist/photons/docs.photon.d.ts +0 -237
- package/dist/photons/docs.photon.d.ts.map +0 -1
- package/dist/photons/docs.photon.js +0 -483
- package/dist/photons/docs.photon.js.map +0 -1
- package/dist/photons/docs.photon.ts +0 -536
- package/dist/photons/slides.photon.d.ts +0 -212
- package/dist/photons/slides.photon.d.ts.map +0 -1
- package/dist/photons/slides.photon.js +0 -355
- package/dist/photons/slides.photon.js.map +0 -1
- package/dist/photons/slides.photon.ts +0 -370
- package/dist/photons/spreadsheet/ui/spreadsheet.html +0 -779
- package/dist/photons/spreadsheet.photon.d.ts +0 -554
- package/dist/photons/spreadsheet.photon.d.ts.map +0 -1
- package/dist/photons/spreadsheet.photon.js +0 -1050
- package/dist/photons/spreadsheet.photon.js.map +0 -1
- package/dist/photons/spreadsheet.photon.ts +0 -1239
- package/dist/photons/ui/builder-compass.html +0 -1199
- package/dist/photons/ui/builder-compass.photon.html +0 -380
- package/dist/security-scanner.d.ts +0 -52
- package/dist/security-scanner.d.ts.map +0 -1
- package/dist/security-scanner.js +0 -181
- package/dist/security-scanner.js.map +0 -1
- package/dist/shared/performance.d.ts +0 -65
- package/dist/shared/performance.d.ts.map +0 -1
- package/dist/shared/performance.js +0 -136
- package/dist/shared/performance.js.map +0 -1
|
@@ -11,6 +11,7 @@ import { createLogger } from './shared/logger.js';
|
|
|
11
11
|
import { getErrorMessage } from './shared/error-handler.js';
|
|
12
12
|
import { verifyContentHash, validateAssetPath, isPathWithin } from './shared/security.js';
|
|
13
13
|
import { getDefaultContext } from './context.js';
|
|
14
|
+
import { getMetadataPath, resolvePath } from '@portel/photon-core';
|
|
14
15
|
import { SchemaExtractor } from '@portel/photon-core';
|
|
15
16
|
// Timeout for marketplace fetch requests
|
|
16
17
|
const FETCH_TIMEOUT_MS = 10 * 1000;
|
|
@@ -32,8 +33,12 @@ function getGitHubToken() {
|
|
|
32
33
|
_ghToken = process.env.GITHUB_TOKEN || null;
|
|
33
34
|
if (!_ghToken) {
|
|
34
35
|
try {
|
|
35
|
-
const {
|
|
36
|
-
_ghToken =
|
|
36
|
+
const { execFileSync } = require('child_process');
|
|
37
|
+
_ghToken =
|
|
38
|
+
execFileSync('gh', ['auth', 'token'], {
|
|
39
|
+
encoding: 'utf-8',
|
|
40
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
41
|
+
}).trim() || null;
|
|
37
42
|
}
|
|
38
43
|
catch {
|
|
39
44
|
_ghToken = null;
|
|
@@ -56,7 +61,7 @@ function ghFetch(url, options = {}) {
|
|
|
56
61
|
return fetch(url, { ...options, headers });
|
|
57
62
|
}
|
|
58
63
|
const CONFIG_DIR = getDefaultContext().baseDir;
|
|
59
|
-
const METADATA_FILE =
|
|
64
|
+
const METADATA_FILE = getMetadataPath();
|
|
60
65
|
// Cache is considered stale after 24 hours
|
|
61
66
|
const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
62
67
|
// Built-in marketplaces that ship with the runtime
|
|
@@ -126,6 +131,11 @@ export async function readLocalMetadata() {
|
|
|
126
131
|
}
|
|
127
132
|
return { photons: {} };
|
|
128
133
|
}
|
|
134
|
+
function validateSafeName(name, label) {
|
|
135
|
+
if (/[;&|$`(){}\\\<>!#~\n\r]/.test(name)) {
|
|
136
|
+
throw new Error(`Invalid ${label}: contains unsafe characters`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
129
139
|
export class MarketplaceManager {
|
|
130
140
|
config = { marketplaces: [] };
|
|
131
141
|
logger;
|
|
@@ -138,8 +148,8 @@ export class MarketplaceManager {
|
|
|
138
148
|
const dir = baseDir || CONFIG_DIR;
|
|
139
149
|
this.configDir = dir;
|
|
140
150
|
this.configFile = path.join(dir, 'marketplaces.json');
|
|
141
|
-
this.cacheDir = path.join(
|
|
142
|
-
this.metadataFile =
|
|
151
|
+
this.cacheDir = path.join(getDefaultContext().cacheDir, 'marketplaces');
|
|
152
|
+
this.metadataFile = getMetadataPath(dir);
|
|
143
153
|
}
|
|
144
154
|
async initialize() {
|
|
145
155
|
await fs.mkdir(this.configDir, { recursive: true });
|
|
@@ -731,7 +741,7 @@ export class MarketplaceManager {
|
|
|
731
741
|
* Safe to call on every startup — only fetches when assets are actually missing.
|
|
732
742
|
*/
|
|
733
743
|
async repairMissingAssets(workingDir) {
|
|
734
|
-
const localMetadata = await
|
|
744
|
+
const localMetadata = await this.readMetadata();
|
|
735
745
|
let repaired = 0;
|
|
736
746
|
for (const [fileName, installInfo] of Object.entries(localMetadata.photons)) {
|
|
737
747
|
const photonName = fileName.replace(/\.photon\.ts$/, '');
|
|
@@ -965,6 +975,11 @@ export class MarketplaceManager {
|
|
|
965
975
|
}
|
|
966
976
|
}
|
|
967
977
|
}
|
|
978
|
+
// Install @photon transitive dependencies from the same marketplace
|
|
979
|
+
const transitiveDeps = await this.installTransitiveDeps(content, result.marketplace, workingDir);
|
|
980
|
+
if (transitiveDeps.length > 0) {
|
|
981
|
+
assetsInstalled.push(...transitiveDeps.map((d) => `@photon ${d}`));
|
|
982
|
+
}
|
|
968
983
|
return { photonPath, assetsInstalled };
|
|
969
984
|
}
|
|
970
985
|
/**
|
|
@@ -1004,10 +1019,21 @@ export class MarketplaceManager {
|
|
|
1004
1019
|
const deps = extractor.extractPhotonDependencies(content);
|
|
1005
1020
|
const installed = [];
|
|
1006
1021
|
for (const dep of deps) {
|
|
1022
|
+
// Resolve dependency name from source
|
|
1023
|
+
let depName;
|
|
1007
1024
|
if (dep.sourceType === 'local' &&
|
|
1008
1025
|
(dep.source.startsWith('./') || dep.source.startsWith('../'))) {
|
|
1009
|
-
|
|
1010
|
-
|
|
1026
|
+
// Relative path: ./chat.photon.ts → chat
|
|
1027
|
+
depName = path.basename(dep.source).replace(/\.photon\.(ts|js)$/, '');
|
|
1028
|
+
}
|
|
1029
|
+
else if (dep.sourceType === 'marketplace' || !dep.source.startsWith('/')) {
|
|
1030
|
+
// Marketplace name: whatsapp, agent-router, courier
|
|
1031
|
+
depName = dep.source;
|
|
1032
|
+
}
|
|
1033
|
+
else {
|
|
1034
|
+
continue; // Absolute paths — skip
|
|
1035
|
+
}
|
|
1036
|
+
{
|
|
1011
1037
|
if (visited.has(depName))
|
|
1012
1038
|
continue;
|
|
1013
1039
|
visited.add(depName);
|
|
@@ -1016,6 +1042,9 @@ export class MarketplaceManager {
|
|
|
1016
1042
|
const installDir = namespace ? path.join(workingDir, namespace) : workingDir;
|
|
1017
1043
|
if (existsSync(path.join(installDir, `${depName}.photon.ts`)))
|
|
1018
1044
|
continue;
|
|
1045
|
+
// Also check flat in workingDir
|
|
1046
|
+
if (existsSync(path.join(workingDir, `${depName}.photon.ts`)))
|
|
1047
|
+
continue;
|
|
1019
1048
|
// Fetch from the same marketplace
|
|
1020
1049
|
this.logger.info(`Fetching @photon dependency: ${depName}`);
|
|
1021
1050
|
const depResult = await this.fetchMCPFromMarketplace(depName, marketplace);
|
|
@@ -1123,7 +1152,7 @@ export class MarketplaceManager {
|
|
|
1123
1152
|
return { photons: {} };
|
|
1124
1153
|
}
|
|
1125
1154
|
async writeMetadata(metadata) {
|
|
1126
|
-
await fs.mkdir(this.
|
|
1155
|
+
await fs.mkdir(path.dirname(this.metadataFile), { recursive: true });
|
|
1127
1156
|
await writeJSON(this.metadataFile, metadata);
|
|
1128
1157
|
}
|
|
1129
1158
|
/**
|
|
@@ -1307,30 +1336,82 @@ export class MarketplaceManager {
|
|
|
1307
1336
|
* Shared logic used by both CLI and Beam.
|
|
1308
1337
|
*/
|
|
1309
1338
|
async forkPhoton(name, workingDir, options) {
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
if (
|
|
1339
|
+
validateSafeName(name, 'photon name');
|
|
1340
|
+
if (options?.targetRepo)
|
|
1341
|
+
validateSafeName(options.targetRepo, 'target repo');
|
|
1342
|
+
if (options?.createRepo)
|
|
1343
|
+
validateSafeName(options.createRepo, 'repo name');
|
|
1344
|
+
if (options?.newName)
|
|
1345
|
+
validateSafeName(options.newName, 'new photon name');
|
|
1346
|
+
const sourcePath = await resolvePath(name, workingDir);
|
|
1347
|
+
if (!sourcePath) {
|
|
1314
1348
|
return { success: false, message: `Photon not found: ${name}` };
|
|
1315
1349
|
}
|
|
1316
|
-
|
|
1317
|
-
const
|
|
1318
|
-
const
|
|
1319
|
-
|
|
1350
|
+
const sourceName = path.basename(sourcePath).replace(/\.photon\.(ts|js)$/, '');
|
|
1351
|
+
const normalizedSourceKey = this.toMetadataKey(sourcePath, workingDir);
|
|
1352
|
+
const requestedNewName = options?.newName?.trim();
|
|
1353
|
+
const localMetadata = await this.readMetadata();
|
|
1354
|
+
const installMeta = localMetadata.photons[normalizedSourceKey];
|
|
1355
|
+
const isLocalSource = !installMeta;
|
|
1356
|
+
const targetName = requestedNewName || sourceName;
|
|
1357
|
+
const suggestedName = `${sourceName}-copy`;
|
|
1358
|
+
if (isLocalSource && !requestedNewName) {
|
|
1320
1359
|
return {
|
|
1321
|
-
success:
|
|
1322
|
-
message: `${
|
|
1360
|
+
success: false,
|
|
1361
|
+
message: `${sourceName} is already local. Choose a new local name to fork it.`,
|
|
1362
|
+
requiresName: true,
|
|
1363
|
+
suggestedName,
|
|
1323
1364
|
};
|
|
1324
1365
|
}
|
|
1366
|
+
if (isLocalSource && requestedNewName === sourceName) {
|
|
1367
|
+
return {
|
|
1368
|
+
success: false,
|
|
1369
|
+
message: 'Forking a local photon requires a different new name.',
|
|
1370
|
+
requiresName: true,
|
|
1371
|
+
suggestedName,
|
|
1372
|
+
};
|
|
1373
|
+
}
|
|
1374
|
+
const targetPath = path.join(workingDir, `${targetName}.photon.ts`);
|
|
1375
|
+
const sourceRealPath = await fs.realpath(sourcePath).catch(() => sourcePath);
|
|
1376
|
+
const targetExists = existsSync(targetPath);
|
|
1377
|
+
const targetRealPath = targetExists
|
|
1378
|
+
? await fs.realpath(targetPath).catch(() => targetPath)
|
|
1379
|
+
: null;
|
|
1380
|
+
if (targetExists && targetRealPath !== sourceRealPath) {
|
|
1381
|
+
return {
|
|
1382
|
+
success: false,
|
|
1383
|
+
message: `A local photon named ${targetName} already exists. Choose a different local name.`,
|
|
1384
|
+
requiresName: true,
|
|
1385
|
+
suggestedName,
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
const fileName = `${targetName}.photon.ts`;
|
|
1389
|
+
const filePath = targetPath;
|
|
1325
1390
|
// Check @forkedFrom tag
|
|
1326
|
-
const content = await readText(
|
|
1391
|
+
const content = await readText(sourcePath);
|
|
1327
1392
|
const hasForkedFrom = content.includes('@forkedFrom');
|
|
1393
|
+
const sourceAssetDir = path.join(path.dirname(sourcePath), sourceName);
|
|
1394
|
+
const targetAssetDir = path.join(workingDir, targetName);
|
|
1395
|
+
if (targetRealPath !== sourceRealPath && !isLocalSource) {
|
|
1396
|
+
await fs.mkdir(workingDir, { recursive: true });
|
|
1397
|
+
await fs.rename(sourcePath, targetPath);
|
|
1398
|
+
await this.movePhotonAssetDir(sourceAssetDir, targetAssetDir);
|
|
1399
|
+
}
|
|
1400
|
+
else if (targetRealPath !== sourceRealPath) {
|
|
1401
|
+
await fs.copyFile(sourcePath, targetPath);
|
|
1402
|
+
await this.copyPhotonAssetDir(sourceAssetDir, targetAssetDir);
|
|
1403
|
+
}
|
|
1404
|
+
else if (path.dirname(sourcePath) !== workingDir || targetName !== sourceName) {
|
|
1405
|
+
await fs.mkdir(workingDir, { recursive: true });
|
|
1406
|
+
await fs.rename(sourcePath, targetPath);
|
|
1407
|
+
await this.movePhotonAssetDir(sourceAssetDir, targetAssetDir);
|
|
1408
|
+
}
|
|
1328
1409
|
// Handle target repo push if specified
|
|
1329
1410
|
if (options?.targetRepo || options?.createRepo) {
|
|
1330
|
-
const {
|
|
1411
|
+
const { execFileSync } = await import('child_process');
|
|
1331
1412
|
// Check gh CLI
|
|
1332
1413
|
try {
|
|
1333
|
-
|
|
1414
|
+
execFileSync('gh', ['--version'], { stdio: 'pipe' });
|
|
1334
1415
|
}
|
|
1335
1416
|
catch {
|
|
1336
1417
|
return {
|
|
@@ -1341,7 +1422,9 @@ export class MarketplaceManager {
|
|
|
1341
1422
|
if (options.createRepo) {
|
|
1342
1423
|
// Create new repo and push
|
|
1343
1424
|
try {
|
|
1344
|
-
|
|
1425
|
+
execFileSync('gh', ['repo', 'create', options.createRepo, '--public', '--confirm'], {
|
|
1426
|
+
stdio: 'pipe',
|
|
1427
|
+
});
|
|
1345
1428
|
}
|
|
1346
1429
|
catch {
|
|
1347
1430
|
// Repo may already exist
|
|
@@ -1349,23 +1432,17 @@ export class MarketplaceManager {
|
|
|
1349
1432
|
const targetRepo = options.createRepo;
|
|
1350
1433
|
const tmpDir = path.join(os.tmpdir(), `photon-fork-${Date.now()}`);
|
|
1351
1434
|
try {
|
|
1352
|
-
|
|
1435
|
+
execFileSync('gh', ['repo', 'clone', targetRepo, tmpDir, '--', '--depth=1'], {
|
|
1353
1436
|
stdio: 'pipe',
|
|
1354
1437
|
});
|
|
1355
1438
|
await fs.copyFile(filePath, path.join(tmpDir, fileName));
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
await fs.mkdir(path.dirname(dstAsset), { recursive: true });
|
|
1364
|
-
await fs.copyFile(srcAsset, dstAsset);
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
execSync(`cd "${tmpDir}" && git add -A && git commit -m "fork: ${name} photon" && git push origin`, { stdio: 'pipe' });
|
|
1439
|
+
await this.copyPhotonAssetDir(targetAssetDir, path.join(tmpDir, targetName));
|
|
1440
|
+
execFileSync('git', ['add', '-A'], { cwd: tmpDir, stdio: 'pipe' });
|
|
1441
|
+
execFileSync('git', ['commit', '-m', `fork: ${name} photon`], {
|
|
1442
|
+
cwd: tmpDir,
|
|
1443
|
+
stdio: 'pipe',
|
|
1444
|
+
});
|
|
1445
|
+
execFileSync('git', ['push', 'origin'], { cwd: tmpDir, stdio: 'pipe' });
|
|
1369
1446
|
await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => { });
|
|
1370
1447
|
}
|
|
1371
1448
|
catch (e) {
|
|
@@ -1380,23 +1457,17 @@ export class MarketplaceManager {
|
|
|
1380
1457
|
// Push to existing repo
|
|
1381
1458
|
const tmpDir = path.join(os.tmpdir(), `photon-fork-${Date.now()}`);
|
|
1382
1459
|
try {
|
|
1383
|
-
|
|
1460
|
+
execFileSync('gh', ['repo', 'clone', options.targetRepo, tmpDir, '--', '--depth=1'], {
|
|
1384
1461
|
stdio: 'pipe',
|
|
1385
1462
|
});
|
|
1386
1463
|
await fs.copyFile(filePath, path.join(tmpDir, fileName));
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
await fs.mkdir(path.dirname(dstAsset), { recursive: true });
|
|
1395
|
-
await fs.copyFile(srcAsset, dstAsset);
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
execSync(`cd "${tmpDir}" && git add -A && git commit -m "fork: ${name} photon" && git push origin`, { stdio: 'pipe' });
|
|
1464
|
+
await this.copyPhotonAssetDir(targetAssetDir, path.join(tmpDir, targetName));
|
|
1465
|
+
execFileSync('git', ['add', '-A'], { cwd: tmpDir, stdio: 'pipe' });
|
|
1466
|
+
execFileSync('git', ['commit', '-m', `fork: ${name} photon`], {
|
|
1467
|
+
cwd: tmpDir,
|
|
1468
|
+
stdio: 'pipe',
|
|
1469
|
+
});
|
|
1470
|
+
execFileSync('git', ['push', 'origin'], { cwd: tmpDir, stdio: 'pipe' });
|
|
1400
1471
|
await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => { });
|
|
1401
1472
|
}
|
|
1402
1473
|
catch (e) {
|
|
@@ -1409,22 +1480,59 @@ export class MarketplaceManager {
|
|
|
1409
1480
|
}
|
|
1410
1481
|
}
|
|
1411
1482
|
// Remove marketplace tracking
|
|
1412
|
-
|
|
1483
|
+
if (installMeta) {
|
|
1484
|
+
delete localMetadata.photons[normalizedSourceKey];
|
|
1485
|
+
}
|
|
1413
1486
|
await this.writeMetadata(localMetadata);
|
|
1414
1487
|
const parts = [];
|
|
1415
|
-
|
|
1488
|
+
if (targetName !== sourceName) {
|
|
1489
|
+
parts.push(`Created local fork ${targetName} from ${sourceName}`);
|
|
1490
|
+
}
|
|
1491
|
+
else {
|
|
1492
|
+
parts.push(`${sourceName} is now your own`);
|
|
1493
|
+
}
|
|
1416
1494
|
if (hasForkedFrom) {
|
|
1417
1495
|
parts.push('Origin preserved as @forkedFrom tag');
|
|
1418
1496
|
}
|
|
1419
|
-
|
|
1497
|
+
if (installMeta) {
|
|
1498
|
+
parts.push('Marketplace update tracking removed');
|
|
1499
|
+
}
|
|
1420
1500
|
return { success: true, message: parts.join('. ') };
|
|
1421
1501
|
}
|
|
1502
|
+
toMetadataKey(filePath, workingDir) {
|
|
1503
|
+
return path.relative(workingDir, filePath).split(path.sep).join('/');
|
|
1504
|
+
}
|
|
1505
|
+
async copyPhotonAssetDir(sourceDir, targetDir) {
|
|
1506
|
+
const stat = await fs.lstat(sourceDir).catch(() => null);
|
|
1507
|
+
if (!stat)
|
|
1508
|
+
return;
|
|
1509
|
+
if (stat.isSymbolicLink()) {
|
|
1510
|
+
const linkTarget = await fs.readlink(sourceDir);
|
|
1511
|
+
await fs.symlink(linkTarget, targetDir).catch(() => { });
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1514
|
+
if (!stat.isDirectory())
|
|
1515
|
+
return;
|
|
1516
|
+
await fs.cp(sourceDir, targetDir, { recursive: true, force: true });
|
|
1517
|
+
}
|
|
1518
|
+
async movePhotonAssetDir(sourceDir, targetDir) {
|
|
1519
|
+
const stat = await fs.lstat(sourceDir).catch(() => null);
|
|
1520
|
+
if (!stat)
|
|
1521
|
+
return;
|
|
1522
|
+
if (existsSync(targetDir))
|
|
1523
|
+
return;
|
|
1524
|
+
await fs.mkdir(path.dirname(targetDir), { recursive: true });
|
|
1525
|
+
await fs.rename(sourceDir, targetDir);
|
|
1526
|
+
}
|
|
1422
1527
|
/**
|
|
1423
1528
|
* Contribute a photon back upstream via PR.
|
|
1424
1529
|
* Shared logic used by both CLI and Beam.
|
|
1425
1530
|
*/
|
|
1426
1531
|
async contributePhoton(name, workingDir, options) {
|
|
1427
|
-
|
|
1532
|
+
validateSafeName(name, 'photon name');
|
|
1533
|
+
if (options?.branch)
|
|
1534
|
+
validateSafeName(options.branch, 'branch name');
|
|
1535
|
+
const { execFileSync } = await import('child_process');
|
|
1428
1536
|
const fileName = `${name}.photon.ts`;
|
|
1429
1537
|
const filePath = path.join(workingDir, fileName);
|
|
1430
1538
|
// Check file exists
|
|
@@ -1433,7 +1541,7 @@ export class MarketplaceManager {
|
|
|
1433
1541
|
}
|
|
1434
1542
|
// Check gh CLI
|
|
1435
1543
|
try {
|
|
1436
|
-
|
|
1544
|
+
execFileSync('gh', ['--version'], { stdio: 'pipe' });
|
|
1437
1545
|
}
|
|
1438
1546
|
catch {
|
|
1439
1547
|
return {
|
|
@@ -1443,7 +1551,7 @@ export class MarketplaceManager {
|
|
|
1443
1551
|
}
|
|
1444
1552
|
// Check gh auth
|
|
1445
1553
|
try {
|
|
1446
|
-
|
|
1554
|
+
execFileSync('gh', ['auth', 'status'], { stdio: 'pipe' });
|
|
1447
1555
|
}
|
|
1448
1556
|
catch {
|
|
1449
1557
|
return {
|
|
@@ -1492,20 +1600,20 @@ export class MarketplaceManager {
|
|
|
1492
1600
|
}
|
|
1493
1601
|
// Fork the repo
|
|
1494
1602
|
try {
|
|
1495
|
-
|
|
1603
|
+
execFileSync('gh', ['repo', 'fork', repo, '--clone=false'], { stdio: 'pipe' });
|
|
1496
1604
|
}
|
|
1497
1605
|
catch {
|
|
1498
1606
|
// Fork may already exist
|
|
1499
1607
|
}
|
|
1500
1608
|
// Get fork name
|
|
1501
|
-
const forkJson =
|
|
1609
|
+
const forkJson = execFileSync('gh', ['api', 'user'], { encoding: 'utf-8' });
|
|
1502
1610
|
const ghUser = JSON.parse(forkJson).login;
|
|
1503
1611
|
const repoName = repo.split('/')[1];
|
|
1504
1612
|
const forkRepo = `${ghUser}/${repoName}`;
|
|
1505
1613
|
// Clone to temp dir
|
|
1506
1614
|
const tmpDir = path.join(os.tmpdir(), `photon-contribute-${Date.now()}`);
|
|
1507
1615
|
try {
|
|
1508
|
-
|
|
1616
|
+
execFileSync('gh', ['repo', 'clone', forkRepo, tmpDir, '--', '--depth=1'], {
|
|
1509
1617
|
stdio: 'pipe',
|
|
1510
1618
|
});
|
|
1511
1619
|
// Copy modified photon file
|
|
@@ -1523,9 +1631,24 @@ export class MarketplaceManager {
|
|
|
1523
1631
|
}
|
|
1524
1632
|
}
|
|
1525
1633
|
// Create branch, commit, push
|
|
1526
|
-
|
|
1634
|
+
execFileSync('git', ['checkout', '-b', branchName], { cwd: tmpDir, stdio: 'pipe' });
|
|
1635
|
+
execFileSync('git', ['add', '-A'], { cwd: tmpDir, stdio: 'pipe' });
|
|
1636
|
+
execFileSync('git', ['commit', '-m', `improve: update ${name} photon`], {
|
|
1637
|
+
cwd: tmpDir,
|
|
1638
|
+
stdio: 'pipe',
|
|
1639
|
+
});
|
|
1640
|
+
execFileSync('git', ['push', 'origin', branchName], { cwd: tmpDir, stdio: 'pipe' });
|
|
1527
1641
|
// Create PR
|
|
1528
|
-
const prOutput =
|
|
1642
|
+
const prOutput = execFileSync('gh', [
|
|
1643
|
+
'pr',
|
|
1644
|
+
'create',
|
|
1645
|
+
'--repo',
|
|
1646
|
+
repo,
|
|
1647
|
+
'--title',
|
|
1648
|
+
`Improve ${name} photon`,
|
|
1649
|
+
'--body',
|
|
1650
|
+
`Contributed improvements to ${name} photon via Photon marketplace.`,
|
|
1651
|
+
], { cwd: tmpDir, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
1529
1652
|
// Cleanup temp dir
|
|
1530
1653
|
await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => { });
|
|
1531
1654
|
const prUrl = prOutput.trim();
|