@super-protocol/sp-cli 0.0.2-beta.16 → 0.0.2-beta.17

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/README.md CHANGED
@@ -21,7 +21,7 @@ $ npm install -g @super-protocol/sp-cli
21
21
  $ sp COMMAND
22
22
  running command...
23
23
  $ sp (--version)
24
- @super-protocol/sp-cli/0.0.2-beta.16 linux-x64 node-v22.21.1
24
+ @super-protocol/sp-cli/0.0.2-beta.17 linux-x64 node-v22.21.1
25
25
  $ sp --help [COMMAND]
26
26
  USAGE
27
27
  $ sp COMMAND
@@ -65,7 +65,7 @@ DESCRIPTION
65
65
  Information about current authorized user
66
66
  ```
67
67
 
68
- _See code: [src/commands/account/info.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/account/info.ts)_
68
+ _See code: [src/commands/account/info.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/account/info.ts)_
69
69
 
70
70
  ## `sp auth login`
71
71
 
@@ -89,7 +89,7 @@ EXAMPLES
89
89
  $ sp auth login
90
90
  ```
91
91
 
92
- _See code: [src/commands/auth/login.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/auth/login.ts)_
92
+ _See code: [src/commands/auth/login.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/auth/login.ts)_
93
93
 
94
94
  ## `sp auth me`
95
95
 
@@ -102,7 +102,7 @@ GLOBAL FLAGS
102
102
  --json Format output as json.
103
103
  ```
104
104
 
105
- _See code: [src/commands/auth/me.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/auth/me.ts)_
105
+ _See code: [src/commands/auth/me.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/auth/me.ts)_
106
106
 
107
107
  ## `sp autocomplete [SHELL]`
108
108
 
@@ -163,7 +163,7 @@ EXAMPLES
163
163
  $ sp config delete - Delete a configuration
164
164
  ```
165
165
 
166
- _See code: [src/commands/config/index.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/config/index.ts)_
166
+ _See code: [src/commands/config/index.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/config/index.ts)_
167
167
 
168
168
  ## `sp config add [FILE]`
169
169
 
@@ -202,7 +202,7 @@ EXAMPLES
202
202
  }
203
203
  ```
204
204
 
205
- _See code: [src/commands/config/add.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/config/add.ts)_
205
+ _See code: [src/commands/config/add.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/config/add.ts)_
206
206
 
207
207
  ## `sp config create`
208
208
 
@@ -229,7 +229,7 @@ EXAMPLES
229
229
  $ sp config create --name "Production" --url "https://api.dp.superprotocol.com"
230
230
  ```
231
231
 
232
- _See code: [src/commands/config/create.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/config/create.ts)_
232
+ _See code: [src/commands/config/create.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/config/create.ts)_
233
233
 
234
234
  ## `sp config delete`
235
235
 
@@ -257,7 +257,7 @@ EXAMPLES
257
257
  $ sp config delete --name "My Config" --force
258
258
  ```
259
259
 
260
- _See code: [src/commands/config/delete.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/config/delete.ts)_
260
+ _See code: [src/commands/config/delete.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/config/delete.ts)_
261
261
 
262
262
  ## `sp config list`
263
263
 
@@ -277,7 +277,7 @@ EXAMPLES
277
277
  $ sp config list
278
278
  ```
279
279
 
280
- _See code: [src/commands/config/list.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/config/list.ts)_
280
+ _See code: [src/commands/config/list.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/config/list.ts)_
281
281
 
282
282
  ## `sp config show`
283
283
 
@@ -297,7 +297,7 @@ EXAMPLES
297
297
  $ sp config show
298
298
  ```
299
299
 
300
- _See code: [src/commands/config/show.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/config/show.ts)_
300
+ _See code: [src/commands/config/show.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/config/show.ts)_
301
301
 
302
302
  ## `sp config use`
303
303
 
@@ -317,11 +317,11 @@ EXAMPLES
317
317
  $ sp config use
318
318
  ```
319
319
 
320
- _See code: [src/commands/config/use.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/config/use.ts)_
320
+ _See code: [src/commands/config/use.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/config/use.ts)_
321
321
 
322
322
  ## `sp files download RESOURCEFILE LOCALDIRECTORY`
323
323
 
324
- Download file or directory described in resource frole
324
+ Download file or directory described in resource file
325
325
 
