stone-lang 0.1.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.
Files changed (68) hide show
  1. package/README.md +52 -0
  2. package/StoneEngine.js +879 -0
  3. package/StoneEngineService.js +1727 -0
  4. package/adapters/FileSystemAdapter.js +230 -0
  5. package/adapters/OutputAdapter.js +208 -0
  6. package/adapters/index.js +6 -0
  7. package/cli/CLIOutputAdapter.js +196 -0
  8. package/cli/DaemonClient.js +349 -0
  9. package/cli/JSONOutputAdapter.js +135 -0
  10. package/cli/ReplSession.js +567 -0
  11. package/cli/ViewerServer.js +590 -0
  12. package/cli/commands/check.js +84 -0
  13. package/cli/commands/daemon.js +189 -0
  14. package/cli/commands/kill.js +66 -0
  15. package/cli/commands/package.js +713 -0
  16. package/cli/commands/ps.js +65 -0
  17. package/cli/commands/run.js +537 -0
  18. package/cli/entry.js +169 -0
  19. package/cli/index.js +14 -0
  20. package/cli/stonec.js +358 -0
  21. package/cli/test-compiler.js +181 -0
  22. package/cli/viewer/index.html +495 -0
  23. package/daemon/IPCServer.js +455 -0
  24. package/daemon/ProcessManager.js +327 -0
  25. package/daemon/ProcessRunner.js +307 -0
  26. package/daemon/daemon.js +398 -0
  27. package/daemon/index.js +16 -0
  28. package/frontend/analysis/index.js +5 -0
  29. package/frontend/analysis/livenessAnalyzer.js +568 -0
  30. package/frontend/analysis/treeShaker.js +265 -0
  31. package/frontend/index.js +20 -0
  32. package/frontend/parsing/astBuilder.js +2196 -0
  33. package/frontend/parsing/index.js +7 -0
  34. package/frontend/parsing/sonParser.js +592 -0
  35. package/frontend/parsing/stoneAstTypes.js +703 -0
  36. package/frontend/parsing/terminal-registry.js +435 -0
  37. package/frontend/parsing/tokenizer.js +692 -0
  38. package/frontend/type-checker/OverloadedFunctionType.js +43 -0
  39. package/frontend/type-checker/TypeEnvironment.js +165 -0
  40. package/frontend/type-checker/bidirectionalInference.js +149 -0
  41. package/frontend/type-checker/index.js +10 -0
  42. package/frontend/type-checker/moduleAnalysis.js +248 -0
  43. package/frontend/type-checker/operatorMappings.js +35 -0
  44. package/frontend/type-checker/overloadResolution.js +605 -0
  45. package/frontend/type-checker/typeChecker.js +452 -0
  46. package/frontend/type-checker/typeCompatibility.js +389 -0
  47. package/frontend/type-checker/visitors/controlFlow.js +483 -0
  48. package/frontend/type-checker/visitors/functions.js +604 -0
  49. package/frontend/type-checker/visitors/index.js +38 -0
  50. package/frontend/type-checker/visitors/literals.js +341 -0
  51. package/frontend/type-checker/visitors/modules.js +159 -0
  52. package/frontend/type-checker/visitors/operators.js +109 -0
  53. package/frontend/type-checker/visitors/statements.js +768 -0
  54. package/frontend/types/index.js +5 -0
  55. package/frontend/types/operatorMap.js +134 -0
  56. package/frontend/types/types.js +2046 -0
  57. package/frontend/utils/errorCollector.js +244 -0
  58. package/frontend/utils/index.js +5 -0
  59. package/frontend/utils/moduleResolver.js +479 -0
  60. package/package.json +50 -0
  61. package/packages/browserCache.js +359 -0
  62. package/packages/fetcher.js +236 -0
  63. package/packages/index.js +130 -0
  64. package/packages/lockfile.js +271 -0
  65. package/packages/manifest.js +291 -0
  66. package/packages/packageResolver.js +356 -0
  67. package/packages/resolver.js +310 -0
  68. package/packages/semver.js +635 -0
