ic-mops 0.27.2 → 0.28.0-pre.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ic-mops",
3
- "version": "0.27.2",
3
+ "version": "0.28.0-pre.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mops": "dist/cli.js"
@@ -0,0 +1,3 @@
1
+ export declare function resolvePackages({ verbose }?: {
2
+ verbose?: boolean | undefined;
3
+ }): Promise<Record<string, string>>;
@@ -0,0 +1,108 @@
1
+ import path from 'node:path';
2
+ import chalk from 'chalk';
3
+ import { checkConfigFile, formatDir, formatGithubDir, getRootDir, parseGithubURL, readConfig } from './mops.js';
4
+ import { readVesselConfig } from './vessel.js';
5
+ export async function resolvePackages({ verbose = false } = {}) {
6
+ if (!checkConfigFile()) {
7
+ return {};
8
+ }
9
+ let packages = {};
10
+ let versions = {};
11
+ let compareVersions = (a = '0.0.0', b = '0.0.0') => {
12
+ let ap = a.split('.').map((x) => parseInt(x));
13
+ let bp = b.split('.').map((x) => parseInt(x));
14
+ if (ap[0] - bp[0]) {
15
+ return Math.sign(ap[0] - bp[0]);
16
+ }
17
+ if (ap[0] === bp[0] && ap[1] - bp[1]) {
18
+ return Math.sign(ap[1] - bp[1]);
19
+ }
20
+ if (ap[0] === bp[0] && ap[1] === bp[1] && ap[2] - bp[2]) {
21
+ return Math.sign(ap[2] - bp[2]);
22
+ }
23
+ return 0;
24
+ };
25
+ const gitVerRegex = new RegExp(/v(\d{1,2}\.\d{1,2}\.\d{1,2})(-.*)?$/);
26
+ const compareGitVersions = (repoA, repoB) => {
27
+ const { branch: a } = parseGithubURL(repoA);
28
+ const { branch: b } = parseGithubURL(repoB);
29
+ if (gitVerRegex.test(a) && gitVerRegex.test(b)) {
30
+ return compareVersions(a.substring(1), b.substring(1));
31
+ }
32
+ else if (!gitVerRegex.test(a)) {
33
+ return -1;
34
+ }
35
+ else {
36
+ return 1;
37
+ }
38
+ };
39
+ let collectDeps = async (config, isRoot = false) => {
40
+ let allDeps = [...Object.values(config.dependencies || {})];
41
+ if (isRoot) {
42
+ allDeps = [...allDeps, ...Object.values(config['dev-dependencies'] || {})];
43
+ }
44
+ for (const pkgDetails of allDeps) {
45
+ const { name, repo, version } = pkgDetails;
46
+ // take root dep version or bigger one
47
+ if (isRoot
48
+ || !packages[name]
49
+ || !packages[name]?.isRoot
50
+ && (repo && packages[name]?.repo && compareGitVersions(packages[name]?.repo || '', repo) === -1
51
+ || compareVersions(packages[name]?.version, version) === -1)) {
52
+ packages[name] = {
53
+ ...pkgDetails,
54
+ isRoot,
55
+ };
56
+ }
57
+ let nestedConfig;
58
+ if (repo) {
59
+ const dir = formatGithubDir(name, repo);
60
+ nestedConfig = await readVesselConfig(dir) || {};
61
+ }
62
+ else if (!pkgDetails.path && version) {
63
+ const file = formatDir(name, version) + '/mops.toml';
64
+ nestedConfig = readConfig(file);
65
+ }
66
+ if (nestedConfig && !pkgDetails.path) {
67
+ await collectDeps(nestedConfig);
68
+ }
69
+ if (!versions[name]) {
70
+ versions[name] = [];
71
+ }
72
+ if (repo) {
73
+ const { branch } = parseGithubURL(repo);
74
+ versions[name]?.push(branch);
75
+ }
76
+ else if (version) {
77
+ versions[name]?.push(version);
78
+ }
79
+ }
80
+ };
81
+ let config = readConfig();
82
+ await collectDeps(config, true);
83
+ // show conflicts
84
+ if (verbose) {
85
+ for (let [dep, vers] of Object.entries(versions)) {
86
+ if (vers.length > 1) {
87
+ console.log(chalk.yellow('WARN:'), `Conflicting package versions "${dep}" - ${vers.join(', ')}`);
88
+ }
89
+ }
90
+ }
91
+ let rootDir = getRootDir();
92
+ return Object.fromEntries(Object.entries(packages).map(([name, pkg]) => {
93
+ let version;
94
+ if (pkg.path) {
95
+ version = path.resolve(rootDir, pkg.path).replaceAll('{MOPS_ENV}', process.env.MOPS_ENV || 'local');
96
+ }
97
+ else if (pkg.repo) {
98
+ version = pkg.repo;
99
+ }
100
+ else if (pkg.version) {
101
+ version = pkg.version;
102
+ }
103
+ else {
104
+ return [name, ''];
105
+ }
106
+ return [name, version];
107
+ }).filter(([, version]) => version !== ''));
108
+ }
package/mops.ts CHANGED
@@ -221,6 +221,21 @@ export function parseGithubURL(href: string) {
221
221
  return {org, gitName, branch};
222
222
  }