326
326
  ```
327
327
  USAGE
@@ -332,24 +332,24 @@ ARGUMENTS
332
332
  LOCALDIRECTORY Path to save downloaded file
333
333
 
334
334
  FLAGS
335
- --maximum-concurrent=<value> [default: 1] Maximum concurrent pieces to upload at once per transfer
335
+ --maximum-concurrent=<value> [default: 1] Maximum concurrent pieces to download at once per transfer
336
336
 
337
337
  GLOBAL FLAGS
338
338
  --config=<value> Specify config file.
339
339
  --json Format output as json.
340
340
 
341
341
  DESCRIPTION
342
- Download file or directory described in resource frole
342
+ Download file or directory described in resource file
343
343
 
344
344
  EXAMPLES
345
345
  $ sp files download ./resource.json ./pathToDownload
346
346
  ```
347
347
 
348
- _See code: [src/commands/files/download.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/files/download.ts)_
348
+ _See code: [src/commands/files/download.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/files/download.ts)_
349
349
 
350
350
  ## `sp files upload PATH`
351
351
 
352
- Upload files of directory to remote storage
352
+ Upload file or directory to remote storage
353
353
 
354
354
  ```
355
355
  USAGE
@@ -373,13 +373,13 @@ GLOBAL FLAGS
373
373
  --json Format output as json.
374
374
 
375
375
  DESCRIPTION
376
- Upload files of directory to remote storage
376
+ Upload file or directory to remote storage
377
377
 
378
378
  EXAMPLES
379
379
  $ sp files upload ./file.txt
380
380
  ```
381
381
 
382
- _See code: [src/commands/files/upload.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/files/upload.ts)_
382
+ _See code: [src/commands/files/upload.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/files/upload.ts)_
383
383
 
384
384
  ## `sp help [COMMAND]`
385
385
 
@@ -450,7 +450,7 @@ EXAMPLES
450
450
  $ sp storage create --not-default
451
451
  ```
452
452
 
453
- _See code: [src/commands/storage/create.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/storage/create.ts)_
453
+ _See code: [src/commands/storage/create.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/storage/create.ts)_
454
454
 
455
455
  ## `sp storage select`
456
456
 
@@ -476,7 +476,7 @@ EXAMPLES
476
476
  $ sp storage select --id=2de3e3a4-0000-1111-2222-333344445555
477
477
  ```
478
478
 
479
- _See code: [src/commands/storage/select.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/storage/select.ts)_
479
+ _See code: [src/commands/storage/select.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/storage/select.ts)_
480
480
 
481
481
  ## `sp storage update`
482
482
 
@@ -503,5 +503,5 @@ EXAMPLES
503
503
  $ sp storage update --id=2de3e3a4-0000-1111-2222-333344445555