@@ -0,0 +1,359 @@
1
+ /**
2
+ * Stone Browser Package Cache
3
+ *
4
+ * Manages package caching in the browser using IndexedDB.
5
+ * Packages are cached until logout.
6
+ */
7
+
8
+ const DB_NAME = 'stone-packages';
9
+ const DB_VERSION = 1;
10
+ const STORE_NAME = 'packages';
11
+
12
+ /**
13
+ * Open the IndexedDB database
14
+ */
15
+ function openDatabase() {
16
+ return new Promise((resolve, reject) => {
17
+ if (typeof indexedDB === 'undefined') {
18
+ reject(new Error('IndexedDB not available'));
19
+ return;
20
+ }
21
+
22
+ const request = indexedDB.open(DB_NAME, DB_VERSION);
23
+
24
+ request.onerror = () => reject(request.error);
25
+ request.onsuccess = () => resolve(request.result);
26
+
27
+ request.onupgradeneeded = (event) => {
28
+ const db = event.target.result;
29
+
30
+ if (!db.objectStoreNames.contains(STORE_NAME)) {
31
+ const store = db.createObjectStore(STORE_NAME, { keyPath: 'key' });
32
+ store.createIndex('name', 'name', { unique: false });
33
+ store.createIndex('version', 'version', { unique: false });
34
+ store.createIndex('timestamp', 'timestamp', { unique: false });
35
+ }
36
+ };
37
+ });
38
+ }
39
+
40
+ /**
41
+ * Browser Package Cache
42
+ */
43
+ export class BrowserPackageCache {
44
+ constructor() {
45
+ this.db = null;
46
+ this.memoryCache = new Map(); // In-memory fallback
47
+ }
48
+
49
+ /**
50
+ * Initialize the cache
51
+ */
52
+ async init() {
53
+ try {
54
+ this.db = await openDatabase();
55
+ } catch (e) {
56
+ // Fall back to memory cache
57
+ console.warn('IndexedDB not available, using memory cache');
58
+ this.db = null;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Generate cache key for a package
64
+ */
65
+ getKey(name, version) {
66
+ return `${name}@${version}`;
67
+ }
68
+
69
+ /**
70
+ * Check if a package is cached
71
+ */
72
+ async has(name, version) {
73
+ const key = this.getKey(name, version);
74
+
75
+ if (!this.db) {
76
+ return this.memoryCache.has(key);
77
+ }
78
+
79
+ return new Promise((resolve, reject) => {
80
+ const tx = this.db.transaction(STORE_NAME, 'readonly');
81
+ const store = tx.objectStore(STORE_NAME);
82
+ const request = store.get(key);
83
+
84
+ request.onerror = () => reject(request.error);
85
+ request.onsuccess = () => resolve(request.result !== undefined);
86
+ });
87
+ }
88
+
89
+ /**
90
+ * Get a cached package
91
+ */
92
+ async get(name, version) {
93
+ const key = this.getKey(name, version);
94
+
95
+ if (!this.db) {
96
+ return this.memoryCache.get(key) || null;
97
+ }
98
+
99
+ return new Promise((resolve, reject) => {
100
+ const tx = this.db.transaction(STORE_NAME, 'readonly');
101
+ const store = tx.objectStore(STORE_NAME);
102
+ const request = store.get(key);
103
+
104
+ request.onerror = () => reject(request.error);
105
+ request.onsuccess = () => resolve(request.result || null);
106
+ });
107
+ }
108
+
109
+ /**
110
+ * Cache a package
111
+ */
112
+ async set(name, version, data) {
113
+ const key = this.getKey(name, version);
114
+
115
+ const entry = {
116
+ key,
117
+ name,
118
+ version,
119
+ data,
120
+ timestamp: Date.now(),
121
+ };
122
+
123
+ if (!this.db) {
124
+ this.memoryCache.set(key, entry);
125
+ return;
126
+ }
127
+
128
+ return new Promise((resolve, reject) => {
129
+ const tx = this.db.transaction(STORE_NAME, 'readwrite');
130
+ const store = tx.objectStore(STORE_NAME);
131
+ const request = store.put(entry);
132
+
133
+ request.onerror = () => reject(request.error);
134
+ request.onsuccess = () => resolve();
135
+ });
136
+ }
137
+
138
+ /**
139
+ * Remove a package from cache
140
+ */
141
+ async delete(name, version) {
142
+ const key = this.getKey(name, version);
143
+
144
+ if (!this.db) {
145
+ this.memoryCache.delete(key);
146
+ return;
147
+ }
148
+
149
+ return new Promise((resolve, reject) => {
150
+ const tx = this.db.transaction(STORE_NAME, 'readwrite');
151
+ const store = tx.objectStore(STORE_NAME);
152
+ const request = store.delete(key);
153
+
154
+ request.onerror = () => reject(request.error);
155
+ request.onsuccess = () => resolve();
156
+ });
157
+ }
158
+
159
+ /**
160
+ * Clear all cached packages
161
+ */
162
+ async clear() {
163
+ if (!this.db) {
164
+ this.memoryCache.clear();
165
+ return;
166
+ }
167
+
168
+ return new Promise((resolve, reject) => {
169
+ const tx = this.db.transaction(STORE_NAME, 'readwrite');
170
+ const store = tx.objectStore(STORE_NAME);
171
+ const request = store.clear();
172
+
173
+ request.onerror = () => reject(request.error);
174
+ request.onsuccess = () => resolve();
175
+ });
176
+ }
177
+
178
+ /**
179
+ * List all cached packages
180
+ */
181
+ async list() {
182
+ if (!this.db) {
183
+ return Array.from(this.memoryCache.values()).map(e => ({
184
+ name: e.name,
185
+ version: e.version,
186
+ timestamp: e.timestamp,
187
+ }));
188
+ }
189
+
190
+ return new Promise((resolve, reject) => {
191
+ const tx = this.db.transaction(STORE_NAME, 'readonly');
192
+ const store = tx.objectStore(STORE_NAME);
193
+ const request = store.getAll();
194
+
195
+ request.onerror = () => reject(request.error);
196
+ request.onsuccess = () => {
197
+ const entries = request.result || [];
198
+ resolve(entries.map(e => ({
199
+ name: e.name,
200
+ version: e.version,
201
+ timestamp: e.timestamp,
202
+ })));
203
+ };
204
+ });
205
+ }
206
+
207
+ /**
208
+ * Get cache size in bytes (approximate)
209
+ */
210
+ async getSize() {
211
+ const packages = await this.list();
212
+ let size = 0;
213
+
214
+ for (const pkg of packages) {
215
+ const entry = await this.get(pkg.name, pkg.version);
216
+ if (entry && entry.data) {
217
+ size += JSON.stringify(entry.data).length;
218
+ }
219
+ }
220
+
221
+ return size;
222
+ }
223
+ }
224
+
225
+ /**
226
+ * Web Package Manager
227
+ *
228
+ * Manages package resolution and caching for web/Riva environment.
229
+ */
230
+ export class WebPackageManager {
231
+ constructor(options = {}) {
232
+ this.cache = new BrowserPackageCache();
233
+ this.fetcher = options.fetcher || null;
234
+
235
+ // User's global dependencies (from user account)
236
+ this.globalDeps = options.globalDeps || {};
237
+
238
+ // Virtual file system for resolved packages
239
+ this.virtualFS = new Map();
240
+ }
241
+
242
+ /**
243
+ * Initialize the package manager
244
+ */
245
+ async init() {
246
+ await this.cache.init();
247
+ }
248
+
249
+ /**
250
+ * Resolve and load all dependencies for a workspace
251
+ */
252
+ async loadDependencies(workspaceDeps = {}) {
253
+ // Merge global and workspace dependencies
254
+ const allDeps = { ...this.globalDeps, ...workspaceDeps };
255
+
256
+ const loaded = [];
257
+ const errors = [];
258
+
259
+ for (const [name, spec] of Object.entries(allDeps)) {
260
+ try {
261
+ await this.loadPackage(name, spec);
262
+ loaded.push(name);
263
+ } catch (e) {
264
+ errors.push({ name, error: e.message });
265
+ }
266
+ }
267
+
268
+ return { loaded, errors };
269
+ }
270
+
271
+ /**
272
+ * Load a single package
273
+ */
274
+ async loadPackage(name, spec) {
275
+ const version = typeof spec === 'string' ? spec : spec.version;
276
+ const source = typeof spec === 'object' ? spec.source : null;
277
+
278
+ // Check cache first
279
+ const cached = await this.cache.get(name, version);
280
+ if (cached) {
281
+ this.addToVirtualFS(name, cached.data);
282
+ return cached.data;
283
+ }
284
+
285
+ // Fetch package
286
+ if (!this.fetcher) {
287
+ throw new Error(`No fetcher configured for package: ${name}`);
288
+ }
289
+
290
+ const pkgData = await this.fetcher.fetchPackage(name, version, source);
291
+
292
+ // Cache it
293
+ await this.cache.set(name, version, pkgData);
294
+
295
+ // Add to virtual FS
296
+ this.addToVirtualFS(name, pkgData);
297
+
298
+ return pkgData;
299
+ }
300
+
301
+ /**
302
+ * Add package to virtual file system
303
+ */
304
+ addToVirtualFS(name, pkgData) {
305
+ const basePath = `stone_modules/${name}`;
306
+
307
+ if (pkgData.files) {
308
+ for (const [filename, content] of pkgData.files) {
309
+ this.virtualFS.set(`${basePath}/${filename}`, content);
310
+ }
311
+ }
312
+
313
+ if (pkgData.manifest) {
314
+ this.virtualFS.set(`${basePath}/package.son`, JSON.stringify(pkgData.manifest));
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Get a file from virtual FS
320
+ */
321
+ getFile(path) {
322
+ return this.virtualFS.get(path) || null;
323
+ }
324
+
325
+ /**
326
+ * Check if file exists in virtual FS
327
+ */
328
+ hasFile(path) {
329
+ return this.virtualFS.has(path);
330
+ }
331
+
332
+ /**
333
+ * Clear cache (call on logout)
334
+ */
335
+ async clearCache() {
336
+ await this.cache.clear();
337
+ this.virtualFS.clear();
338
+ }
339
+
340
+ /**
341
+ * Set global dependencies (from user account)
342
+ */
343
+ setGlobalDeps(deps) {
344
+ this.globalDeps = deps || {};
345
+ }
346
+ }
347
+
348
+ /**
349
+ * Create a web package manager
350
+ */
351
+ export function createWebPackageManager(options = {}) {
352
+ return new WebPackageManager(options);
353
+ }
354
+
355
+ export default {
356
+ BrowserPackageCache,
357
+ WebPackageManager,
358
+ createWebPackageManager,
359
+ };
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Stone Package Fetcher
3
+ *
4
+ * Fetches packages from HTTP sources and installs them locally.
5
+ * Handles downloading, extracting, and verification.
6
+ */
7
+
8
+ import { parseSON } from '../frontend/parsing/sonParser.js';
9
+
10
+ /**
11
+ * Fetch error
12
+ */
13
+ export class FetchError extends Error {
14
+ constructor(message, url = null, statusCode = null) {
15
+ super(message);
16
+ this.name = 'FetchError';
17
+ this.url = url;
18
+ this.statusCode = statusCode;
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Package Fetcher - Abstract base for different environments
24
+ */
25
+ export class PackageFetcher {
26
+ constructor(options = {}) {
27
+ // Base URL for package registry (if any)
28
+ this.registryUrl = options.registryUrl || null;
29
+
30
+ // Cache of fetched package info
31
+ this.cache = new Map();
32
+ }
33
+
34
+ /**
35
+ * Fetch package versions list from source
36
+ * @param {string} name - Package name
37
+ * @param {string} source - Source URL
38
+ * @returns {Promise<{versions: string[], source: string}>}
39
+ */
40
+ async fetchVersions(name, source) {
41
+ // Try to get versions.son from the source
42
+ const versionsUrl = this.resolveUrl(source || this.registryUrl, name, 'versions.son');
43
+
44
+ try {
45
+ const content = await this.fetchText(versionsUrl);
46
+ const data = parseSON(content, versionsUrl);
47
+
48
+ return {
49
+ versions: data.versions || [],
50
+ source: source || this.registryUrl,
51
+ };
52
+ } catch (e) {
53
+ // If versions.son doesn't exist, return empty
54
+ return { versions: [], source };
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Fetch a specific package version
60
+ * @param {string} name - Package name
61
+ * @param {string} version - Version to fetch
62
+ * @param {string} source - Source URL
63
+ * @returns {Promise<{files: Map<string, string>, manifest: object}>}
64
+ */
65
+ async fetchPackage(name, version, source) {
66
+ const packageUrl = this.resolveUrl(source, name, version);
67
+
68
+ // Fetch the package manifest first
69
+ const manifestUrl = `${packageUrl}/package.son`;
70
+ const manifestContent = await this.fetchText(manifestUrl);
71
+ const manifest = parseSON(manifestContent, manifestUrl);
72
+
73
+ // Fetch the file list
74
+ const filesUrl = `${packageUrl}/files.son`;
75
+ let fileList = [];
76
+
77
+ try {
78
+ const filesContent = await this.fetchText(filesUrl);
79
+ const filesData = parseSON(filesContent, filesUrl);
80
+ fileList = filesData.files || [];
81
+ } catch (e) {
82
+ // No files.son, try common files
83
+ fileList = ['main.stn'];
84
+ }
85
+
86
+ // Fetch each file
87
+ const files = new Map();
88
+ for (const file of fileList) {
89
+ const fileUrl = `${packageUrl}/${file}`;
90
+ try {
91
+ const content = await this.fetchText(fileUrl);
92
+ files.set(file, content);
93
+ } catch (e) {
94
+ // Skip missing files
95
+ }
96
+ }
97
+
98
+ return { files, manifest };
99
+ }
100
+
101
+ /**
102
+ * Resolve a URL for a package resource
103
+ */
104
+ resolveUrl(base, name, resource) {
105
+ if (!base) {
106
+ throw new FetchError(`No source URL specified for package: ${name}`);
107
+ }
108
+
109
+ // Ensure base doesn't end with /
110
+ base = base.replace(/\/+$/, '');
111
+
112
+ return `${base}/${name}/${resource}`;
113
+ }
114
+
115
+ /**
116
+ * Fetch text content from a URL (to be implemented by subclasses)
117
+ */
118
+ async fetchText(url) {
119
+ throw new Error('fetchText must be implemented by subclass');
120
+ }
121
+
122
+ /**
123
+ * Compute integrity hash for content
124
+ */
125
+ async computeHash(content) {
126
+ // Use SubtleCrypto if available (browser/modern Node)
127
+ if (typeof crypto !== 'undefined' && crypto.subtle) {
128
+ const encoder = new TextEncoder();
129
+ const data = encoder.encode(content);
130
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
131
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
132
+ return 'sha256-' + hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
133
+ }
134
+
135
+ // Fallback: no hashing
136
+ return null;
137
+ }
138
+
139
+ /**
140
+ * Verify integrity hash
141
+ */
142
+ async verifyIntegrity(content, expectedHash) {
143
+ if (!expectedHash) return true;
144
+
145
+ const actualHash = await this.computeHash(content);
146
+ if (!actualHash) return true; // Can't verify, skip
147
+
148
+ return actualHash === expectedHash;
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Node.js Package Fetcher - Uses native fetch or http module
154
+ */
155
+ export class NodePackageFetcher extends PackageFetcher {
156
+ async fetchText(url) {
157
+ // Use native fetch if available (Node 18+)
158
+ if (typeof fetch === 'function') {
159
+ const response = await fetch(url);
160
+
161
+ if (!response.ok) {
162
+ throw new FetchError(
163
+ `Failed to fetch ${url}: ${response.status} ${response.statusText}`,
164
+ url,
165
+ response.status
166
+ );
167
+ }
168
+
169
+ return await response.text();
170
+ }
171
+
172
+ // Fallback to Node's http/https modules
173
+ return new Promise((resolve, reject) => {
174
+ const protocol = url.startsWith('https') ? require('https') : require('http');
175
+
176
+ protocol.get(url, (res) => {
177
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
178
+ // Follow redirect
179
+ this.fetchText(res.headers.location).then(resolve).catch(reject);
180
+ return;
181
+ }
182
+
183
+ if (res.statusCode !== 200) {
184
+ reject(new FetchError(
185
+ `Failed to fetch ${url}: ${res.statusCode}`,
186
+ url,
187
+ res.statusCode
188
+ ));
189
+ return;
190
+ }
191
+
192
+ let data = '';
193
+ res.on('data', chunk => data += chunk);
194
+ res.on('end', () => resolve(data));
195
+ res.on('error', reject);
196
+ }).on('error', reject);
197
+ });
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Browser Package Fetcher - Uses fetch API
203
+ */
204
+ export class BrowserPackageFetcher extends PackageFetcher {
205
+ async fetchText(url) {
206
+ const response = await fetch(url);
207
+
208
+ if (!response.ok) {
209
+ throw new FetchError(
210
+ `Failed to fetch ${url}: ${response.status} ${response.statusText}`,
211
+ url,
212
+ response.status
213
+ );
214
+ }
215
+
216
+ return await response.text();
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Create the appropriate fetcher for the current environment
222
+ */
223
+ export function createFetcher(options = {}) {
224
+ if (typeof window !== 'undefined') {
225
+ return new BrowserPackageFetcher(options);
226
+ }
227
+ return new NodePackageFetcher(options);
228
+ }
229
+
230
+ export default {
231
+ PackageFetcher,
232
+ NodePackageFetcher,
233
+ BrowserPackageFetcher,
234
+ FetchError,
235
+ createFetcher,
236
+ };
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Stone Package System
3
+ *
4
+ * Main entry point for the Stone package management system.
5
+ * Exports all package-related functionality.
6
+ */
7
+
8
+ // SON Parser
9
+ export { parseSON, stringifySON, SONParseError } from '../frontend/parsing/sonParser.js';
10
+
11
+ // Semver
12
+ export {
13
+ SemVer,
14
+ SemVerError,
15
+ VersionRange,
16
+ parseVersion,
17
+ parseRange,
18
+ satisfies,
19
+ compare,
20
+ gt,
21
+ gte,
22
+ lt,
23
+ lte,
24
+ eq,
25
+ sort,
26
+ rsort,
27
+ maxSatisfying,
28
+ minSatisfying,
29
+ valid,
30
+ coerce,
31
+ } from './semver.js';
32
+
33
+ // Package Manifest
34
+ export {
35
+ PackageManifest,
36
+ ManifestError,
37
+ parseManifest,
38
+ createManifest,
39
+ stringifyManifest,
40
+ } from './manifest.js';
41
+
42
+ // Dependency Resolver
43
+ export {
44
+ DependencyResolver,
45
+ SimpleResolver,
46
+ ResolutionError,
47
+ checkCompatibility,
48
+ } from './resolver.js';
49
+
50
+ // Package Fetcher
51
+ export {
52
+ PackageFetcher,
53
+ NodePackageFetcher,
54
+ BrowserPackageFetcher,
55
+ FetchError,
56
+ createFetcher,
57
+ } from './fetcher.js';
58
+
59
+ // Lock File
60
+ export {
61
+ LockFile,
62
+ LockedPackage,
63
+ LockFileError,
64
+ parseLockFile,
65
+ stringifyLockFile,
66
+ checkLockFileStatus,
67
+ } from './lockfile.js';
68
+
69
+ // Package Resolution
70
+ export {
71
+ PackageContext,
72
+ createNodePackageContext,
73
+ createWebPackageContext,
74
+ getStoneHome,
75
+ } from './packageResolver.js';
76
+
77
+ // Browser Cache (web only)
78
+ export {
79
+ BrowserPackageCache,
80
+ WebPackageManager,
81
+ createWebPackageManager,
82
+ } from './browserCache.js';
83
+
84
+ /**
85
+ * Create a package manager instance with all components wired together
86
+ */
87
+ export function createPackageManager(options = {}) {
88
+ const fetcher = options.fetcher || (typeof window !== 'undefined'
89
+ ? new (require('./fetcher.js').BrowserPackageFetcher)(options)
90
+ : new (require('./fetcher.js').NodePackageFetcher)(options));
91
+
92
+ const resolver = new (require('./resolver.js').DependencyResolver)({
93
+ fetchVersions: (name, source) => fetcher.fetchVersions(name, source),
94
+ ...options,
95
+ });
96
+
97
+ return {
98
+ fetcher,
99
+ resolver,
100
+
101
+ /**
102
+ * Resolve dependencies from a manifest
103
+ */
104
+ async resolve(manifest) {
105
+ return resolver.resolve(manifest);
106
+ },
107
+
108
+ /**
109
+ * Fetch and install a package
110
+ */
111
+ async fetchPackage(name, version, source) {
112
+ return fetcher.fetchPackage(name, version, source);
113
+ },
114
+
115
+ /**
116
+ * Parse a package.son file
117
+ */
118
+ parseManifest: require('./manifest.js').parseManifest,
119
+
120
+ /**
121
+ * Parse a lock file
122
+ */
123
+ parseLockFile: require('./lockfile.js').parseLockFile,
124
+ };
125
+ }
126
+
127
+ export default {
128
+ // Re-export everything for convenient default import
129
+ createPackageManager,
130
+ };