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,356 @@
1
+ /**
2
+ * Stone Package-Aware Module Resolver
3
+ *
4
+ * Extends the base module resolver to support:
5
+ * - package.son project root detection
6
+ * - stone_modules resolution
7
+ * - Global ~/.stone/stone_modules fallback
8
+ */
9
+
10
+ import { parseSON } from '../frontend/parsing/sonParser.js';
11
+
12
+ // Platform-specific path utilities
13
+ const isWindows = typeof process !== 'undefined' && process.platform === 'win32';
14
+ const pathSep = isWindows ? '\\' : '/';
15
+
16
+ /**
17
+ * Normalize path separators
18
+ */
19
+ function normalizePath(p) {
20
+ if (!p) return p;
21
+ return p.replace(/[\\/]+/g, pathSep);
22
+ }
23
+
24
+ /**
25
+ * Join path segments
26
+ */
27
+ function joinPath(...segments) {
28
+ return segments.filter(Boolean).join(pathSep).replace(/[\\/]+/g, pathSep);
29
+ }
30
+
31
+ /**
32
+ * Get parent directory
33
+ */
34
+ function getParentDir(p) {
35
+ if (!p) return null;
36
+ const normalized = normalizePath(p);
37
+ const lastSep = normalized.lastIndexOf(pathSep);
38
+ if (lastSep <= 0) return null;
39
+ return normalized.substring(0, lastSep);
40
+ }
41
+
42
+ /**
43
+ * Check if path is at filesystem root
44
+ */
45
+ function isRoot(p) {
46
+ if (!p) return true;
47
+ const normalized = normalizePath(p);
48
+ // Unix root
49
+ if (normalized === '/') return true;
50
+ // Windows root (C:\)
51
+ if (/^[A-Za-z]:[\\/]?$/.test(normalized)) return true;
52
+ return false;
53
+ }
54
+
55
+ /**
56
+ * Get user home directory
57
+ */
58
+ function getHomeDir() {
59
+ if (typeof process !== 'undefined') {
60
+ return process.env.HOME || process.env.USERPROFILE || '';
61
+ }
62
+ return '';
63
+ }
64
+
65
+ /**
66
+ * Get global Stone directory (~/.stone)
67
+ */
68
+ function getStoneHome() {
69
+ // Check environment variable first
70
+ if (typeof process !== 'undefined' && process.env.STONE_HOME) {
71
+ return process.env.STONE_HOME;
72
+ }
73
+ // Default to ~/.stone
74
+ const home = getHomeDir();
75
+ if (home) {
76
+ return joinPath(home, '.stone');
77
+ }
78
+ return null;
79
+ }
80
+
81
+ /**
82
+ * Package Resolution Context
83
+ */
84
+ export class PackageContext {
85
+ constructor(options = {}) {
86
+ // File system access functions
87
+ this.fileExists = options.fileExists || (() => false);
88
+ this.readFile = options.readFile || (() => null);
89
+ this.listDir = options.listDir || (() => []);
90
+
91
+ // Cache
92
+ this.projectRootCache = new Map();
93
+ this.manifestCache = new Map();
94
+ this.resolvedModules = new Map();
95
+ }
96
+
97
+ /**
98
+ * Find project root by walking up to find package.son
99
+ * @param {string} startPath - Starting directory path
100
+ * @returns {string|null} Project root path or null
101
+ */
102
+ async findProjectRoot(startPath) {
103
+ if (!startPath) return null;
104
+
105
+ // Check cache
106
+ if (this.projectRootCache.has(startPath)) {
107
+ return this.projectRootCache.get(startPath);
108
+ }
109
+
110
+ let currentDir = normalizePath(startPath);
111
+
112
+ // Walk up until we find package.son or hit root
113
+ while (currentDir && !isRoot(currentDir)) {
114
+ const manifestPath = joinPath(currentDir, 'package.son');
115
+
116
+ if (await this.fileExists(manifestPath)) {
117
+ this.projectRootCache.set(startPath, currentDir);
118
+ return currentDir;
119
+ }
120
+
121
+ currentDir = getParentDir(currentDir);
122
+ }
123
+
124
+ // No package.son found
125
+ this.projectRootCache.set(startPath, null);
126
+ return null;
127
+ }
128
+
129
+ /**
130
+ * Get package manifest for a directory
131
+ */
132
+ async getManifest(dir) {
133
+ if (!dir) return null;
134
+
135
+ const manifestPath = joinPath(dir, 'package.son');
136
+
137
+ if (this.manifestCache.has(manifestPath)) {
138
+ return this.manifestCache.get(manifestPath);
139
+ }
140
+
141
+ try {
142
+ const content = await this.readFile(manifestPath);
143
+ if (!content) {
144
+ this.manifestCache.set(manifestPath, null);
145
+ return null;
146
+ }
147
+
148
+ const manifest = parseSON(content, manifestPath);
149
+ this.manifestCache.set(manifestPath, manifest);
150
+ return manifest;
151
+ } catch (e) {
152
+ this.manifestCache.set(manifestPath, null);
153
+ return null;
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Resolve a module from stone_modules
159
+ * @param {string} moduleName - Module name (not a path)
160
+ * @param {string} projectRoot - Project root directory
161
+ * @returns {string|null} Path to module's entry file
162
+ */
163
+ async resolveFromStoneModules(moduleName, projectRoot) {
164
+ if (!moduleName || !projectRoot) return null;
165
+
166
+ const stoneModulesDir = joinPath(projectRoot, 'stone_modules', moduleName);
167
+
168
+ // Check if module directory exists
169
+ const moduleManifestPath = joinPath(stoneModulesDir, 'package.son');
170
+ if (await this.fileExists(moduleManifestPath)) {
171
+ // Get entry point from manifest
172
+ const manifest = await this.getManifest(stoneModulesDir);
173
+ const entry = manifest?.entry || 'main.stn';
174
+ const entryPath = joinPath(stoneModulesDir, entry);
175
+
176
+ if (await this.fileExists(entryPath)) {
177
+ return entryPath;
178
+ }
179
+ }
180
+
181
+ // Try direct .stn file
182
+ const directPath = joinPath(projectRoot, 'stone_modules', `${moduleName}.stn`);
183
+ if (await this.fileExists(directPath)) {
184
+ return directPath;
185
+ }
186
+
187
+ // Try main.stn in directory without manifest
188
+ const mainPath = joinPath(stoneModulesDir, 'main.stn');
189
+ if (await this.fileExists(mainPath)) {
190
+ return mainPath;
191
+ }
192
+
193
+ return null;
194
+ }
195
+
196
+ /**
197
+ * Resolve from global stone_modules
198
+ */
199
+ async resolveFromGlobal(moduleName) {
200
+ const stoneHome = getStoneHome();
201
+ if (!stoneHome) return null;
202
+
203
+ return this.resolveFromStoneModules(moduleName, stoneHome);
204
+ }
205
+
206
+ /**
207
+ * Full module resolution
208
+ * @param {string} moduleName - Module name to resolve
209
+ * @param {string} fromPath - Path of the importing file
210
+ * @param {object} options - Resolution options
211
+ * @returns {string|null} Resolved module path
212
+ */
213
+ async resolveModule(moduleName, fromPath, options = {}) {
214
+ // Skip relative imports - handled by base resolver
215
+ if (moduleName.startsWith('./') || moduleName.startsWith('../')) {
216
+ return null; // Let base resolver handle it
217
+ }
218
+
219
+ // Skip built-ins (handled by base resolver)
220
+ if (options.isBuiltin?.(moduleName)) {
221
+ return null;
222
+ }
223
+
224
+ const cacheKey = `${fromPath}:${moduleName}`;
225
+ if (this.resolvedModules.has(cacheKey)) {
226
+ return this.resolvedModules.get(cacheKey);
227
+ }
228
+
229
+ // Find project root
230
+ const startDir = getParentDir(fromPath) || fromPath;
231
+ const projectRoot = await this.findProjectRoot(startDir);
232
+
233
+ // 1. Try local stone_modules (at project root)
234
+ if (projectRoot) {
235
+ const localPath = await this.resolveFromStoneModules(moduleName, projectRoot);
236
+ if (localPath) {
237
+ this.resolvedModules.set(cacheKey, localPath);
238
+ return localPath;
239
+ }
240
+ }
241
+
242
+ // 2. Try global stone_modules
243
+ const globalPath = await this.resolveFromGlobal(moduleName);
244
+ if (globalPath) {
245
+ this.resolvedModules.set(cacheKey, globalPath);
246
+ return globalPath;
247
+ }
248
+
249
+ this.resolvedModules.set(cacheKey, null);
250
+ return null;
251
+ }
252
+
253
+ /**
254
+ * Clear all caches
255
+ */
256
+ clearCache() {
257
+ this.projectRootCache.clear();
258
+ this.manifestCache.clear();
259
+ this.resolvedModules.clear();
260
+ }
261
+ }
262
+
263
+ /**
264
+ * Create a package context for Node.js environment
265
+ */
266
+ export async function createNodePackageContext() {
267
+ // Dynamic import for Node.js fs module
268
+ let fs, path;
269
+
270
+ try {
271
+ fs = await import('fs');
272
+ path = await import('path');
273
+ } catch (e) {
274
+ // Not in Node.js environment
275
+ return new PackageContext();
276
+ }
277
+
278
+ return new PackageContext({
279
+ fileExists: async (p) => {
280
+ try {
281
+ await fs.promises.access(p);
282
+ return true;
283
+ } catch {
284
+ return false;
285
+ }
286
+ },
287
+ readFile: async (p) => {
288
+ try {
289
+ return await fs.promises.readFile(p, 'utf8');
290
+ } catch {
291
+ return null;
292
+ }
293
+ },
294
+ listDir: async (p) => {
295
+ try {
296
+ return await fs.promises.readdir(p);
297
+ } catch {
298
+ return [];
299
+ }
300
+ },
301
+ });
302
+ }
303
+
304
+ /**
305
+ * Create a package context for web/Riva environment
306
+ */
307
+ export function createWebPackageContext(options = {}) {
308
+ // virtualFS should be a Map or object with file paths as keys
309
+ const virtualFS = options.virtualFS || new Map();
310
+ const fetchPackage = options.fetchPackage || (() => null);
311
+
312
+ return new PackageContext({
313
+ fileExists: async (p) => {
314
+ if (virtualFS instanceof Map) {
315
+ return virtualFS.has(p);
316
+ }
317
+ return p in virtualFS;
318
+ },
319
+ readFile: async (p) => {
320
+ if (virtualFS instanceof Map) {
321
+ return virtualFS.get(p) || null;
322
+ }
323
+ return virtualFS[p] || null;
324
+ },
325
+ listDir: async (p) => {
326
+ const prefix = p.endsWith('/') ? p : p + '/';
327
+ const files = [];
328
+
329
+ const entries = virtualFS instanceof Map
330
+ ? Array.from(virtualFS.keys())
331
+ : Object.keys(virtualFS);
332
+
333
+ for (const entry of entries) {
334
+ if (entry.startsWith(prefix)) {
335
+ const rest = entry.substring(prefix.length);
336
+ const nextSep = rest.indexOf('/');
337
+ const name = nextSep >= 0 ? rest.substring(0, nextSep) : rest;
338
+ if (name && !files.includes(name)) {
339
+ files.push(name);
340
+ }
341
+ }
342
+ }
343
+
344
+ return files;
345
+ },
346
+ });
347
+ }
348
+
349
+ export default {
350
+ PackageContext,
351
+ createNodePackageContext,
352
+ createWebPackageContext,
353
+ getStoneHome,
354
+ normalizePath,
355
+ joinPath,
356
+ };
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Stone Package Dependency Resolver
3
+ *
4
+ * Resolves package dependencies with version constraints.
5
+ * Builds dependency graph and finds compatible versions.
6
+ */
7
+
8
+ import { parseRange, satisfies, maxSatisfying, parseVersion } from './semver.js';
9
+
10
+ /**
11
+ * Resolution error
12
+ */
13
+ export class ResolutionError extends Error {
14
+ constructor(message, pkg = null, details = null) {
15
+ super(message);
16
+ this.name = 'ResolutionError';
17
+ this.package = pkg;
18
+ this.details = details;
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Dependency graph node
24
+ */
25
+ class DependencyNode {
26
+ constructor(name) {
27
+ this.name = name;
28
+ this.constraints = []; // Array of { range, source } where source is the dependent package
29
+ this.resolvedVersion = null;
30
+ this.dependencies = new Map(); // name -> DependencyNode
31
+ this.source = null; // URL source for fetching
32
+ }
33
+
34
+ addConstraint(range, source, packageSource = null) {
35
+ this.constraints.push({ range, source });
36
+ if (packageSource && !this.source) {
37
+ this.source = packageSource;
38
+ }
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Dependency Resolver
44
+ */
45
+ export class DependencyResolver {
46
+ constructor(options = {}) {
47
+ // Function to fetch available versions for a package
48
+ // Should return: { versions: string[], source?: string }
49
+ this.fetchVersions = options.fetchVersions || null;
50
+
51
+ // Cache of available versions per package
52
+ this.versionCache = new Map();
53
+
54
+ // The resolved dependency graph
55
+ this.graph = new Map();
56
+ }
57
+
58
+ /**
59
+ * Resolve dependencies starting from a root manifest
60
+ * @param {object} manifest - The root package manifest (parsed package.son)
61
+ * @returns {Map<string, ResolvedPackage>} Map of package name to resolved info
62
+ */
63
+ async resolve(manifest) {
64
+ // Clear previous state
65
+ this.graph.clear();
66
+
67
+ // Build the dependency graph
68
+ await this.buildGraph(manifest);
69
+
70
+ // Resolve versions for each package
71
+ const resolved = await this.resolveVersions();
72
+
73
+ return resolved;
74
+ }
75
+
76
+ /**
77
+ * Build the dependency graph from a manifest
78
+ */
79
+ async buildGraph(manifest, source = '<root>') {
80
+ const deps = this.normalizeDependencies(manifest.dependencies || {});
81
+
82
+ for (const [name, spec] of Object.entries(deps)) {
83
+ await this.addDependency(name, spec.version, source, spec.source);
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Add a dependency to the graph
89
+ */
90
+ async addDependency(name, versionRange, source, packageSource = null) {
91
+ // Get or create node
92
+ let node = this.graph.get(name);
93
+ if (!node) {
94
+ node = new DependencyNode(name);
95
+ this.graph.set(name, node);
96
+ }
97
+
98
+ // Add constraint
99
+ const range = parseRange(versionRange);
100
+ node.addConstraint(range, source, packageSource);
101
+
102
+ // If we have a version fetcher, get the package's dependencies too
103
+ if (this.fetchVersions && !node.resolvedVersion) {
104
+ try {
105
+ const pkgInfo = await this.getPackageInfo(name, packageSource);
106
+ if (pkgInfo && pkgInfo.dependencies) {
107
+ // Add transitive dependencies
108
+ const transDeps = this.normalizeDependencies(pkgInfo.dependencies);
109
+ for (const [depName, depSpec] of Object.entries(transDeps)) {
110
+ await this.addDependency(depName, depSpec.version, name, depSpec.source);
111
+ }
112
+ }
113
+ } catch (e) {
114
+ // Package info not available, continue without transitive deps
115
+ }
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Normalize dependencies to { version, source? } format
121
+ */
122
+ normalizeDependencies(deps) {
123
+ const result = {};
124
+ for (const [name, spec] of Object.entries(deps)) {
125
+ if (typeof spec === 'string') {
126
+ result[name] = { version: spec };
127
+ } else {
128
+ result[name] = { version: spec.version, source: spec.source };
129
+ }
130
+ }
131
+ return result;
132
+ }
133
+
134
+ /**
135
+ * Get package info (versions, dependencies) from cache or fetcher
136
+ */
137
+ async getPackageInfo(name, source = null) {
138
+ // Check cache
139
+ if (this.versionCache.has(name)) {
140
+ return this.versionCache.get(name);
141
+ }
142
+
143
+ // Fetch if we have a fetcher
144
+ if (this.fetchVersions) {
145
+ try {
146
+ const info = await this.fetchVersions(name, source);
147
+ this.versionCache.set(name, info);
148
+ return info;
149
+ } catch (e) {
150
+ throw new ResolutionError(`Failed to fetch versions for ${name}: ${e.message}`, name);
151
+ }
152
+ }
153
+
154
+ return null;
155
+ }
156
+
157
+ /**
158
+ * Resolve versions for all packages in the graph
159
+ */
160
+ async resolveVersions() {
161
+ const resolved = new Map();
162
+
163
+ for (const [name, node] of this.graph) {
164
+ const version = await this.resolvePackageVersion(name, node);
165
+
166
+ resolved.set(name, {
167
+ name,
168
+ version,
169
+ source: node.source,
170
+ constraints: node.constraints.map(c => ({
171
+ range: c.range.toString(),
172
+ source: c.source,
173
+ })),
174
+ });
175
+ }
176
+
177
+ return resolved;
178
+ }
179
+
180
+ /**
181
+ * Resolve a single package's version
182
+ */
183
+ async resolvePackageVersion(name, node) {
184
+ // Get available versions
185
+ const pkgInfo = await this.getPackageInfo(name, node.source);
186
+ const availableVersions = pkgInfo?.versions || [];
187
+
188
+ if (availableVersions.length === 0) {
189
+ // No versions available - check if constraints can be satisfied with any version
190
+ // For offline/local development, we might not have version info
191
+ throw new ResolutionError(
192
+ `No versions available for package: ${name}`,
193
+ name,
194
+ { constraints: node.constraints.map(c => ({ range: c.range.toString(), source: c.source })) }
195
+ );
196
+ }
197
+
198
+ // Find versions that satisfy ALL constraints
199
+ const satisfyingVersions = availableVersions.filter(v => {
200
+ return node.constraints.every(c => satisfies(v, c.range));
201
+ });
202
+
203
+ if (satisfyingVersions.length === 0) {
204
+ // No version satisfies all constraints - report conflict
205
+ const constraintDetails = node.constraints.map(c => ({
206
+ range: c.range.toString(),
207
+ source: c.source,
208
+ satisfying: availableVersions.filter(v => satisfies(v, c.range)),
209
+ }));
210
+
211
+ throw new ResolutionError(
212
+ `Cannot resolve ${name}: no version satisfies all constraints`,
213
+ name,
214
+ {
215
+ available: availableVersions,
216
+ constraints: constraintDetails,
217
+ }
218
+ );
219
+ }
220
+
221
+ // Return the highest satisfying version
222
+ return maxSatisfying(satisfyingVersions, '*');
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Simple resolver for when all versions are known upfront
228
+ */
229
+ export class SimpleResolver {
230
+ /**
231
+ * Resolve dependencies with known available versions
232
+ * @param {object} dependencies - Dependencies to resolve { name: versionRange }
233
+ * @param {object} availableVersions - Available versions { name: [versions] }
234
+ * @returns {object} Resolved versions { name: version }
235
+ */
236
+ static resolve(dependencies, availableVersions) {
237
+ const resolved = {};
238
+ const errors = [];
239
+
240
+ for (const [name, versionRange] of Object.entries(dependencies)) {
241
+ const range = typeof versionRange === 'string' ? versionRange : versionRange.version;
242
+ const available = availableVersions[name] || [];
243
+
244
+ if (available.length === 0) {
245
+ errors.push(`No versions available for: ${name}`);
246
+ continue;
247
+ }
248
+
249
+ const matching = maxSatisfying(available, range);
250
+ if (!matching) {
251
+ errors.push(`No version of ${name} satisfies ${range}. Available: ${available.join(', ')}`);
252
+ continue;
253
+ }
254
+
255
+ resolved[name] = matching;
256
+ }
257
+
258
+ if (errors.length > 0) {
259
+ throw new ResolutionError(
260
+ `Resolution failed:\n${errors.join('\n')}`,
261
+ null,
262
+ { errors }
263
+ );
264
+ }
265
+
266
+ return resolved;
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Check if a set of dependencies can be resolved together
272
+ * @param {object} dependencies - Map of package name to constraints
273
+ * @param {object} availableVersions - Map of package name to available versions
274
+ * @returns {object} { valid: boolean, conflicts?: [...] }
275
+ */
276
+ export function checkCompatibility(dependencies, availableVersions) {
277
+ const conflicts = [];
278
+
279
+ for (const [name, constraints] of Object.entries(dependencies)) {
280
+ const available = availableVersions[name] || [];
281
+
282
+ // Find versions that satisfy all constraints for this package
283
+ const constraintList = Array.isArray(constraints) ? constraints : [constraints];
284
+ const ranges = constraintList.map(c => parseRange(typeof c === 'string' ? c : c.range));
285
+
286
+ const satisfying = available.filter(v => {
287
+ return ranges.every(r => r.test(parseVersion(v)));
288
+ });
289
+
290
+ if (satisfying.length === 0) {
291
+ conflicts.push({
292
+ package: name,
293
+ constraints: constraintList,
294
+ available,
295
+ });
296
+ }
297
+ }
298
+
299
+ return {
300
+ valid: conflicts.length === 0,
301
+ conflicts,
302
+ };
303
+ }
304
+
305
+ export default {
306
+ DependencyResolver,
307
+ SimpleResolver,
308
+ ResolutionError,
309
+ checkCompatibility,
310
+ };