ic-mops 0.1.4 → 0.1.7

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 {checkApiCompatibility, getMaxVersion, getNetwork, setNetwork} from './mops.js';
14
+ import {checkApiCompatibility, getHighestVersion, 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';
@@ -64,13 +64,13 @@ program
64
64
  installAll(options);
65
65
  }
66
66
  else {
67
- let version = await getMaxVersion(pkg);
67
+ let version = await getHighestVersion(pkg);
68
68
  await install(pkg, version, {verbose: options.verbose});
69
69
 
70
70
  config.dependencies[pkg] = version;
71
71
  wirteConfig(config);
72
72
  logUpdate.clear();
73
- console.log(chalk.green('Package installed ') + `${pkg} = '${version}'`);
73
+ console.log(chalk.green('Package installed ') + `${pkg} = "${version}"`);
74
74
  }
75
75
  });
76
76
 
@@ -1,10 +1,15 @@
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);
7
- fs.writeFileSync(url, data);
8
+ if (!fs.existsSync(globalCacheDir)) {
9
+ fs.mkdirSync(globalCacheDir);
10
+ }
11
+ let identityPem = path.resolve(globalCacheDir, 'identity.pem');
12
+ fs.writeFileSync(identityPem, data);
8
13
  console.log(chalk.green('Success'));
9
14
  }
