@aotui/runtime 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,41 @@
1
+ import { type CatalogData } from './default-catalog.js';
2
+ import type { CatalogConfig, CatalogTrustKeyConfig } from '../engine/app/config.js';
3
+ export interface CatalogSignature {
4
+ keyId: string;
5
+ algorithm?: 'ed25519';
6
+ value: string;
7
+ }
8
+ export interface RemoteCatalogEnvelope {
9
+ catalog: CatalogData;
10
+ signature?: CatalogSignature;
11
+ }
12
+ export interface TrustedCatalogKey {
13
+ keyId: string;
14
+ algorithm: 'ed25519';
15
+ publicKey: string;
16
+ }
17
+ export interface CatalogResolverOptions {
18
+ remoteUrl?: string;
19
+ cachePath?: string;
20
+ requireSignature?: boolean;
21
+ trustedKeys?: TrustedCatalogKey[];
22
+ fetchImpl?: typeof fetch;
23
+ }
24
+ export interface ResolvedCatalog {
25
+ source: 'remote' | 'cache' | 'builtin';
26
+ catalog: CatalogData;
27
+ remoteUrl?: string;
28
+ cachedAt?: string;
29
+ signatureVerified: boolean;
30
+ warnings: string[];
31
+ }
32
+ export declare function resolveCatalogOptionsFromConfig(config?: CatalogConfig): CatalogResolverOptions;
33
+ export declare function resolveCatalog(options?: CatalogResolverOptions): Promise<ResolvedCatalog>;
34
+ export declare function fetchRemoteCatalog(remoteUrl: string, options?: CatalogResolverOptions): Promise<{
35
+ catalog: CatalogData;
36
+ signature?: CatalogSignature;
37
+ signatureVerified: boolean;
38
+ warnings: string[];
39
+ }>;
40
+ export declare function verifyCatalogSignature(catalog: CatalogData, signature: CatalogSignature, key: TrustedCatalogKey | CatalogTrustKeyConfig): boolean;
41
+ export declare function stableStringify(value: unknown): string;
@@ -0,0 +1,186 @@
1
+ import { createPublicKey, verify } from 'crypto';
2
+ import os from 'os';
3
+ import path from 'path';
4
+ import { promises as fs } from 'fs';
5
+ import { DEFAULT_APP_CATALOG } from './default-catalog.js';
6
+ import { isCatalogData } from './catalog.js';
7
+ export function resolveCatalogOptionsFromConfig(config) {
8
+ return {
9
+ remoteUrl: config?.url ?? process.env.AOTUI_APP_CATALOG_URL,
10
+ cachePath: config?.cachePath,
11
+ requireSignature: config?.requireSignature ?? false,
12
+ trustedKeys: (config?.trustedKeys ?? []).map((key) => ({
13
+ keyId: key.keyId,
14
+ algorithm: key.algorithm ?? 'ed25519',
15
+ publicKey: key.publicKey
16
+ }))
17
+ };
18
+ }
19
+ export async function resolveCatalog(options = {}) {
20
+ const remoteUrl = options.remoteUrl?.trim();
21
+ const cachePath = options.cachePath ?? getDefaultCatalogCachePath();
22
+ const warnings = [];
23
+ if (remoteUrl) {
24
+ try {
25
+ const remote = await fetchRemoteCatalog(remoteUrl, options);
26
+ await writeCatalogCache(cachePath, {
27
+ remoteUrl,
28
+ cachedAt: new Date().toISOString(),
29
+ signatureVerified: remote.signatureVerified,
30
+ catalog: remote.catalog,
31
+ signature: remote.signature
32
+ });
33
+ return {
34
+ source: 'remote',
35
+ catalog: remote.catalog,
36
+ remoteUrl,
37
+ cachedAt: new Date().toISOString(),
38
+ signatureVerified: remote.signatureVerified,
39
+ warnings: remote.warnings
40
+ };
41
+ }
42
+ catch (error) {
43
+ const message = error instanceof Error ? error.message : String(error);
44
+ warnings.push(`Remote catalog unavailable: ${message}`);
45
+ const cached = await readCatalogCache(cachePath);
46
+ if (cached) {
47
+ return {
48
+ source: 'cache',
49
+ catalog: cached.catalog,
50
+ remoteUrl: cached.remoteUrl,
51
+ cachedAt: cached.cachedAt,
52
+ signatureVerified: cached.signatureVerified,
53
+ warnings
54
+ };
55
+ }
56
+ }
57
+ }
58
+ return {
59
+ source: 'builtin',
60
+ catalog: DEFAULT_APP_CATALOG,
61
+ signatureVerified: false,
62
+ warnings
63
+ };
64
+ }
65
+ export async function fetchRemoteCatalog(remoteUrl, options = {}) {
66
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
67
+ if (!fetchImpl) {
68
+ throw new Error('Fetch API is not available in this runtime');
69
+ }
70
+ const response = await fetchImpl(remoteUrl, {
71
+ headers: {
72
+ accept: 'application/json'
73
+ }
74
+ });
75
+ if (!response.ok) {
76
+ throw new Error(`HTTP ${response.status} ${response.statusText}`.trim());
77
+ }
78
+ const json = await response.json();
79
+ const envelope = normalizeEnvelope(json);
80
+ const trustedKeys = options.trustedKeys ?? [];
81
+ const requireSignature = options.requireSignature ?? false;
82
+ const warnings = [];
83
+ let signatureVerified = false;
84
+ if (envelope.signature) {
85
+ if (envelope.signature.algorithm && envelope.signature.algorithm !== 'ed25519') {
86
+ throw new Error(`Unsupported catalog signature algorithm: ${envelope.signature.algorithm}`);
87
+ }
88
+ const key = trustedKeys.find((item) => item.keyId === envelope.signature?.keyId);
89
+ if (!key) {
90
+ if (requireSignature || trustedKeys.length > 0) {
91
+ throw new Error(`Missing trusted key for catalog signature: ${envelope.signature.keyId}`);
92
+ }
93
+ warnings.push(`Catalog signature present but key "${envelope.signature.keyId}" is not configured as trusted.`);
94
+ }
95
+ else {
96
+ const verified = verifyCatalogSignature(envelope.catalog, envelope.signature, key);
97
+ if (!verified) {
98
+ throw new Error(`Catalog signature verification failed for key "${envelope.signature.keyId}"`);
99
+ }
100
+ signatureVerified = true;
101
+ }
102
+ }
103
+ else if (requireSignature || trustedKeys.length > 0) {
104
+ throw new Error('Remote catalog is unsigned, but signature verification is required');
105
+ }
106
+ return {
107
+ catalog: envelope.catalog,
108
+ signature: envelope.signature,
109
+ signatureVerified,
110
+ warnings
111
+ };
112
+ }
113
+ export function verifyCatalogSignature(catalog, signature, key) {
114
+ const normalizedAlgorithm = key.algorithm ?? 'ed25519';
115
+ if (normalizedAlgorithm !== 'ed25519') {
116
+ throw new Error(`Unsupported trusted key algorithm: ${normalizedAlgorithm}`);
117
+ }
118
+ const publicKey = createPublicKey(key.publicKey);
119
+ const payload = Buffer.from(stableStringify(catalog), 'utf-8');
120
+ const signatureBytes = Buffer.from(signature.value, 'base64');
121
+ return verify(null, payload, publicKey, signatureBytes);
122
+ }
123
+ export function stableStringify(value) {
124
+ if (Array.isArray(value)) {
125
+ return `[${value.map((item) => stableStringify(item)).join(',')}]`;
126
+ }
127
+ if (value && typeof value === 'object') {
128
+ const entries = Object.entries(value)
129
+ .filter(([, entryValue]) => entryValue !== undefined)
130
+ .sort(([left], [right]) => left.localeCompare(right));
131
+ return `{${entries.map(([key, entryValue]) => `${JSON.stringify(key)}:${stableStringify(entryValue)}`).join(',')}}`;
132
+ }
133
+ return JSON.stringify(value);
134
+ }
135
+ function normalizeEnvelope(value) {
136
+ if (isCatalogData(value)) {
137
+ return { catalog: value };
138
+ }
139
+ if (typeof value !== 'object' || value === null) {
140
+ throw new Error('Catalog response is not a valid JSON object');
141
+ }
142
+ const envelope = value;
143
+ if (!isCatalogData(envelope.catalog)) {
144
+ throw new Error('Catalog response does not include a valid "catalog" payload');
145
+ }
146
+ if (envelope.signature !== undefined) {
147
+ if (typeof envelope.signature !== 'object' || envelope.signature === null) {
148
+ throw new Error('Catalog signature must be an object');
149
+ }
150
+ const signature = envelope.signature;
151
+ if (typeof signature.keyId !== 'string' || typeof signature.value !== 'string') {
152
+ throw new Error('Catalog signature is missing keyId or value');
153
+ }
154
+ if (signature.algorithm !== undefined && signature.algorithm !== 'ed25519') {
155
+ throw new Error(`Unsupported catalog signature algorithm: ${signature.algorithm}`);
156
+ }
157
+ }
158
+ return envelope;
159
+ }
160
+ function getDefaultCatalogCachePath() {
161
+ return path.join(os.homedir(), '.agentina', 'cache', 'app-catalog.json');
162
+ }
163
+ async function readCatalogCache(cachePath) {
164
+ try {
165
+ const content = await fs.readFile(cachePath, 'utf-8');
166
+ const cached = JSON.parse(content);
167
+ if (!isCatalogData(cached.catalog)) {
168
+ return null;
169
+ }
170
+ if (typeof cached.remoteUrl !== 'string' || typeof cached.cachedAt !== 'string' || typeof cached.signatureVerified !== 'boolean') {
171
+ return null;
172
+ }
173
+ return cached;
174
+ }
175
+ catch (error) {
176
+ if (error?.code === 'ENOENT') {
177
+ return null;
178
+ }
179
+ throw error;
180
+ }
181
+ }
182
+ async function writeCatalogCache(cachePath, record) {
183
+ await fs.mkdir(path.dirname(cachePath), { recursive: true });
184
+ await fs.writeFile(cachePath, JSON.stringify(record, null, 2), 'utf-8');
185
+ }
186
+ //# sourceMappingURL=catalog-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-resolver.js","sourceRoot":"","sources":["../../src/cli/catalog-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type CatalogAppEntry, type CatalogData } from './default-catalog.js';
2
+ export interface CatalogSearchResult extends CatalogAppEntry {
3
+ score: number;
4
+ }
5
+ export declare function isCatalogData(value: unknown): value is CatalogData;
6
+ export declare function searchCatalog(query: string | undefined, catalog?: CatalogData): CatalogSearchResult[];
@@ -0,0 +1,55 @@
1
+ import { DEFAULT_APP_CATALOG } from './default-catalog.js';
2
+ export function isCatalogData(value) {
3
+ if (typeof value !== 'object' || value === null) {
4
+ return false;
5
+ }
6
+ const candidate = value;
7
+ if (typeof candidate.version !== 'number' || typeof candidate.updatedAt !== 'string' || !Array.isArray(candidate.apps)) {
8
+ return false;
9
+ }
10
+ return candidate.apps.every((app) => (typeof app === 'object'
11
+ && app !== null
12
+ && typeof app.id === 'string'
13
+ && typeof app.name === 'string'
14
+ && typeof app.packageName === 'string'
15
+ && typeof app.description === 'string'
16
+ && typeof app.latestVersion === 'string'
17
+ && (app.keywords === undefined || Array.isArray(app.keywords))
18
+ && (app.homepage === undefined || typeof app.homepage === 'string')));
19
+ }
20
+ export function searchCatalog(query, catalog = DEFAULT_APP_CATALOG) {
21
+ const normalized = (query ?? '').trim().toLowerCase();
22
+ if (!normalized) {
23
+ return catalog.apps.map((app) => ({ ...app, score: 1 }));
24
+ }
25
+ const matches = catalog.apps
26
+ .map((app) => {
27
+ const haystacks = [
28
+ app.id,
29
+ app.name,
30
+ app.packageName,
31
+ app.description,
32
+ ...(app.keywords ?? [])
33
+ ].map((item) => item.toLowerCase());
34
+ const contains = haystacks.some((item) => item.includes(normalized));
35
+ if (!contains) {
36
+ return null;
37
+ }
38
+ let score = 10;
39
+ if (app.packageName.toLowerCase() === normalized)
40
+ score += 30;
41
+ if (app.id.toLowerCase() === normalized)
42
+ score += 20;
43
+ if (app.name.toLowerCase() === normalized)
44
+ score += 15;
45
+ if (app.packageName.toLowerCase().includes(normalized))
46
+ score += 8;
47
+ if ((app.keywords ?? []).some((k) => k.toLowerCase() === normalized))
48
+ score += 5;
49
+ return { ...app, score };
50
+ })
51
+ .filter((app) => app !== null)
52
+ .sort((a, b) => b.score - a.score || a.packageName.localeCompare(b.packageName));
53
+ return matches;
54
+ }
55
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/cli/catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface CatalogAppEntry {
2
+ id: string;
3
+ name: string;
4
+ packageName: string;
5
+ description: string;
6
+ latestVersion: string;
7
+ keywords?: string[];
8
+ homepage?: string;
9
+ }
10
+ export interface CatalogData {
11
+ version: number;
12
+ updatedAt: string;
13
+ apps: CatalogAppEntry[];
14
+ }
15
+ export declare const DEFAULT_APP_CATALOG: CatalogData;
@@ -0,0 +1,39 @@
1
+ export const DEFAULT_APP_CATALOG = {
2
+ version: 1,
3
+ updatedAt: '2026-03-06T00:00:00.000Z',
4
+ apps: [
5
+ {
6
+ id: 'system-terminal',
7
+ name: 'Terminal',
8
+ packageName: '@aotui/system-terminal',
9
+ description: 'Multi-terminal command execution app for agent workflows.',
10
+ latestVersion: '0.1.0',
11
+ keywords: ['terminal', 'shell', 'command', 'tools']
12
+ },
13
+ {
14
+ id: 'system-planning',
15
+ name: 'Planning App',
16
+ packageName: '@aotui/system-planning',
17
+ description: 'Create plans, phases, and todos for long-running tasks.',
18
+ latestVersion: '0.1.0',
19
+ keywords: ['planning', 'todo', 'project', 'task']
20
+ },
21
+ {
22
+ id: 'system-lite-browser',
23
+ name: 'Lite Browser',
24
+ packageName: '@aotui/system-lite-browser',
25
+ description: 'Lightweight browser with page extraction for agents.',
26
+ latestVersion: '0.1.0',
27
+ keywords: ['browser', 'web', 'search', 'crawl']
28
+ },
29
+ {
30
+ id: 'system-token-monitor',
31
+ name: 'Token Monitor',
32
+ packageName: '@aotui/system-token-monitor',
33
+ description: 'Observe token usage and budget in AOTUI sessions.',
34
+ latestVersion: '0.1.0',
35
+ keywords: ['token', 'monitor', 'budget', 'usage']
36
+ }
37
+ ]
38
+ };
39
+ //# sourceMappingURL=default-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-catalog.js","sourceRoot":"","sources":["../../src/cli/default-catalog.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,MAAM,mBAAmB,GAAgB;IAC5C,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,0BAA0B;IACrC,IAAI,EAAE;QACF;YACI,EAAE,EAAE,iBAAiB;YACrB,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,wBAAwB;YACrC,WAAW,EAAE,2DAA2D;YACxE,aAAa,EAAE,OAAO;YACtB,QAAQ,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC;SACtD;QACD;YACI,EAAE,EAAE,iBAAiB;YACrB,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,wBAAwB;YACrC,WAAW,EAAE,yDAAyD;YACtE,aAAa,EAAE,OAAO;YACtB,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC;SACpD;QACD;YACI,EAAE,EAAE,qBAAqB;YACzB,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,4BAA4B;YACzC,WAAW,EAAE,sDAAsD;YACnE,aAAa,EAAE,OAAO;YACtB,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC;SAClD;QACD;YACI,EAAE,EAAE,sBAAsB;YAC1B,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,6BAA6B;YAC1C,WAAW,EAAE,mDAAmD;YAChE,aAAa,EAAE,OAAO;YACtB,QAAQ,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC;SACpD;KACJ;CACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface NpmInstallOptions {
2
+ cacheRoot?: string;
3
+ forceReinstall?: boolean;
4
+ npmBinary?: string;
5
+ commandRunner?: (command: string, args: string[], cwd: string) => Promise<void>;
6
+ }
7
+ export interface NpmInstallResult {
8
+ packageName: string;
9
+ packageSpec: string;
10
+ requestedVersion: string | null;
11
+ resolvedVersion: string | null;
12
+ installRoot: string;
13
+ installedPath: string;
14
+ localSource: string;
15
+ }
16
+ export declare function installNpmPackage(packageInput: string, options?: NpmInstallOptions): Promise<NpmInstallResult>;
@@ -0,0 +1,88 @@
1
+ import path from 'path';
2
+ import os from 'os';
3
+ import fs from 'fs';
4
+ import fsp from 'fs/promises';
5
+ import { execFile as nodeExecFile } from 'child_process';
6
+ import { promisify } from 'util';
7
+ import { parseNpmSpecifier } from './sources.js';
8
+ const execFile = promisify(nodeExecFile);
9
+ export async function installNpmPackage(packageInput, options) {
10
+ const parsed = parseNpmSpecifier(packageInput);
11
+ const cacheRoot = options?.cacheRoot ?? getDefaultAppCacheRoot();
12
+ const npmBinary = options?.npmBinary ?? 'npm';
13
+ const requestedVersion = parsed.version;
14
+ const versionSegment = sanitizeSegment(parsed.version ?? 'latest');
15
+ const packageSegment = sanitizePackageName(parsed.packageName);
16
+ const installRoot = path.join(cacheRoot, packageSegment, versionSegment);
17
+ await fsp.mkdir(installRoot, { recursive: true });
18
+ await ensureInstallWorkspace(installRoot);
19
+ const installedPath = path.join(installRoot, 'node_modules', parsed.packageName);
20
+ const alreadyInstalled = fs.existsSync(installedPath);
21
+ if (!alreadyInstalled || options?.forceReinstall) {
22
+ await runInstallCommand(npmBinary, ['install', '--no-save', '--omit=dev', '--ignore-scripts', parsed.packageSpec], installRoot, options?.commandRunner);
23
+ }
24
+ if (!fs.existsSync(installedPath)) {
25
+ throw new Error(`Package install succeeded but app path was not found: ${installedPath}`);
26
+ }
27
+ const resolvedVersion = await readPackageVersion(installedPath);
28
+ return {
29
+ packageName: parsed.packageName,
30
+ packageSpec: parsed.packageSpec,
31
+ requestedVersion,
32
+ resolvedVersion,
33
+ installRoot,
34
+ installedPath,
35
+ localSource: `local:${installedPath}`
36
+ };
37
+ }
38
+ function getDefaultAppCacheRoot() {
39
+ return path.join(os.homedir(), '.agentina', 'apps', 'npm');
40
+ }
41
+ async function ensureInstallWorkspace(workspaceRoot) {
42
+ const packageJsonPath = path.join(workspaceRoot, 'package.json');
43
+ if (fs.existsSync(packageJsonPath)) {
44
+ return;
45
+ }
46
+ await fsp.writeFile(packageJsonPath, JSON.stringify({
47
+ name: 'agentina-app-cache',
48
+ private: true
49
+ }, null, 2), 'utf-8');
50
+ }
51
+ async function runInstallCommand(command, args, cwd, commandRunner) {
52
+ if (commandRunner) {
53
+ await commandRunner(command, args, cwd);
54
+ return;
55
+ }
56
+ try {
57
+ await execFile(command, args, { cwd });
58
+ }
59
+ catch (error) {
60
+ const stderr = error?.stderr ? String(error.stderr).trim() : '';
61
+ const reason = stderr ? `: ${stderr}` : '';
62
+ throw new Error(`Failed to install npm package with "${command} ${args.join(' ')}"${reason}`);
63
+ }
64
+ }
65
+ async function readPackageVersion(installedPath) {
66
+ const packageJsonPath = path.join(installedPath, 'package.json');
67
+ if (!fs.existsSync(packageJsonPath)) {
68
+ return null;
69
+ }
70
+ try {
71
+ const raw = await fsp.readFile(packageJsonPath, 'utf-8');
72
+ const json = JSON.parse(raw);
73
+ return typeof json.version === 'string' ? json.version : null;
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ }
79
+ function sanitizePackageName(value) {
80
+ return value
81
+ .replace(/^@/, 'scope-')
82
+ .replace(/[\\/]/g, '__')
83
+ .replace(/[^a-zA-Z0-9._-]/g, '_');
84
+ }
85
+ function sanitizeSegment(value) {
86
+ return value.replace(/[^a-zA-Z0-9._-]/g, '_');
87
+ }
88
+ //# sourceMappingURL=npm-installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm-installer.js","sourceRoot":"","sources":["../../src/cli/npm-installer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export interface NpmSpecifier {
2
+ packageName: string;
3
+ version: string | null;
4
+ packageSpec: string;
5
+ }
6
+ export type ParsedInstallSource = ParsedLocalSource | ParsedNpmSource;
7
+ export interface ParsedLocalSource {
8
+ kind: 'local';
9
+ source: string;
10
+ absolutePath: string;
11
+ }
12
+ export interface ParsedNpmSource {
13
+ kind: 'npm';
14
+ source: string;
15
+ packageName: string;
16
+ version: string | null;
17
+ packageSpec: string;
18
+ }
19
+ export declare function parseInstallSource(input: string, cwd?: string): ParsedInstallSource;
20
+ export declare function parseNpmSpecifier(raw: string): NpmSpecifier;
21
+ export declare function looksLikeLocalPath(value: string): boolean;
@@ -0,0 +1,131 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ import { fileURLToPath } from 'url';
5
+ export function parseInstallSource(input, cwd = process.cwd()) {
6
+ const value = input.trim();
7
+ if (!value) {
8
+ throw new Error('Install source is required');
9
+ }
10
+ if (value.startsWith('git:')) {
11
+ throw new Error('git source is not supported yet. Use npm package or local path');
12
+ }
13
+ if (value.startsWith('local:')) {
14
+ const localPath = value.slice('local:'.length);
15
+ return parseLocalSource(localPath, cwd);
16
+ }
17
+ if (value.startsWith('file://')) {
18
+ const absolutePath = fileURLToPath(value);
19
+ return {
20
+ kind: 'local',
21
+ source: `local:${absolutePath}`,
22
+ absolutePath
23
+ };
24
+ }
25
+ if (value.startsWith('npm:')) {
26
+ const npm = parseNpmSpecifier(value.slice('npm:'.length));
27
+ return {
28
+ kind: 'npm',
29
+ source: `npm:${npm.packageSpec}`,
30
+ packageName: npm.packageName,
31
+ version: npm.version,
32
+ packageSpec: npm.packageSpec
33
+ };
34
+ }
35
+ if (looksLikeLocalPath(value)) {
36
+ return parseLocalSource(value, cwd);
37
+ }
38
+ const npm = parseNpmSpecifier(value);
39
+ return {
40
+ kind: 'npm',
41
+ source: `npm:${npm.packageSpec}`,
42
+ packageName: npm.packageName,
43
+ version: npm.version,
44
+ packageSpec: npm.packageSpec
45
+ };
46
+ }
47
+ function parseLocalSource(localPathInput, cwd) {
48
+ const expanded = expandHomePath(localPathInput.trim());
49
+ const absolutePath = path.isAbsolute(expanded)
50
+ ? expanded
51
+ : path.resolve(cwd, expanded);
52
+ return {
53
+ kind: 'local',
54
+ source: `local:${absolutePath}`,
55
+ absolutePath
56
+ };
57
+ }
58
+ export function parseNpmSpecifier(raw) {
59
+ const spec = raw.trim();
60
+ if (!spec) {
61
+ throw new Error('npm package spec cannot be empty');
62
+ }
63
+ if (spec.startsWith('@')) {
64
+ const slashIndex = spec.indexOf('/');
65
+ if (slashIndex <= 1) {
66
+ throw new Error(`Invalid scoped npm package spec: ${raw}`);
67
+ }
68
+ const atAfterScope = spec.lastIndexOf('@');
69
+ if (atAfterScope > slashIndex) {
70
+ const packageName = spec.slice(0, atAfterScope);
71
+ const version = spec.slice(atAfterScope + 1);
72
+ validatePackageName(packageName, raw);
73
+ return {
74
+ packageName,
75
+ version: version || null,
76
+ packageSpec: version ? `${packageName}@${version}` : packageName
77
+ };
78
+ }
79
+ validatePackageName(spec, raw);
80
+ return {
81
+ packageName: spec,
82
+ version: null,
83
+ packageSpec: spec
84
+ };
85
+ }
86
+ const atIndex = spec.lastIndexOf('@');
87
+ if (atIndex > 0) {
88
+ const packageName = spec.slice(0, atIndex);
89
+ const version = spec.slice(atIndex + 1);
90
+ validatePackageName(packageName, raw);
91
+ return {
92
+ packageName,
93
+ version: version || null,
94
+ packageSpec: version ? `${packageName}@${version}` : packageName
95
+ };
96
+ }
97
+ validatePackageName(spec, raw);
98
+ return {
99
+ packageName: spec,
100
+ version: null,
101
+ packageSpec: spec
102
+ };
103
+ }
104
+ export function looksLikeLocalPath(value) {
105
+ if (!value)
106
+ return false;
107
+ if (value.startsWith('.') || value.startsWith('/') || value.startsWith('~'))
108
+ return true;
109
+ if (/^[a-zA-Z]:[\\/]/.test(value))
110
+ return true;
111
+ if (value.startsWith('file://'))
112
+ return true;
113
+ if (value.startsWith('@'))
114
+ return false;
115
+ if (fs.existsSync(value))
116
+ return true;
117
+ return false;
118
+ }
119
+ function expandHomePath(input) {
120
+ if (!input.startsWith('~')) {
121
+ return input;
122
+ }
123
+ return path.join(os.homedir(), input.slice(1));
124
+ }
125
+ function validatePackageName(name, raw) {
126
+ const npmNamePattern = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
127
+ if (!npmNamePattern.test(name)) {
128
+ throw new Error(`Invalid npm package name in spec "${raw}"`);
129
+ }
130
+ }
131
+ //# sourceMappingURL=sources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sources.js","sourceRoot":"","sources":["../../src/cli/sources.ts"],"names":[],"mappings":"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"}