504
504
  ```
505
505
 
506
- _See code: [src/commands/storage/update.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.16/src/commands/storage/update.ts)_
506
+ _See code: [src/commands/storage/update.ts](https://github.com/Super-Protocol/sp-cli/blob/v0.0.2-beta.17/src/commands/storage/update.ts)_
507
507
  <!-- commandsstop -->
@@ -44,7 +44,7 @@ export default class SpLogin extends BaseCommand {
44
44
  this.warn('Storage initialization failed. You can set up storage later using "sp storage create" or "sp storage select".');
45
45
  }
46
46
  const account = accountManager.getAddress();
47
- this.log(`Logined in with account ${account}`);
47
+ this.log(`Logged in with account ${account}`);
48
48
  return { account, success: true };
49
49
  }
50
50
  }
@@ -8,13 +8,13 @@ export default class FilesDownload extends BaseCommand {
8
8
  // eslint-disable-next-line perfectionist/sort-objects
9
9
  localDirectory: Args.string({ description: 'Path to save downloaded file', required: true }),
10
10
  };
11
- static description = 'Download file or directory described in resource frole';
11
+ static description = 'Download file or directory described in resource file';
12
12
  static examples = [
13
13
  '<%= config.bin %> <%= command.id %> ./resource.json ./pathToDownload ',
14
14
  ];
15
15
  static flags = {
16
16
  'maximum-concurrent': Flags.integer({
17
- default: 1, description: 'Maximum concurrent pieces to upload at once per transfer', max: 1000, min: 1,
17
+ default: 1, description: 'Maximum concurrent pieces to download at once per transfer', max: 1000, min: 1,
18
18
  }),
19
19
  };
20
20
  static help = 'Download and decrypt a file from the remote storage to <localPath> using resource file <resourcePath>';
@@ -25,20 +25,19 @@ export default class FilesDownload extends BaseCommand {
25
25
  async run() {
26
26
  const { args, flags } = await this.parse(FilesDownload);
27
27
  const { providerClient } = this.container;
28
- const storageSerivce = new StorageService(providerClient, this.logger);
28
+ const storageService = new StorageService(providerClient, this.logger);
29
29
  const progress = createProgressPrinter({
30
30
  action: 'Download',
31
31
  start: 'Downloading: ',
32
32
  });
33
33
  try {
34
- await storageSerivce.download({
34
+ await storageService.download({
35
35
  downloadPath: args.localDirectory,
36
36
  maximumConcurrent: flags['maximum-concurrent'],
37
37
  resourcePath: args.resourceFile,
38
38
  }, ({ current, key, total }) => {
39
39
  progress.advance(key, current / total * 100, `Downloading: ${key} [${current}/${total}]`);
40
40
  });
41
- progress.finish();
42
41
  }
43
42
  catch (error) {
44
43
  let reason = '';
@@ -48,6 +47,9 @@ export default class FilesDownload extends BaseCommand {
48
47
  }
49
48
  this.error(`Download aborted. Reason: ${reason}`);
50
49
  }
51
- this.log('Download successful completed');
50
+ finally {
51
+ progress.finish();
52
+ }
53
+ this.log('Download successfully completed');
52
54
  }
53
55
  }
@@ -6,7 +6,7 @@ export default class FilesUpload extends BaseCommand {
6
6
  static args = {
7
7
  path: Args.string({ description: 'file or directory to upload', required: true }),
8
8
  };
9
- static description = 'Upload files of directory to remote storage';
9
+ static description = 'Upload file or directory to remote storage';
10
10
  static examples = [
11
11
  '<%= config.bin %> <%= command.id %> ./file.txt',
12
12
  ];
@@ -45,24 +45,23 @@ export default class FilesUpload extends BaseCommand {
45
45
  async run() {
46
46
  const { args, flags } = await this.parse(FilesUpload);
47
47
  const { providerClient } = this.container;
48
- const storageSerivce = new StorageService(providerClient, this.logger);
48
+ const storageService = new StorageService(providerClient, this.logger);
49
49
  const progress = createProgressPrinter({
50
50
  action: 'Upload',
51
51
  start: 'Uploading: ',
52
52
  });
53
53
  try {
54
- await storageSerivce.upload({
54
+ await storageService.upload({
55
55
  localPath: args.path,
56
56
  maximumConcurrent: flags['maximum-concurrent'],
57
57
  metadataPath: flags.metadata,
58
58
  outputPath: flags.output,
59
59
  remotePath: flags.filename,
60
60
  sync: flags.sync,
61
- withEncryption: flags['skip-encryption'],
61
+ withEncryption: !flags['skip-encryption'],
62
62
  }, ({ current, key, total }) => {
63
63
  progress.advance(key, current / total * 100, `Uploading: ${key} [${current}/${total}]`);
64
64
  });
65
- progress.finish();
66
65
  }
67
66
  catch (error) {
68
67
  let reason = '';
@@ -72,6 +71,9 @@ export default class FilesUpload extends BaseCommand {
72
71
  }
73
72
  this.error(`Upload aborted. Reason: ${reason}`);
74
73
  }
75
- this.log('Upload successful completed');
74
+ finally {
75
+ progress.finish();
76
+ }
77
+ this.log('Upload successfully completed');
76
78
  }
77
79
  }
@@ -65,7 +65,7 @@ export class AccountManager {
65
65
  }
66
66
  catch (error) {
67
67
  this.logger.warn({ err: error }, 'Incorrect config file');
68
- ux.warn("Account doesn't exists in current configuration");
68
+ ux.warn("Account doesn't exist in current configuration");
69
69
  const ask = await confirm({
70
70
  message: 'Do you want to create new account?',
71
71
  });
@@ -176,11 +176,15 @@ export class ConfigFileManager {
176
176
  catch {
177
177
  //
178
178
  }
179
- finally {
179
+ try {
180
180
  await this.setCurrentConfig(DEFAULT_USER_CONFIG_FILE);
181
181
  }
182
+ catch (error) {
183
+ this.logger.error({ err: error }, 'Failed to set default config');
184
+ throw error;
185
+ }
182
186
  }
183
- return path.join(this.configsDir, this.configs.currentConfig);
187
+ return path.join(this.configsDir, this.configs.currentConfig || DEFAULT_USER_CONFIG_FILE);
184
188
  }
185
189
  async importConfig(sourcePath, targetName) {
186
190
  if (!fs.existsSync(sourcePath)) {
@@ -67,5 +67,6 @@ export declare class StorageService {
67
67
  } | undefined>;
68
68
  updateStorage(id: string, storage: UpdateStorageDto): Promise<StorageResponseDto>;
69
69
  upload(params: IUploadParams, progressCb: ProgressCb): Promise<void>;
70
+ private getStorageCredentials;
70
71
  }
71
72
  export {};
@@ -67,7 +67,8 @@ export class StorageService {
67
67
  }
68
68
  let localPath = preparePath(params.downloadPath);
69
69
  if (resource.filepath) {
70
- localPath = joinPaths(localPath, resource.filepath);
70
+ const sanitizedFilepath = resource.filepath.replaceAll('..', '').replace(/^\/+/, '');
71
+ localPath = joinPaths(localPath, sanitizedFilepath);
71
72
  }
72
73
  try {
73
74
  this.logger.info('Starting download');
@@ -242,7 +243,7 @@ export class StorageService {
242
243
  }
243
244
  async upload(params, progressCb) {
244
245
  const storage = await this.getCurrentStorage();
245
- const remotePath = `${params.remotePath || generateExternalId()}`;
246
+ const remotePath = params.remotePath ? params.remotePath.replaceAll('..', '').replace(/^\/+/, '') : generateExternalId();
246
247
  const resourceFilePath = preparePath(params.outputPath || '');
247
248
  try {
248
249
  await fs.stat(resourceFilePath);
@@ -257,32 +258,7 @@ export class StorageService {
257
258
  if (params.metadataPath) {
258
259
  metadata = await readJsonFile({ path: preparePath(params.metadataPath) });
259
260
  }
260
- const writeCredentials = storage.storageType === StorageType.StorJ
261
- ? {
262
- bucket: storage.bucket,
263
- prefix: joinPaths(storage.prefix, remotePath),
264
- token: storage.storjCredentials.writeAccessToken,
265
- }
266
- : {
267
- accessKeyId: storage.s3Credentials.writeAccessKeyId,
268
- bucket: storage.bucket,
269
- endpoint: S3_ENDPOINT,
270
- prefix: joinPaths(storage.prefix, remotePath),
271
- secretKey: storage.s3Credentials.writeSecretAccessKey,
272
- };
273
- const readCredentials = storage.storageType === StorageType.StorJ
274
- ? {
275
- bucket: storage.bucket,
276
- prefix: joinPaths(storage.prefix, remotePath),
277
- token: storage.storjCredentials.readAccessToken,
278
- }
279
- : {
280
- accessKeyId: storage.s3Credentials.readAccessKeyId,
281
- bucket: storage.bucket,
282
- endpoint: S3_ENDPOINT,
283
- prefix: joinPaths(storage.prefix, remotePath),
284
- secretKey: storage.s3Credentials.readSecretAccessKey,
285
- };
261
+ const { readCredentials, writeCredentials } = this.getStorageCredentials(storage, remotePath);
286
262
  const info = await fs.stat(params.localPath);
287
263
  let { localPath } = params;
288
264
  let sourcePath;
@@ -310,7 +286,7 @@ export class StorageService {
310
286
  ...metadata,
311
287
  ...uploadResult,
312
288
  };
313
- await fs.writeFile(resourceFilePath, JSON.stringify(result, null, 2));
289
+ await fs.writeFile(resourceFilePath, JSON.stringify(result, null, 2), { flag: 'wx' });
314
290
  this.logger.info(`Resource file was created in ${resourceFilePath}`);
315
291
  }
316
292
  catch (error) {
@@ -318,6 +294,47 @@ export class StorageService {
318
294
  throw error;
319
295
  }
320
296
  }
297
+ getStorageCredentials(storage, remotePath) {
298
+ if (storage.storageType === StorageType.StorJ) {
299
+ const { readAccessToken, writeAccessToken } = storage.storjCredentials || {};
300
+ if (!writeAccessToken || !readAccessToken) {
301
+ throw new StorageError('StorJ credentials are missing or incomplete');
302
+ }
303
+ return {
304
+ readCredentials: {
305
+ bucket: storage.bucket,
306
+ prefix: joinPaths(storage.prefix, remotePath),
307
+ token: readAccessToken,
308
+ }, writeCredentials: {
309
+ bucket: storage.bucket,
310
+ prefix: joinPaths(storage.prefix, remotePath),
311
+ token: writeAccessToken,
312
+ },
313
+ };
314
+ }
315
+ if (storage.storageType === StorageType.S3) {
316
+ const { readAccessKeyId, readSecretAccessKey, writeAccessKeyId, writeSecretAccessKey } = storage.s3Credentials || {};
317
+ if (!writeAccessKeyId || !writeSecretAccessKey || !readAccessKeyId || !readSecretAccessKey) {
318
+ throw new StorageError('S3 credentials are missing or incomplete');
319
+ }
320
+ return {
321
+ readCredentials: {
322
+ accessKeyId: readAccessKeyId,
323
+ bucket: storage.bucket,
324
+ endpoint: S3_ENDPOINT,
325
+ prefix: joinPaths(storage.prefix, remotePath),
326
+ secretKey: readSecretAccessKey,
327
+ }, writeCredentials: {
328
+ accessKeyId: writeAccessKeyId,
329
+ bucket: storage.bucket,
330
+ endpoint: S3_ENDPOINT,
331
+ prefix: joinPaths(storage.prefix, remotePath),
332
+ secretKey: writeSecretAccessKey,
333
+ },
334
+ };
335
+ }
336
+ throw new StorageError(`Unknown storage type: ${storage.storageType}`);
337
+ }
321
338
  }
322
339
  __decorate([
323
340
  Retryable({ maxAttempts: 3, value: [StoragesUndefinedError, StorageCreateError, ProviderClientError] })
@@ -2,6 +2,7 @@ import * as p from '@clack/prompts';
2
2
  export const createProgressPrinter = ({ action, done = 'completed', start, }) => {
3
3
  const progressBars = {};
4
4
  let lastKey = '';
5
+ let lastProgress = 0;
5
6
  const getProgress = (key) => {
6
7
  if (key in progressBars) {
7
8
  lastKey = key;
@@ -9,6 +10,7 @@ export const createProgressPrinter = ({ action, done = 'completed', start, }) =>
9
10
  }
10
11
  if (lastKey in progressBars) {
11
12
  const progressBar = progressBars[lastKey];
13
+ lastProgress = 0;
12
14
  progressBar.stop(`${action} ${lastKey} ${done}`);
13
15
  }
14
16
  const progressBar = p.progress({ size: 100, style: 'block' });
@@ -16,11 +18,17 @@ export const createProgressPrinter = ({ action, done = 'completed', start, }) =>
16
18
  progressBars[key] = progressBar;
17
19
  return progressBar;
18
20
  };
19
- const finish = () => progressBars[lastKey].stop(`${action} ${lastKey} ${done}`);
21
+ const finish = () => {
22
+ if (lastKey && progressBars[lastKey]) {
23
+ lastProgress = 0;
24
+ progressBars[lastKey].stop(`${action} ${lastKey} ${done}`);
25
+ }
26
+ };
20
27
  return {
21
28
  advance(key, num, message) {
22
29
  const progress = getProgress(key);
23
- progress.advance(num, message);
30
+ progress.advance(num - lastProgress, message);
31
+ lastProgress = num;
24
32
  },
25
33
  finish,
26
34
  };
@@ -426,7 +426,7 @@
426
426
  "required": true
427
427
  }
428
428
  },
429
- "description": "Download file or directory described in resource frole",
429
+ "description": "Download file or directory described in resource file",
430
430
  "examples": [
431
431
  "<%= config.bin %> <%= command.id %> ./resource.json ./pathToDownload "
432
432
  ],
@@ -448,7 +448,7 @@
448
448
  "type": "option"
449
449
  },
450
450
  "maximum-concurrent": {
451
- "description": "Maximum concurrent pieces to upload at once per transfer",
451
+ "description": "Maximum concurrent pieces to download at once per transfer",
452
452
  "name": "maximum-concurrent",
453
453
  "default": 1,
454
454
  "hasDynamicHelp": false,
@@ -482,7 +482,7 @@
482
482
  "required": true
483
483
  }
484
484
  },
485
- "description": "Upload files of directory to remote storage",
485
+ "description": "Upload file or directory to remote storage",
486
486
  "examples": [
487
487
  "<%= config.bin %> <%= command.id %> ./file.txt"
488
488
  ],
@@ -733,5 +733,5 @@
733
733
  ]
734
734
  }
735
735
  },
736
- "version": "0.0.2-beta.16"
736
+ "version": "0.0.2-beta.17"
737
737
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@super-protocol/sp-cli",
3
3
  "description": "SuperProtocol Command line interface",
4
- "version": "0.0.2-beta.16",
4
+ "version": "0.0.2-beta.17",
5
5
  "author": "SuperProtocol",
6
6
  "publishConfig": {
7
7
  "access": "public",