10
15
  catch (err) {
@@ -1,8 +1,9 @@
1
1
  import path from 'path';
2
2
  import fs from 'fs';
3
3
  import logUpdate from 'log-update';
4
- import {checkConfigFile, getMaxVersion, mainActor, progressBar, readConfig} from '../mops.js';
4
+ import {checkConfigFile, getHighestVersion, mainActor, progressBar, readConfig, storageActor} from '../mops.js';
5
5
  import {parallel} from '../parallel.js';
6
+ import chalk from 'chalk';
6
7
 
7
8
  export async function install(pkg, version = '', {verbose, silent, dep} = {}) {
8
9
  if (!checkConfigFile()) {
@@ -10,7 +11,7 @@ export async function install(pkg, version = '', {verbose, silent, dep} = {}) {
10
11
  }
11
12
 
12
13
  if (!version) {
13
- version = await getMaxVersion(pkg);
14
+ version = await getHighestVersion(pkg);
14
15
  }
15
16
 
16
17
  let dir = path.join(process.cwd(), '.mops', `${pkg}@${version}`);
@@ -27,7 +28,9 @@ export async function install(pkg, version = '', {verbose, silent, dep} = {}) {
27
28
  if (!dep) {
28
29
  actor.notifyInstall(pkg, version);
29
30
  }
31
+ let packageDetails = await actor.getPackageDetails(pkg, version);
30
32
  let filesIds = await actor.getFileIds(pkg, version);
33
+ let storage = await storageActor(packageDetails.publication.storage);
31
34
 
32
35
  // progress
33
36
  let total = filesIds.length + 1;
@@ -40,9 +43,25 @@ export async function install(pkg, version = '', {verbose, silent, dep} = {}) {
40
43
  // download files
41
44
  progress();
42
45
  await parallel(8, filesIds, async (fileId) => {
43
- let file = await actor.getFile(fileId);
44
- fs.mkdirSync(path.join(dir, path.dirname(file.path)), {recursive: true});
45
- fs.writeFileSync(path.join(dir, file.path), Buffer.from(file.content));
46
+ let fileMetaRes = await storage.getFileMeta(fileId);
47
+ if (fileMetaRes.err) {
48
+ console.log(chalk.red('ERR: ') + fileMetaRes.err);
49
+ return;
50
+ }
51
+ let fileMeta = fileMetaRes.ok;
52
+
53
+ let chunks = Array(Number(fileMeta.chunkCount));
54
+ for (let i = 0; i < fileMeta.chunkCount; i++) {
55
+ let chunkRes = await storage.downloadChunk(fileId, i);
56
+ if (chunkRes.err) {
57
+ console.log(chalk.red('ERR: ') + chunkRes.err);
58
+ return;
59
+ }
60
+ chunks[i] = chunkRes.ok;
61
+ }
62
+
63
+ fs.mkdirSync(path.join(dir, path.dirname(fileMeta.path)), {recursive: true});
64
+ fs.writeFileSync(path.join(dir, fileMeta.path), Buffer.from(chunks.flat()));
46
65
  progress();
47
66
  });
48
67
  }
@@ -188,8 +188,28 @@ export async function publish() {
188
188
  // upload files
189
189
  await parallel(8, files, async (file) => {
190
190
  progress();
191
+
192
+ let chunkSize = 1024 * 1024 + 512 * 1024; // 1.5mb
191
193
  let content = fs.readFileSync(file);
192
- await actor.uploadFile(puiblishingId, file, Array.from(content));
194
+ let chunkCount = Math.ceil(content.length / chunkSize);
195
+ let firstChunk = Array.from(content.slice(0, chunkSize));
196
+
197
+ let res = await actor.startFileUpload(puiblishingId, file, chunkCount, firstChunk);
198
+ if (res.err) {
199
+ console.log(chalk.red('Error: ') + res.err);
200
+ return;
201
+ }
202
+ let fileId = res.ok;
203
+
204
+ for (let i = 1; i < chunkCount; i++) {
205
+ let start = i * chunkSize;
206
+ let chunk = Array.from(content.slice(start, start + chunkSize));
207
+ let res = await actor.uploadFileChunk(puiblishingId, fileId, i, chunk);
208
+ if (res.err) {
209
+ console.log(chalk.red('Error: ') + res.err);
210
+ return;
211
+ }
212
+ }
193
213
  });
194
214
 
195
215
  // finish
@@ -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 {getMaxVersion, readConfig} from '../mops.js';
5
+ import {getHighestVersion, readConfig} from '../mops.js';
6
6
 
7
7
  function rootDir(cwd = process.cwd()) {
8
8
  let configFile = path.join(cwd, 'mops.toml');
@@ -73,7 +73,7 @@ export async function sources({verbose} = {}) {
73
73
  packages['base-unofficial'] = downloadedPackages['base-unofficial'];
74
74
  }
75
75
  else {
76
- let version = await getMaxVersion('base-unofficial');
76
+ let version = await getHighestVersion('base-unofficial');
77
77
  await install('base-unofficial', version, {silent: true, dep: true});
78
78
  packages['base-unofficial'] = version;
79
79
  }
@@ -13,20 +13,20 @@ export async function uninstall(pkg, version) {
13
13
  let pkgDir = path.join(process.cwd(), '.mops', `${pkg}@${version}`);
14
14
 
15
15
  if (!fs.existsSync(pkgDir)) {
16
- console.log(`No cache to remove ${pkg} = '${version}'`);
16
+ console.log(`No cache to remove ${pkg} = "${version}"`);
17
17
  return;
18
18
  }
19
19
 
20
20
  // don't remove if there are dependents
21
21
  // let dependents = getDependents(pkg, version);
22
22
  // if (dependents.length) {
23
- // console.log(`Cache left ${pkg} = '${version}' (dependents: ${dependents})`)
23
+ // console.log(`Cache left ${pkg} = "${version}" (dependents: ${dependents})`)
24
24
  // return;
25
25
  // }
26
26
 
27
27
  del.sync([`${pkgDir}/**`]);
28
28
 
29
- console.log(chalk.green('Package removed ') + `${pkg} = '${version}'`);
29
+ console.log(chalk.green('Package removed ') + `${pkg} = "${version}"`);
30
30
 
31
31
  // remove dependencies
32
32
  // let text = fs.readFileSync(path.join(pkgDir, 'mops.toml')).toString();
@@ -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 = path.resolve(globalCacheDir, 'identity.pem');
7
8
  if (fs.existsSync(identityPem)) {
8
9
  let identity = getIdentity();
9
10
  console.log(identity.getPrincipal().toText());
@@ -1,11 +1,23 @@
1
1
  type Version = text;
2
2
  type Time = int;
3
3
  type Text = text;
4
+ type StorageStats =
5
+ record {
6
+ cyclesBalance: nat;
7
+ fileCount: nat;
8
+ memorySize: nat;
9
+ };
10
+ type StorageId = principal;
4
11
  type Script =
5
12
  record {
6
13
  name: text;
7
14
  value: text;
8
15
  };
16
+ type Result_2 =
17
+ variant {
18
+ err: Err;
19
+ ok: FileId;
20
+ };
9
21
  type Result_1 =
10
22
  variant {
11
23
  err: PublishingErr;
@@ -18,29 +30,39 @@ type Result =
18
30
  };
19
31
  type PublishingId = text;
20
32
  type PublishingErr = text;
21
- type PackageSummary =
33
+ type PackagePublication =
34
+ record {
35
+ storage: principal;
36
+ time: Time;
37
+ user: principal;
38
+ };
39
+ type PackageName__1 = text;
40
+ type PackageName = text;
41
+ type PackageDetails =
42
+ record {
43
+ config: PackageConfig__1;
44
+ downloadsInLast30Days: nat;
45
+ downloadsTotal: nat;
46
+ owner: principal;
47
+ publication: PackagePublication;
48
+ };
49
+ type PackageConfig__1 =
22
50
  record {
23
51
  dependencies: vec Dependency;
24
52
  description: text;
25
53
  dfx: text;
26
54
  documentation: text;
27
55
  donation: text;
28
- downloadsInLast30Days: nat;
29
- downloadsTotal: nat;
30
56
  homepage: text;
31
57
  keywords: vec text;
32
58
  license: text;
33
59
  moc: text;
34
60
  name: PackageName;
35
- owner: principal;
36
61
  readme: text;
37
62
  repository: text;
38
63
  scripts: vec Script;
39
- updatedAt: Time;
40
64
  version: text;
41
65
  };
42
- type PackageName__1 = text;
43
- type PackageName = text;
44
66
  type PackageConfig =
45
67
  record {
46
68
  dependencies: vec Dependency;
@@ -59,12 +81,6 @@ type PackageConfig =
59
81
  version: text;
60
82
  };
61
83
  type FileId = text;
62
- type File =
63
- record {
64
- content: blob;
65
- id: FileId;
66
- path: Text;
67
- };
68
84
  type Err = text;
69
85
  type Dependency =
70
86
  record {
@@ -74,15 +90,17 @@ type Dependency =
74
90
  service : {
75
91
  finishPublish: (PublishingId) -> (Result);
76
92
  getApiVersion: () -> (Text) query;
77
- getConfig: (PackageName__1, Version) -> (PackageConfig) query;
78
- getFile: (FileId) -> (File) query;
79
93
  getFileIds: (PackageName__1, Version) -> (vec FileId) query;
80
- getMaxVersion: (PackageName__1) -> (Version) query;
81
- getPackageSummary: (PackageName__1, Version) -> (PackageSummary) query;
82
- getReadmeFile: (PackageName__1, Version) -> (File) query;
83
- getRecentlyUpdatedPackages: () -> (vec PackageSummary) query;
94
+ getHighestVersion: (PackageName__1) -> (Version) query;
95
+ getPackageDetails: (PackageName__1, Version) -> (PackageDetails) query;
96
+ getRecentlyUpdatedPackages: () -> (vec PackageDetails) query;
97
+ getStoragesStats: () -> (vec record {
98
+ StorageId;
99
+ StorageStats;
100
+ }) query;
84
101
  notifyInstall: (PackageName__1, Version) -> () oneway;
85
- search: (Text) -> (vec PackageSummary) query;
102
+ search: (Text) -> (vec PackageDetails) query;
103
+ startFileUpload: (PublishingId, Text, nat, blob) -> (Result_2);
86
104
  startPublish: (PackageConfig) -> (Result_1);
87
- uploadFile: (PublishingId, Text, blob) -> (Result);
105
+ uploadFileChunk: (PublishingId, FileId, nat, blob) -> (Result);
88
106
  }
@@ -3,11 +3,6 @@ import type { ActorMethod } from '@dfinity/agent';
3
3
 
4
4
  export interface Dependency { 'name' : PackageName, 'version' : string }
5
5
  export type Err = string;
6
- export interface File {
7
- 'id' : FileId,
8
- 'content' : Array<number>,
9
- 'path' : Text,
10
- }
11
6
  export type FileId = string;
12
7
  export interface PackageConfig {
13
8
  'dfx' : string,
@@ -25,50 +20,71 @@ export interface PackageConfig {
25
20
  'license' : string,
26
21
  'readme' : string,
27
22
  }
28
- export type PackageName = string;
29
- export type PackageName__1 = string;
30
- export interface PackageSummary {
23
+ export interface PackageConfig__1 {
31
24
  'dfx' : string,
32
25
  'moc' : string,
33
26
  'scripts' : Array<Script>,
34
- 'owner' : Principal,
35
27
  'documentation' : string,
36
28
  'name' : PackageName,
37
29
  'homepage' : string,
38
- 'downloadsTotal' : bigint,
39
- 'downloadsInLast30Days' : bigint,
40
30
  'description' : string,
41
31
  'version' : string,
42
32
  'keywords' : Array<string>,
43
33
  'donation' : string,
44
- 'updatedAt' : Time,
45
34
  'repository' : string,
46
35
  'dependencies' : Array<Dependency>,
47
36
  'license' : string,
48
37
  'readme' : string,
49
38
  }
39
+ export interface PackageDetails {
40
+ 'owner' : Principal,
41
+ 'downloadsTotal' : bigint,
42
+ 'downloadsInLast30Days' : bigint,
43
+ 'config' : PackageConfig__1,
44
+ 'publication' : PackagePublication,
45
+ }
46
+ export type PackageName = string;
47
+ export type PackageName__1 = string;
48
+ export interface PackagePublication {
49
+ 'storage' : Principal,
50
+ 'time' : Time,
51
+ 'user' : Principal,
52
+ }
50
53
  export type PublishingErr = string;
51
54
  export type PublishingId = string;
52
55
  export type Result = { 'ok' : null } |
53
56
  { 'err' : Err };
54
57
  export type Result_1 = { 'ok' : PublishingId } |
55
58
  { 'err' : PublishingErr };
59
+ export type Result_2 = { 'ok' : FileId } |
60
+ { 'err' : Err };
56
61
  export interface Script { 'value' : string, 'name' : string }
62
+ export type StorageId = Principal;
63
+ export interface StorageStats {
64
+ 'fileCount' : bigint,
65
+ 'cyclesBalance' : bigint,
66
+ 'memorySize' : bigint,
67
+ }
57
68
  export type Text = string;
58
69
  export type Time = bigint;
59
70
  export type Version = string;
60
71
  export interface _SERVICE {
61
72
  'finishPublish' : ActorMethod<[PublishingId], Result>,
62
73
  'getApiVersion' : ActorMethod<[], Text>,
63
- 'getConfig' : ActorMethod<[PackageName__1, Version], PackageConfig>,
64
- 'getFile' : ActorMethod<[FileId], File>,
65
74
  'getFileIds' : ActorMethod<[PackageName__1, Version], Array<FileId>>,
66
- 'getMaxVersion' : ActorMethod<[PackageName__1], Version>,
67
- 'getPackageSummary' : ActorMethod<[PackageName__1, Version], PackageSummary>,
68
- 'getReadmeFile' : ActorMethod<[PackageName__1, Version], File>,
69
- 'getRecentlyUpdatedPackages' : ActorMethod<[], Array<PackageSummary>>,
75
+ 'getHighestVersion' : ActorMethod<[PackageName__1], Version>,
76
+ 'getPackageDetails' : ActorMethod<[PackageName__1, Version], PackageDetails>,
77
+ 'getRecentlyUpdatedPackages' : ActorMethod<[], Array<PackageDetails>>,
78
+ 'getStoragesStats' : ActorMethod<[], Array<[StorageId, StorageStats]>>,
70
79
  'notifyInstall' : ActorMethod<[PackageName__1, Version], undefined>,
71
- 'search' : ActorMethod<[Text], Array<PackageSummary>>,
80
+ 'search' : ActorMethod<[Text], Array<PackageDetails>>,
81
+ 'startFileUpload' : ActorMethod<
82
+ [PublishingId, Text, bigint, Array<number>],
83
+ Result_2,
84
+ >,
72
85
  'startPublish' : ActorMethod<[PackageConfig], Result_1>,
73
- 'uploadFile' : ActorMethod<[PublishingId, Text, Array<number>], Result>,
86
+ 'uploadFileChunk' : ActorMethod<
87
+ [PublishingId, FileId, bigint, Array<number>],
88
+ Result,
89
+ >,
74
90
  }
@@ -5,10 +5,11 @@ export const idlFactory = ({ IDL }) => {
5
5
  const Text = IDL.Text;
6
6
  const PackageName__1 = IDL.Text;
7
7
  const Version = IDL.Text;
8
+ const FileId = IDL.Text;
8
9
  const Script = IDL.Record({ 'value' : IDL.Text, 'name' : IDL.Text });
9
10
  const PackageName = IDL.Text;
10
11
  const Dependency = IDL.Record({ 'name' : PackageName, 'version' : IDL.Text });
11
- const PackageConfig = IDL.Record({
12
+ const PackageConfig__1 = IDL.Record({
12
13
  'dfx' : IDL.Text,
13
14
  'moc' : IDL.Text,
14
15
  'scripts' : IDL.Vec(Script),
@@ -24,28 +25,37 @@ export const idlFactory = ({ IDL }) => {
24
25
  'license' : IDL.Text,
25
26
  'readme' : IDL.Text,
26
27
  });
27
- const FileId = IDL.Text;
28
- const File = IDL.Record({
29
- 'id' : FileId,
30
- 'content' : IDL.Vec(IDL.Nat8),
31
- 'path' : Text,
32
- });
33
28
  const Time = IDL.Int;
34
- const PackageSummary = IDL.Record({
29
+ const PackagePublication = IDL.Record({
30
+ 'storage' : IDL.Principal,
31
+ 'time' : Time,
32
+ 'user' : IDL.Principal,
33
+ });
34
+ const PackageDetails = IDL.Record({
35
+ 'owner' : IDL.Principal,
36
+ 'downloadsTotal' : IDL.Nat,
37
+ 'downloadsInLast30Days' : IDL.Nat,
38
+ 'config' : PackageConfig__1,
39
+ 'publication' : PackagePublication,
40
+ });
41
+ const StorageId = IDL.Principal;
42
+ const StorageStats = IDL.Record({
43
+ 'fileCount' : IDL.Nat,
44
+ 'cyclesBalance' : IDL.Nat,
45
+ 'memorySize' : IDL.Nat,
46
+ });
47
+ const Result_2 = IDL.Variant({ 'ok' : FileId, 'err' : Err });
48
+ const PackageConfig = IDL.Record({
35
49
  'dfx' : IDL.Text,
36
50
  'moc' : IDL.Text,
37
51
  'scripts' : IDL.Vec(Script),
38
- 'owner' : IDL.Principal,
39
52
  'documentation' : IDL.Text,
40
53
  'name' : PackageName,
41
54
  'homepage' : IDL.Text,
42
- 'downloadsTotal' : IDL.Nat,
43
- 'downloadsInLast30Days' : IDL.Nat,
44
55
  'description' : IDL.Text,
45
56
  'version' : IDL.Text,
46
57
  'keywords' : IDL.Vec(IDL.Text),
47
58
  'donation' : IDL.Text,
48
- 'updatedAt' : Time,
49
59
  'repository' : IDL.Text,
50
60
  'dependencies' : IDL.Vec(Dependency),
51
61
  'license' : IDL.Text,
@@ -56,34 +66,37 @@ export const idlFactory = ({ IDL }) => {
56
66
  return IDL.Service({
57
67
  'finishPublish' : IDL.Func([PublishingId], [Result], []),
58
68
  'getApiVersion' : IDL.Func([], [Text], ['query']),
59
- 'getConfig' : IDL.Func(
60
- [PackageName__1, Version],
61
- [PackageConfig],
62
- ['query'],
63
- ),
64
- 'getFile' : IDL.Func([FileId], [File], ['query']),
65
69
  'getFileIds' : IDL.Func(
66
70
  [PackageName__1, Version],
67
71
  [IDL.Vec(FileId)],
68
72
  ['query'],
69
73
  ),
70
- 'getMaxVersion' : IDL.Func([PackageName__1], [Version], ['query']),
71
- 'getPackageSummary' : IDL.Func(
74
+ 'getHighestVersion' : IDL.Func([PackageName__1], [Version], ['query']),
75
+ 'getPackageDetails' : IDL.Func(
72
76
  [PackageName__1, Version],
73
- [PackageSummary],
77
+ [PackageDetails],
74
78
  ['query'],
75
79
  ),
76
- 'getReadmeFile' : IDL.Func([PackageName__1, Version], [File], ['query']),
77
80
  'getRecentlyUpdatedPackages' : IDL.Func(
78
81
  [],
79
- [IDL.Vec(PackageSummary)],
82
+ [IDL.Vec(PackageDetails)],
83
+ ['query'],
84
+ ),
85
+ 'getStoragesStats' : IDL.Func(
86
+ [],
87
+ [IDL.Vec(IDL.Tuple(StorageId, StorageStats))],
80
88
  ['query'],
81
89
  ),
82
90
  'notifyInstall' : IDL.Func([PackageName__1, Version], [], ['oneway']),
83
- 'search' : IDL.Func([Text], [IDL.Vec(PackageSummary)], ['query']),
91
+ 'search' : IDL.Func([Text], [IDL.Vec(PackageDetails)], ['query']),
92
+ 'startFileUpload' : IDL.Func(
93
+ [PublishingId, Text, IDL.Nat, IDL.Vec(IDL.Nat8)],
94
+ [Result_2],
95
+ [],
96
+ ),
84
97
  'startPublish' : IDL.Func([PackageConfig], [Result_1], []),
85
- 'uploadFile' : IDL.Func(
86
- [PublishingId, Text, IDL.Vec(IDL.Nat8)],
98
+ 'uploadFileChunk' : IDL.Func(
99
+ [PublishingId, FileId, IDL.Nat, IDL.Vec(IDL.Nat8)],
87
100
  [Result],
88
101
  [],
89
102
  ),
@@ -0,0 +1,38 @@
1
+ import { Actor, HttpAgent } from "@dfinity/agent";
2
+
3
+ // Imports and re-exports candid interface
4
+ import { idlFactory } from './storage.did.js';
5
+ export { idlFactory } from './storage.did.js';
6
+ // CANISTER_ID is replaced by webpack based on node environment
7
+ export const canisterId = process.env.STORAGE_CANISTER_ID;
8
+
9
+ /**
10
+ *
11
+ * @param {string | import("@dfinity/principal").Principal} canisterId Canister ID of Agent
12
+ * @param {{agentOptions?: import("@dfinity/agent").HttpAgentOptions; actorOptions?: import("@dfinity/agent").ActorConfig}} [options]
13
+ * @return {import("@dfinity/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
14
+ */
15
+ export const createActor = (canisterId, options) => {
16
+ const agent = new HttpAgent({ ...options?.agentOptions });
17
+
18
+ // Fetch root key for certificate validation during development
19
+ if(process.env.NODE_ENV !== "production") {
20
+ agent.fetchRootKey().catch(err=>{
21
+ console.warn("Unable to fetch root key. Check to ensure that your local replica is running");
22
+ console.error(err);
23
+ });
24
+ }
25
+
26
+ // Creates an actor with using the candid interface and the HttpAgent
27
+ return Actor.createActor(idlFactory, {
28
+ agent,
29
+ canisterId,
30
+ ...options?.actorOptions,
31
+ });
32
+ };
33
+
34
+ /**
35
+ * A ready-to-use agent for the storage canister
36
+ * @type {import("@dfinity/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
37
+ */
38
+ export const storage = createActor(canisterId);
@@ -0,0 +1,46 @@
1
+ type StorageStats =
2
+ record {
3
+ cyclesBalance: nat;
4
+ fileCount: nat;
5
+ memorySize: nat;
6
+ };
7
+ type Storage =
8
+ service {
9
+ acceptCycles: () -> ();
10
+ deleteFile: (FileId) -> ();
11
+ downloadChunk: (FileId, nat) -> (Result_2) query;
12
+ finishUpload: (FileId) -> ();
13
+ getFileIdsRange: (nat, nat) -> (vec FileId) query;
14
+ getFileMeta: (FileId) -> (Result_1) query;
15
+ getStats: () -> (StorageStats) query;
16
+ startUpload: (FileMeta) -> (Result);
17
+ updateFileOwners: (FileId, vec principal) -> ();
18
+ uploadChunk: (FileId, nat, Chunk) -> ();
19
+ };
20
+ type Result_2 =
21
+ variant {
22
+ err: Err;
23
+ ok: Chunk;
24
+ };
25
+ type Result_1 =
26
+ variant {
27
+ err: Err;
28
+ ok: FileMeta;
29
+ };
30
+ type Result =
31
+ variant {
32
+ err: Err;
33
+ ok;
34
+ };
35
+ type FileMeta =
36
+ record {
37
+ chunkCount: nat;
38
+ id: FileId__1;
39
+ owners: vec principal;
40
+ path: text;
41
+ };
42
+ type FileId__1 = text;
43
+ type FileId = text;
44
+ type Err = text;
45
+ type Chunk = blob;
46
+ service : () -> Storage
@@ -0,0 +1,37 @@
1
+ import type { Principal } from '@dfinity/principal';
2
+ import type { ActorMethod } from '@dfinity/agent';
3
+
4
+ export type Chunk = Array<number>;
5
+ export type Err = string;
6
+ export type FileId = string;
7
+ export type FileId__1 = string;
8
+ export interface FileMeta {
9
+ 'id' : FileId__1,
10
+ 'owners' : Array<Principal>,
11
+ 'path' : string,
12
+ 'chunkCount' : bigint,
13
+ }
14
+ export type Result = { 'ok' : null } |
15
+ { 'err' : Err };
16
+ export type Result_1 = { 'ok' : FileMeta } |
17
+ { 'err' : Err };
18
+ export type Result_2 = { 'ok' : Chunk } |
19
+ { 'err' : Err };
20
+ export interface Storage {
21
+ 'acceptCycles' : ActorMethod<[], undefined>,
22
+ 'deleteFile' : ActorMethod<[FileId], undefined>,
23
+ 'downloadChunk' : ActorMethod<[FileId, bigint], Result_2>,
24
+ 'finishUpload' : ActorMethod<[FileId], undefined>,
25
+ 'getFileIdsRange' : ActorMethod<[bigint, bigint], Array<FileId>>,
26
+ 'getFileMeta' : ActorMethod<[FileId], Result_1>,
27
+ 'getStats' : ActorMethod<[], StorageStats>,
28
+ 'startUpload' : ActorMethod<[FileMeta], Result>,
29
+ 'updateFileOwners' : ActorMethod<[FileId, Array<Principal>], undefined>,
30
+ 'uploadChunk' : ActorMethod<[FileId, bigint, Chunk], undefined>,
31
+ }
32
+ export interface StorageStats {
33
+ 'fileCount' : bigint,
34
+ 'cyclesBalance' : bigint,
35
+ 'memorySize' : bigint,
36
+ }
37
+ export interface _SERVICE extends Storage {}
@@ -0,0 +1,38 @@
1
+ export const idlFactory = ({ IDL }) => {
2
+ const FileId = IDL.Text;
3
+ const Chunk = IDL.Vec(IDL.Nat8);
4
+ const Err = IDL.Text;
5
+ const Result_2 = IDL.Variant({ 'ok' : Chunk, 'err' : Err });
6
+ const FileId__1 = IDL.Text;
7
+ const FileMeta = IDL.Record({
8
+ 'id' : FileId__1,
9
+ 'owners' : IDL.Vec(IDL.Principal),
10
+ 'path' : IDL.Text,
11
+ 'chunkCount' : IDL.Nat,
12
+ });
13
+ const Result_1 = IDL.Variant({ 'ok' : FileMeta, 'err' : Err });
14
+ const StorageStats = IDL.Record({
15
+ 'fileCount' : IDL.Nat,
16
+ 'cyclesBalance' : IDL.Nat,
17
+ 'memorySize' : IDL.Nat,
18
+ });
19
+ const Result = IDL.Variant({ 'ok' : IDL.Null, 'err' : Err });
20
+ const Storage = IDL.Service({
21
+ 'acceptCycles' : IDL.Func([], [], []),
22
+ 'deleteFile' : IDL.Func([FileId], [], []),
23
+ 'downloadChunk' : IDL.Func([FileId, IDL.Nat], [Result_2], ['query']),
24
+ 'finishUpload' : IDL.Func([FileId], [], []),
25
+ 'getFileIdsRange' : IDL.Func(
26
+ [IDL.Nat, IDL.Nat],
27
+ [IDL.Vec(FileId)],
28
+ ['query'],
29
+ ),
30
+ 'getFileMeta' : IDL.Func([FileId], [Result_1], ['query']),
31
+ 'getStats' : IDL.Func([], [StorageStats], ['query']),
32
+ 'startUpload' : IDL.Func([FileMeta], [Result], []),
33
+ 'updateFileOwners' : IDL.Func([FileId, IDL.Vec(IDL.Principal)], [], []),
34
+ 'uploadChunk' : IDL.Func([FileId, IDL.Nat, Chunk], [], []),
35
+ });
36
+ return Storage;
37
+ };
38
+ export const init = ({ IDL }) => { return []; };
package/mops.js CHANGED
@@ -6,6 +6,7 @@ import path from 'path';
6
6
  import fs from 'fs';
7
7
 
8
8
  import {idlFactory} from './declarations/main/main.did.js';
9
+ import {idlFactory as storageIdlFactory} from './declarations/storage/storage.did.js';
9
10
  import {decodeFile} from './pem.js';
10
11
 
11
12
 
@@ -16,6 +17,8 @@ let apiVersion = '0.1';
16
17
 
17
18
  let networkFile = new URL('./network.txt', import.meta.url);
18
19
 
20
+ export let globalCacheDir = path.resolve(process.env.HOME || process.env.APPDATA, 'mops');
21
+
19
22
  export function setNetwork(network) {
20
23
  fs.writeFileSync(networkFile, network);
21
24
  }
@@ -44,7 +47,7 @@ export function getNetwork() {
44
47
  }
45
48
 
46
49
  export let getIdentity = () => {
47
- let identityPem = new URL('./identity.pem', import.meta.url);
50
+ let identityPem = path.resolve(globalCacheDir, 'identity.pem');
48
51
  if (fs.existsSync(identityPem)) {
49
52
  return decodeFile(identityPem);
50
53
  }
@@ -68,6 +71,23 @@ export let mainActor = async () => {
68
71
  });
69
72
  };
70
73
 
74
+ export let storageActor = async (storageId) => {
75
+ let network = getNetwork().network;
76
+ let host = getNetwork().host;
77
+
78
+ let identity = getIdentity();
79
+ let agent = new HttpAgent({host, identity});
80
+
81
+ if (network === 'local') {
82
+ await agent.fetchRootKey();
83
+ }
84
+
85
+ return Actor.createActor(storageIdlFactory, {
86
+ agent,
87
+ canisterId: storageId,
88
+ });
89
+ };
90
+
71
91
  export function checkConfigFile() {
72
92
  let configFile = path.join(process.cwd(), 'mops.toml');
73
93
  if (!fs.existsSync(configFile)) {
@@ -82,9 +102,9 @@ export function progressBar(step, total) {
82
102
  return `[${':'.repeat(done)}${' '.repeat(10 - done)}]`;
83
103
  }
84
104
 
85
- export async function getMaxVersion(pkgName) {
105
+ export async function getHighestVersion(pkgName) {
86
106
  let actor = await mainActor();
87
- return actor.getMaxVersion(pkgName);
107
+ return actor.getHighestVersion(pkgName);
88
108
  }
89
109
 
90
110
  export function readConfig(configFile = path.join(process.cwd(), 'mops.toml')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ic-mops",
3
- "version": "0.1.4",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mops": "cli.js"