ic-mops 0.1.2 → 0.1.5

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/cli.js CHANGED
@@ -11,7 +11,7 @@ import {install} from './commands/install.js';
11
11
  import {publish} from './commands/publish.js';
12
12
  import {importPem} from './commands/import-identity.js';
13
13
  import {sources} from './commands/sources.js';
14
- import {getLastVersion, getNetwork, setNetwork} from './mops.js';
14
+ import {checkApiCompatibility, getMaxVersion, getNetwork, setNetwork} from './mops.js';
15
15
  import {whoami} from './commands/whoami.js';
16
16
  import {installAll} from './commands/install-all.js';
17
17
  import logUpdate from 'log-update';
@@ -55,12 +55,17 @@ program
55
55
  config.dependencies = {};
56
56
  }
57
57
 
58
+ let compatible = await checkApiCompatibility();
59
+ if (!compatible) {
60
+ return;
61
+ }
62
+
58
63
  if (!pkg) {
59
64
  installAll(options);
60
65
  }
61
66
  else {
62
- let version = await getLastVersion(pkg);
63
- await install(pkg, version, options.verbose);
67
+ let version = await getMaxVersion(pkg);
68
+ await install(pkg, version, {verbose: options.verbose});
64
69
 
65
70
  config.dependencies[pkg] = version;
66
71
  wirteConfig(config);
@@ -74,7 +79,10 @@ program
74
79
  .command('publish')
75
80
  .description('Publish package to the mops registry')
76
81
  .action(async () => {
77
- await publish();
82
+ let compatible = await checkApiCompatibility();
83
+ if (compatible) {
84
+ await publish();
85
+ }
78
86
  });
79
87
 
80
88
  // set-network
@@ -1,9 +1,11 @@
1
1
  import fs from 'fs';
2
2
  import chalk from 'chalk';
3
+ import path from 'path';
4
+ import {globalCacheDir} from '../mops.js';
3
5
 
4
6
  export async function importPem(data) {
5
7
  try {
6
- let url = new URL('../identity.pem', import.meta.url);
8
+ let url = new URL(path.resolve(globalCacheDir, 'identity.pem'), import.meta.url);
7
9
  fs.writeFileSync(url, data);
8
10
  console.log(chalk.green('Success'));
9
11
  }
@@ -12,7 +12,7 @@ export async function installAll({verbose} = {}) {
12
12
  let deps = Object.entries(config.dependencies || {});
13
13
 
14
14
  for (let [pkg, ver] of deps) {
15
- await install(pkg, ver, verbose);
15
+ await install(pkg, ver, {verbose});
16
16
  }
17
17
 
18
18
  logUpdate.clear();
@@ -1,16 +1,16 @@
1
1
  import path from 'path';
2
2
  import fs from 'fs';
3
3
  import logUpdate from 'log-update';
4
- import {checkConfigFile, getLastVersion, mainActor, progressBar, readConfig} from '../mops.js';
4
+ import {checkConfigFile, getMaxVersion, mainActor, progressBar, readConfig} from '../mops.js';
5
5
  import {parallel} from '../parallel.js';
6
6
 
7
- export async function install(pkg, version = '', verbose = false, dep = false) {
7
+ export async function install(pkg, version = '', {verbose, silent, dep} = {}) {
8
8
  if (!checkConfigFile()) {
9
9
  return;
10
10
  }
11
11
 
12
12
  if (!version) {
13
- version = await getLastVersion(pkg);
13
+ version = await getMaxVersion(pkg);
14
14
  }
15
15
 
16
16
  let dir = path.join(process.cwd(), '.mops', `${pkg}@${version}`);
@@ -18,12 +18,15 @@ export async function install(pkg, version = '', verbose = false, dep = false) {
18
18
 
19
19
  // cache
20
20
  if (fs.existsSync(dir)) {
21
- logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (cache)`);
21
+ silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (cache)`);
22
22
  }
23
23
  // no cache
24
24
  else {
25
25
  fs.mkdirSync(dir, {recursive: true});
26
26
 
27
+ if (!dep) {
28
+ actor.notifyInstall(pkg, version);
29
+ }
27
30
  let filesIds = await actor.getFileIds(pkg, version);
28
31
 
29
32
  // progress
@@ -31,7 +34,7 @@ export async function install(pkg, version = '', verbose = false, dep = false) {
31
34
  let step = 0;
32
35
  let progress = () => {
33
36
  step++;
34
- logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} ${progressBar(step, total)}`);
37
+ silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} ${progressBar(step, total)}`);
35
38
  };
36
39
 
37
40
  // download files
@@ -42,20 +45,15 @@ export async function install(pkg, version = '', verbose = false, dep = false) {
42
45
  fs.writeFileSync(path.join(dir, file.path), Buffer.from(file.content));
43
46
  progress();
44
47
  });
45
-
46
- // TODO: slow (update call)
47
- // if (!dep) {
48
- // await actor.notifyInstall(pkg, version);
49
- // }
50
48
  }
51
49
 
52
50
  if (verbose) {
53
- logUpdate.done();
51
+ silent || logUpdate.done();
54
52
  }
55
53
 
56
54
  // install dependencies
57
55
  let config = readConfig(path.join(dir, 'mops.toml'));
58
56
  for (let [name, version] of Object.entries(config.dependencies || {})) {
59
- await install(name, version, verbose, true);
57
+ await install(name, version, {verbose, silent, dep: true});
60
58
  }
61
59
  }
@@ -17,7 +17,7 @@ export async function publish() {
17
17
 
18
18
  // validate
19
19
  for (let key of Object.keys(config)) {
20
- if (!['package', 'dependencies', 'permissions', 'scripts'].includes(key)) {
20
+ if (!['package', 'dependencies', 'scripts'].includes(key)) {
21
21
  console.log(chalk.red('Error: ') + `Unknown config section [${key}]`);
22
22
  return;
23
23
  }
@@ -59,7 +59,6 @@ export async function publish() {
59
59
  'homepage',
60
60
  'readme',
61
61
  'license',
62
- 'isPrivate',
63
62
  'files',
64
63
  'dfx',
65
64
  'moc',
@@ -101,11 +100,6 @@ export async function publish() {
101
100
  return;
102
101
  }
103
102
 
104
- if (config.package.permissions && Object.keys(config.package.permissions).length > 50) {
105
- console.log(chalk.red('Error: ') + 'max permissions is 50');
106
- return;
107
- }
108
-
109
103
  if (config.package.keywords) {
110
104
  for (let keyword of config.package.keywords) {
111
105
  if (keyword.length > 20) {
@@ -135,7 +129,6 @@ export async function publish() {
135
129
  documentation: config.package.documentation || '',
136
130
  readme: 'README.md',
137
131
  license: config.package.license || '',
138
- isPrivate: false,
139
132
  owner: getIdentity()?.getPrincipal() || Principal.anonymous(),
140
133
  dfx: config.package.dfx || '',
141
134
  moc: config.package.moc || '',
@@ -143,7 +136,6 @@ export async function publish() {
143
136
  dependencies: (Object.entries(config.dependencies || {})).map(([name, version]) => {
144
137
  return {name, version};
145
138
  }),
146
- permissions: [],
147
139
  scripts: [],
148
140
  };
149
141
 
@@ -2,7 +2,7 @@ import path from 'path';
2
2
  import fs from 'fs';
3
3
  import chalk from 'chalk';
4
4
  import {install} from './install.js';
5
- import {getLastVersion, readConfig} from '../mops.js';
5
+ import {getMaxVersion, readConfig} from '../mops.js';
6
6
 
7
7
  function rootDir(cwd = process.cwd()) {
8
8
  let configFile = path.join(cwd, 'mops.toml');
@@ -73,8 +73,8 @@ export async function sources({verbose} = {}) {
73
73
  packages['base-unofficial'] = downloadedPackages['base-unofficial'];
74
74
  }
75
75
  else {
76
- let version = await getLastVersion('base-unofficial');
77
- await install('base-unofficial', version, false, true);
76
+ let version = await getMaxVersion('base-unofficial');
77
+ await install('base-unofficial', version, {silent: true, dep: true});
78
78
  packages['base-unofficial'] = version;
79
79
  }
80
80
  }
@@ -1,9 +1,10 @@
1
1
  import chalk from 'chalk';
2
2
  import fs from 'fs';
3
- import {getIdentity} from '../mops.js';
3
+ import path from 'path';
4
+ import {getIdentity, globalCacheDir} from '../mops.js';
4
5
 
5
6
  export function whoami() {
6
- let identityPem = new URL('../identity.pem', import.meta.url);
7
+ let identityPem = new URL(path.resolve(globalCacheDir, 'identity.pem'), import.meta.url);
7
8
  if (fs.existsSync(identityPem)) {
8
9
  let identity = getIdentity();
9
10
  console.log(identity.getPrincipal().toText());
@@ -18,18 +18,24 @@ type Result =
18
18
  };
19
19
  type PublishingId = text;
20
20
  type PublishingErr = text;
21
- type Permission =
22
- record {
23
- access: Access;
24
- user: principal;
25
- };
26
21
  type PackageSummary =
27
22
  record {
23
+ dependencies: vec Dependency;
28
24
  description: text;
25
+ dfx: text;
26
+ documentation: text;
27
+ donation: text;
29
28
  downloadsInLast30Days: nat;
30
29
  downloadsTotal: nat;
30
+ homepage: text;
31
31
  keywords: vec text;
32
+ license: text;
33
+ moc: text;
32
34
  name: PackageName;
35
+ owner: principal;
36
+ readme: text;
37
+ repository: text;
38
+ scripts: vec Script;
33
39
  updatedAt: Time;
34
40
  version: text;
35
41
  };
@@ -43,13 +49,10 @@ type PackageConfig =
43
49
  documentation: text;
44
50
  donation: text;
45
51
  homepage: text;
46
- isPrivate: bool;
47
52
  keywords: vec text;
48
53
  license: text;
49
54
  moc: text;
50
55
  name: PackageName;
51
- owner: principal;
52
- permissions: vec Permission;
53
56
  readme: text;
54
57
  repository: text;
55
58
  scripts: vec Script;
@@ -68,23 +71,18 @@ type Dependency =
68
71
  name: PackageName;
69
72
  version: text;
70
73
  };
71
- type Access =
72
- variant {
73
- readOnly;
74
- readWrite;
75
- };
76
74
  service : {
77
75
  finishPublish: (PublishingId) -> (Result);
76
+ getApiVersion: () -> (Text) query;
78
77
  getConfig: (PackageName__1, Version) -> (PackageConfig) query;
79
78
  getFile: (FileId) -> (File) query;
80
79
  getFileIds: (PackageName__1, Version) -> (vec FileId) query;
81
- getLastConfig: (PackageName__1) -> (PackageConfig) query;
82
- getLastVersion: (PackageName__1) -> (Version) query;
80
+ getMaxVersion: (PackageName__1) -> (Version) query;
81
+ getPackageSummary: (PackageName__1, Version) -> (PackageSummary) query;
83
82
  getReadmeFile: (PackageName__1, Version) -> (File) query;
84
83
  getRecentlyUpdatedPackages: () -> (vec PackageSummary) query;
85
84
  notifyInstall: (PackageName__1, Version) -> () oneway;
86
85
  search: (Text) -> (vec PackageSummary) query;
87
86
  startPublish: (PackageConfig) -> (Result_1);
88
87
  uploadFile: (PublishingId, Text, blob) -> (Result);
89
- whoami: () -> (Text) query;
90
88
  }
@@ -1,8 +1,6 @@
1
1
  import type { Principal } from '@dfinity/principal';
2
2
  import type { ActorMethod } from '@dfinity/agent';
3
3
 
4
- export type Access = { 'readOnly' : null } |
5
- { 'readWrite' : null };
6
4
  export interface Dependency { 'name' : PackageName, 'version' : string }
7
5
  export type Err = string;
8
6
  export interface File {
@@ -14,9 +12,7 @@ export type FileId = string;
14
12
  export interface PackageConfig {
15
13
  'dfx' : string,
16
14
  'moc' : string,
17
- 'permissions' : Array<Permission>,
18
15
  'scripts' : Array<Script>,
19
- 'owner' : Principal,
20
16
  'documentation' : string,
21
17
  'name' : PackageName,
22
18
  'homepage' : string,
@@ -24,7 +20,6 @@ export interface PackageConfig {
24
20
  'version' : string,
25
21
  'keywords' : Array<string>,
26
22
  'donation' : string,
27
- 'isPrivate' : boolean,
28
23
  'repository' : string,
29
24
  'dependencies' : Array<Dependency>,
30
25
  'license' : string,
@@ -33,15 +28,25 @@ export interface PackageConfig {
33
28
  export type PackageName = string;
34
29
  export type PackageName__1 = string;
35
30
  export interface PackageSummary {
31
+ 'dfx' : string,
32
+ 'moc' : string,
33
+ 'scripts' : Array<Script>,
34
+ 'owner' : Principal,
35
+ 'documentation' : string,
36
36
  'name' : PackageName,
37
+ 'homepage' : string,
37
38
  'downloadsTotal' : bigint,
38
39
  'downloadsInLast30Days' : bigint,
39
40
  'description' : string,
40
41
  'version' : string,
41
42
  'keywords' : Array<string>,
43
+ 'donation' : string,
42
44
  'updatedAt' : Time,
45
+ 'repository' : string,
46
+ 'dependencies' : Array<Dependency>,
47
+ 'license' : string,
48
+ 'readme' : string,
43
49
  }
44
- export interface Permission { 'access' : Access, 'user' : Principal }
45
50
  export type PublishingErr = string;
46
51
  export type PublishingId = string;
47
52
  export type Result = { 'ok' : null } |
@@ -54,16 +59,16 @@ export type Time = bigint;
54
59
  export type Version = string;
55
60
  export interface _SERVICE {
56
61
  'finishPublish' : ActorMethod<[PublishingId], Result>,
62
+ 'getApiVersion' : ActorMethod<[], Text>,
57
63
  'getConfig' : ActorMethod<[PackageName__1, Version], PackageConfig>,
58
64
  'getFile' : ActorMethod<[FileId], File>,
59
65
  'getFileIds' : ActorMethod<[PackageName__1, Version], Array<FileId>>,
60
- 'getLastConfig' : ActorMethod<[PackageName__1], PackageConfig>,
61
- 'getLastVersion' : ActorMethod<[PackageName__1], Version>,
66
+ 'getMaxVersion' : ActorMethod<[PackageName__1], Version>,
67
+ 'getPackageSummary' : ActorMethod<[PackageName__1, Version], PackageSummary>,
62
68
  'getReadmeFile' : ActorMethod<[PackageName__1, Version], File>,
63
69
  'getRecentlyUpdatedPackages' : ActorMethod<[], Array<PackageSummary>>,
64
70
  'notifyInstall' : ActorMethod<[PackageName__1, Version], undefined>,
65
71
  'search' : ActorMethod<[Text], Array<PackageSummary>>,
66
72
  'startPublish' : ActorMethod<[PackageConfig], Result_1>,
67
73
  'uploadFile' : ActorMethod<[PublishingId, Text, Array<number>], Result>,
68
- 'whoami' : ActorMethod<[], Text>,
69
74
  }
@@ -2,19 +2,16 @@ export const idlFactory = ({ IDL }) => {
2
2
  const PublishingId = IDL.Text;
3
3
  const Err = IDL.Text;
4
4
  const Result = IDL.Variant({ 'ok' : IDL.Null, 'err' : Err });
5
+ const Text = IDL.Text;
5
6
  const PackageName__1 = IDL.Text;
6
7
  const Version = IDL.Text;
7
- const Access = IDL.Variant({ 'readOnly' : IDL.Null, 'readWrite' : IDL.Null });
8
- const Permission = IDL.Record({ 'access' : Access, 'user' : IDL.Principal });
9
8
  const Script = IDL.Record({ 'value' : IDL.Text, 'name' : IDL.Text });
10
9
  const PackageName = IDL.Text;
11
10
  const Dependency = IDL.Record({ 'name' : PackageName, 'version' : IDL.Text });
12
11
  const PackageConfig = IDL.Record({
13
12
  'dfx' : IDL.Text,
14
13
  'moc' : IDL.Text,
15
- 'permissions' : IDL.Vec(Permission),
16
14
  'scripts' : IDL.Vec(Script),
17
- 'owner' : IDL.Principal,
18
15
  'documentation' : IDL.Text,
19
16
  'name' : PackageName,
20
17
  'homepage' : IDL.Text,
@@ -22,14 +19,12 @@ export const idlFactory = ({ IDL }) => {
22
19
  'version' : IDL.Text,
23
20
  'keywords' : IDL.Vec(IDL.Text),
24
21
  'donation' : IDL.Text,
25
- 'isPrivate' : IDL.Bool,
26
22
  'repository' : IDL.Text,
27
23
  'dependencies' : IDL.Vec(Dependency),
28
24
  'license' : IDL.Text,
29
25
  'readme' : IDL.Text,
30
26
  });
31
27
  const FileId = IDL.Text;
32
- const Text = IDL.Text;
33
28
  const File = IDL.Record({
34
29
  'id' : FileId,
35
30
  'content' : IDL.Vec(IDL.Nat8),
@@ -37,18 +32,30 @@ export const idlFactory = ({ IDL }) => {
37
32
  });
38
33
  const Time = IDL.Int;
39
34
  const PackageSummary = IDL.Record({
35
+ 'dfx' : IDL.Text,
36
+ 'moc' : IDL.Text,
37
+ 'scripts' : IDL.Vec(Script),
38
+ 'owner' : IDL.Principal,
39
+ 'documentation' : IDL.Text,
40
40
  'name' : PackageName,
41
+ 'homepage' : IDL.Text,
41
42
  'downloadsTotal' : IDL.Nat,
42
43
  'downloadsInLast30Days' : IDL.Nat,
43
44
  'description' : IDL.Text,
44
45
  'version' : IDL.Text,
45
46
  'keywords' : IDL.Vec(IDL.Text),
47
+ 'donation' : IDL.Text,
46
48
  'updatedAt' : Time,
49
+ 'repository' : IDL.Text,
50
+ 'dependencies' : IDL.Vec(Dependency),
51
+ 'license' : IDL.Text,
52
+ 'readme' : IDL.Text,
47
53
  });
48
54
  const PublishingErr = IDL.Text;
49
55
  const Result_1 = IDL.Variant({ 'ok' : PublishingId, 'err' : PublishingErr });
50
56
  return IDL.Service({
51
57
  'finishPublish' : IDL.Func([PublishingId], [Result], []),
58
+ 'getApiVersion' : IDL.Func([], [Text], ['query']),
52
59
  'getConfig' : IDL.Func(
53
60
  [PackageName__1, Version],
54
61
  [PackageConfig],
@@ -60,8 +67,12 @@ export const idlFactory = ({ IDL }) => {
60
67
  [IDL.Vec(FileId)],
61
68
  ['query'],
62
69
  ),
63
- 'getLastConfig' : IDL.Func([PackageName__1], [PackageConfig], ['query']),
64
- 'getLastVersion' : IDL.Func([PackageName__1], [Version], ['query']),
70
+ 'getMaxVersion' : IDL.Func([PackageName__1], [Version], ['query']),
71
+ 'getPackageSummary' : IDL.Func(
72
+ [PackageName__1, Version],
73
+ [PackageSummary],
74
+ ['query'],
75
+ ),
65
76
  'getReadmeFile' : IDL.Func([PackageName__1, Version], [File], ['query']),
66
77
  'getRecentlyUpdatedPackages' : IDL.Func(
67
78
  [],
@@ -76,7 +87,6 @@ export const idlFactory = ({ IDL }) => {
76
87
  [Result],
77
88
  [],
78
89
  ),
79
- 'whoami' : IDL.Func([], [Text], ['query']),
80
90
  });
81
91
  };
82
92
  export const init = ({ IDL }) => { return []; };
package/mops.js CHANGED
@@ -11,8 +11,13 @@ import {decodeFile} from './pem.js';
11
11
 
12
12
  global.fetch = fetch;
13
13
 
14
+ // (!) make changes in pair with backend
15
+ let apiVersion = '0.1';
16
+
14
17
  let networkFile = new URL('./network.txt', import.meta.url);
15
18
 
19
+ export let globalCacheDir = path.resolve(process.env.HOME || process.env.APPDATA, '.mops');
20
+
16
21
  export function setNetwork(network) {
17
22
  fs.writeFileSync(networkFile, network);
18
23
  }
@@ -41,7 +46,7 @@ export function getNetwork() {
41
46
  }
42
47
 
43
48
  export let getIdentity = () => {
44
- let identityPem = new URL('./identity.pem', import.meta.url);
49
+ let identityPem = new URL(path.resolve(globalCacheDir, 'identity.pem'), import.meta.url);
45
50
  if (fs.existsSync(identityPem)) {
46
51
  return decodeFile(identityPem);
47
52
  }
@@ -79,12 +84,31 @@ export function progressBar(step, total) {
79
84
  return `[${':'.repeat(done)}${' '.repeat(10 - done)}]`;
80
85
  }
81
86
 
82
- export async function getLastVersion(pkgName) {
87
+ export async function getMaxVersion(pkgName) {
83
88
  let actor = await mainActor();
84
- return actor.getLastVersion(pkgName);
89
+ return actor.getMaxVersion(pkgName);
85
90
  }
86
91
 
87
92
  export function readConfig(configFile = path.join(process.cwd(), 'mops.toml')) {
88
93
  let text = fs.readFileSync(configFile).toString();
89
94
  return TOML.parse(text);
95
+ }
96
+
97
+ // warn on minor mismatch
98
+ // err on major mismatch
99
+ export async function checkApiCompatibility() {
100
+ let actor = await mainActor();
101
+ let backendApiVer = await actor.getApiVersion();
102
+ if (backendApiVer.split('.')[0] !== apiVersion.split('.')[0]) {
103
+ console.log(chalk.red('ERR: ') + `CLI incompatible with backend. CLI v${apiVersion}, Backend v${backendApiVer}`);
104
+ console.log('Run ' + chalk.greenBright('npm i -g ic-mops') + ' to upgrade cli.');
105
+ return false;
106
+ }
107
+ else if (backendApiVer.split('.')[1] !== apiVersion.split('.')[1]) {
108
+ console.log('-'.repeat(50));
109
+ console.log(chalk.yellow('WARN: ') + `CLI probably incompatible with backend. CLI v${apiVersion}, Backend v${backendApiVer}`);
110
+ console.log('Recommended to run ' + chalk.greenBright('npm i -g ic-mops') + ' to upgrade cli.');
111
+ console.log('-'.repeat(50));
112
+ }
113
+ return true;
90
114
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ic-mops",
3
- "version": "0.1.2",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mops": "cli.js"