223
223
 
224
+ export function getDependencyType(version: string) {
225
+ if (!version || typeof version !== 'string') {
226
+ throw Error(`Invalid dependency value "${version}"`);
227
+ }
228
+ if (version.startsWith('https://github.com/')) {
229
+ return 'github';
230
+ }
231
+ else if (version.match(/^(\.?\.)?\//)) {
232
+ return 'local';
233
+ }
234
+ else {
235
+ return 'mops';
236
+ }
237
+ }
238
+
224
239
  export function readConfig(configFile = getClosestConfigFile()): Config {
225
240
  let text = fs.readFileSync(configFile).toString();
226
241
  let toml = TOML.parse(text);
@@ -230,10 +245,11 @@ export function readConfig(configFile = getClosestConfigFile()): Config {
230
245
  if (!data || typeof data !== 'string') {
231
246
  throw Error(`Invalid dependency value ${name} = "${data}"`);
232
247
  }
233
- if (data.startsWith('https://github.com/')) {
248
+ let depType = getDependencyType(data);
249
+ if (depType === 'github') {
234
250
  deps[name] = {name, repo: data, version: ''};
235
251
  }
236
- else if (data.match(/^(\.?\.)?\//)) {
252
+ else if (depType === 'local') {
237
253
  deps[name] = {name, repo: '', path: data, version: ''};
238
254
  }
239
255
  else {
@@ -0,0 +1,9 @@
1
+ import {mainActor} from './mops.js';
2
+ import {resolvePackages} from './resolve-packages.js';
3
+
4
+ export async function notifyInstalls(names: string[]) {
5
+ let actor = await mainActor();
6
+ let resolvedPackages = await resolvePackages();
7
+ let packages: [string, string][] = names.map(name => [name, resolvedPackages[name] as string]);
8
+ actor.notifyInstalls(packages);
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ic-mops",
3
- "version": "0.27.2",
3
+ "version": "0.28.0-pre.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mops": "dist/cli.js"
@@ -0,0 +1,131 @@
1
+ import path from 'node:path';
2
+ import chalk from 'chalk';
3
+ import {checkConfigFile, formatDir, formatGithubDir, getRootDir, parseGithubURL, readConfig} from './mops.js';
4
+ import {VesselConfig, readVesselConfig} from './vessel.js';
5
+ import {Config, Dependency} from './types.js';
6
+
7
+ export async function resolvePackages({verbose = false} = {}): Promise<Record<string, string>> {
8
+ if (!checkConfigFile()) {
9
+ return {};
10
+ }
11
+
12
+ let packages: Record<string, Dependency & {isRoot: boolean;}> = {};
13
+ let versions: Record<string, string[]> = {};
14
+
15
+ let compareVersions = (a: string = '0.0.0', b: string = '0.0.0') => {
16
+ let ap = a.split('.').map((x: string) => parseInt(x)) as [number, number, number];
17
+ let bp = b.split('.').map((x: string) => parseInt(x)) as [number, number, number];
18
+ if (ap[0] - bp[0]) {
19
+ return Math.sign(ap[0] - bp[0]);
20
+ }
21
+ if (ap[0] === bp[0] && ap[1] - bp[1]) {
22
+ return Math.sign(ap[1] - bp[1]);
23
+ }
24
+ if (ap[0] === bp[0] && ap[1] === bp[1] && ap[2] - bp[2]) {
25
+ return Math.sign(ap[2] - bp[2]);
26
+ }
27
+ return 0;
28
+ };
29
+
30
+ const gitVerRegex = new RegExp(/v(\d{1,2}\.\d{1,2}\.\d{1,2})(-.*)?$/);
31
+
32
+ const compareGitVersions = (repoA: string, repoB: string) => {
33
+ const {branch: a} = parseGithubURL(repoA);
34
+ const {branch: b} = parseGithubURL(repoB);
35
+
36
+ if (gitVerRegex.test(a) && gitVerRegex.test(b)) {
37
+ return compareVersions(a.substring(1), b.substring(1));
38
+ }
39
+ else if (!gitVerRegex.test(a)) {
40
+ return -1;
41
+ }
42
+ else {
43
+ return 1;
44
+ }
45
+ };
46
+
47
+ let collectDeps = async (config: Config | VesselConfig, isRoot = false) => {
48
+ let allDeps = [...Object.values(config.dependencies || {})];
49
+ if (isRoot) {
50
+ allDeps = [...allDeps, ...Object.values(config['dev-dependencies'] || {})];
51
+ }
52
+ for (const pkgDetails of allDeps) {
53
+ const {name, repo, version} = pkgDetails;
54
+
55
+ // take root dep version or bigger one
56
+ if (
57
+ isRoot
58
+ || !packages[name]
59
+ || !packages[name]?.isRoot
60
+ && (
61
+ repo && packages[name]?.repo && compareGitVersions(packages[name]?.repo || '', repo) === -1
62
+ || compareVersions(packages[name]?.version, version) === -1)
63
+ ) {
64
+ packages[name] = {
65
+ ...pkgDetails,
66
+ isRoot,
67
+ };
68
+ }
69
+
70
+ let nestedConfig;
71
+
72
+ if (repo) {
73
+ const dir = formatGithubDir(name, repo);
74
+ nestedConfig = await readVesselConfig(dir) || {};
75
+ }
76
+ else if (!pkgDetails.path && version) {
77
+ const file = formatDir(name, version) + '/mops.toml';
78
+ nestedConfig = readConfig(file);
79
+ }
80
+
81
+ if (nestedConfig && !pkgDetails.path) {
82
+ await collectDeps(nestedConfig);
83
+ }
84
+
85
+ if (!versions[name]) {
86
+ versions[name] = [];
87
+ }
88
+
89
+ if (repo) {
90
+ const {branch} = parseGithubURL(repo);
91
+ versions[name]?.push(branch);
92
+ }
93
+ else if (version) {
94
+ versions[name]?.push(version);
95
+ }
96
+ }
97
+ };
98
+
99
+ let config = readConfig();
100
+ await collectDeps(config, true);
101
+
102
+ // show conflicts
103
+ if (verbose) {
104
+ for (let [dep, vers] of Object.entries(versions)) {
105
+ if (vers.length > 1) {
106
+ console.log(chalk.yellow('WARN:'), `Conflicting package versions "${dep}" - ${vers.join(', ')}`);
107
+ }
108
+ }
109
+ }
110
+
111
+ let rootDir = getRootDir();
112
+
113
+ return Object.fromEntries(
114
+ Object.entries(packages).map(([name, pkg]) => {
115
+ let version: string;
116
+ if (pkg.path) {
117
+ version = path.resolve(rootDir, pkg.path).replaceAll('{MOPS_ENV}', process.env.MOPS_ENV || 'local');
118
+ }
119
+ else if (pkg.repo) {
120
+ version = pkg.repo;
121
+ }
122
+ else if (pkg.version) {
123
+ version = pkg.version;
124
+ }
125
+ else {
126
+ return [name, ''];
127
+ }
128
+ return [name, version];
129
+ }).filter(([, version]) => version !== '')
130
+ );
131
+ }