@mimicprotocol/cli 0.0.1-rc.35 → 0.0.1-rc.37
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/CHANGELOG.md +14 -0
- package/README.md +10 -10
- package/dist/commands/authenticate.js +74 -26
- package/dist/commands/build.js +11 -18
- package/dist/commands/codegen.js +42 -27
- package/dist/commands/compile.js +26 -16
- package/dist/commands/deploy.js +49 -49
- package/dist/commands/functions.js +141 -0
- package/dist/commands/init.js +24 -22
- package/dist/commands/login.js +9 -6
- package/dist/commands/logout.js +5 -2
- package/dist/commands/profiles.js +3 -0
- package/dist/commands/test.js +30 -16
- package/dist/lib/CredentialsManager.js +0 -33
- package/dist/lib/InputsInterfaceGenerator.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @mimicprotocol/cli
|
|
2
2
|
|
|
3
|
+
## 0.0.1-rc.37
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ed2d252: Refactor credentials commands
|
|
8
|
+
- 94ef728: add custom storage
|
|
9
|
+
- 7d2279d: Refactor codegen, compile, build, deploy and test commands and their parameters
|
|
10
|
+
|
|
11
|
+
## 0.0.1-rc.36
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 6a4fb70: rename to use functions
|
|
16
|
+
|
|
3
17
|
## 0.0.1-rc.35
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
|
|
28
28
|
The `mimic` CLI is a command-line interface to:
|
|
29
29
|
|
|
30
|
-
- Initialize a Mimic-compatible
|
|
31
|
-
- Generate types from your
|
|
32
|
-
- Compile your AssemblyScript
|
|
33
|
-
- Test your
|
|
34
|
-
- Deploy compiled
|
|
35
|
-
- Link
|
|
30
|
+
- Initialize a Mimic-compatible function project
|
|
31
|
+
- Generate types from your function manifest and ABIs
|
|
32
|
+
- Compile your AssemblyScript functions to WebAssembly
|
|
33
|
+
- Test your functions
|
|
34
|
+
- Deploy compiled functions to IPFS and the Mimic Registry
|
|
35
|
+
- Link functions to a project in the Mimic explorer
|
|
36
36
|
|
|
37
37
|
## Setup
|
|
38
38
|
|
|
@@ -64,15 +64,15 @@ COMMANDS
|
|
|
64
64
|
logout Remove stored credentials for a profile
|
|
65
65
|
profiles List all configured authentication profiles
|
|
66
66
|
codegen Generates typed interfaces for declared inputs and ABIs from your manifest.yaml file
|
|
67
|
-
compile Compiles
|
|
68
|
-
test Tests your
|
|
69
|
-
deploy Uploads your compiled
|
|
67
|
+
compile Compiles the function
|
|
68
|
+
test Tests your functions
|
|
69
|
+
deploy Uploads your compiled function artifacts to IPFS and registers it into the Mimic Registry
|
|
70
70
|
init Initializes a new Mimic-compatible project structure in the specified directory
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
### Authentication
|
|
74
74
|
|
|
75
|
-
Before deploying
|
|
75
|
+
Before deploying functions, you need to authenticate with your Mimic API key:
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
78
|
# Interactive login (recommended)
|
|
@@ -1,46 +1,94 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
39
|
const core_1 = require("@oclif/core");
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
7
41
|
const CredentialsManager_1 = require("../lib/CredentialsManager");
|
|
8
42
|
const log_1 = __importDefault(require("../log"));
|
|
9
43
|
class Authenticate extends core_1.Command {
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
44
|
run() {
|
|
12
45
|
throw new Error('Method not implemented.');
|
|
13
46
|
}
|
|
14
|
-
authenticate(flags) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
47
|
+
static authenticate(cmd, flags) {
|
|
48
|
+
const apiKey = flags['api-key'];
|
|
49
|
+
const profileName = flags.profile || CredentialsManager_1.CredentialsManager.getDefaultProfileName();
|
|
50
|
+
const credentialsManager = CredentialsManager_1.CredentialsManager.getDefault();
|
|
51
|
+
if (apiKey)
|
|
52
|
+
return { apiKey };
|
|
53
|
+
try {
|
|
54
|
+
const credentialsDir = credentialsManager.getBaseDir();
|
|
55
|
+
const credentialsPath = credentialsManager.getCredentialsPath();
|
|
56
|
+
if (!fs.existsSync(credentialsDir)) {
|
|
57
|
+
throw new Error(`No credentials directory found at ${credentialsDir}. Run 'mimic login' to authenticate.`);
|
|
58
|
+
}
|
|
59
|
+
if (!fs.existsSync(credentialsPath)) {
|
|
60
|
+
throw new Error(`No credentials file found. Run 'mimic login' to authenticate.`);
|
|
61
|
+
}
|
|
62
|
+
const profiles = credentialsManager.readCredentials();
|
|
63
|
+
if (!profiles[profileName]) {
|
|
64
|
+
const availableProfiles = Object.keys(profiles);
|
|
65
|
+
const suggestion = availableProfiles.length > 0
|
|
66
|
+
? `Available profiles: ${availableProfiles.join(', ')}`
|
|
67
|
+
: `No profiles found. Run 'mimic login' to create one.`;
|
|
68
|
+
throw new Error(`Profile '${profileName}' not found. ${suggestion}`);
|
|
20
69
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
70
|
+
const credentials = profiles[profileName];
|
|
71
|
+
if (!credentials.apiKey || credentials.apiKey.trim() === '') {
|
|
72
|
+
throw new Error(`Profile '${profileName}' has no API key. Run 'mimic login --profile ${profileName}' to update credentials.`);
|
|
73
|
+
}
|
|
74
|
+
return { apiKey: credentials.apiKey };
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (error instanceof Error) {
|
|
78
|
+
cmd.error(`Authentication required: ${error.message}`, {
|
|
79
|
+
code: 'AuthenticationRequired',
|
|
80
|
+
suggestions: [
|
|
81
|
+
`Run ${log_1.default.highlightText('mimic login')} to authenticate`,
|
|
82
|
+
`Run ${log_1.default.highlightText(`mimic login --profile ${flags.profile ?? '<profile>'}`)} to create this profile`,
|
|
83
|
+
`Or use ${log_1.default.highlightText('--api-key')} flag to provide API key directly`,
|
|
84
|
+
].filter(Boolean),
|
|
85
|
+
});
|
|
33
86
|
}
|
|
87
|
+
throw error;
|
|
34
88
|
}
|
|
35
|
-
return { apiKey };
|
|
36
89
|
}
|
|
37
90
|
}
|
|
38
|
-
Authenticate.
|
|
39
|
-
Authenticate.examples = [
|
|
40
|
-
'<%= config.bin %> <%= command.id %>',
|
|
41
|
-
'<%= config.bin %> <%= command.id %> --profile staging',
|
|
42
|
-
'<%= config.bin %> <%= command.id %> --profile production --api-key YOUR_API_KEY',
|
|
43
|
-
];
|
|
91
|
+
Authenticate.hidden = true;
|
|
44
92
|
Authenticate.flags = {
|
|
45
93
|
profile: core_1.Flags.string({
|
|
46
94
|
char: 'p',
|
package/dist/commands/build.js
CHANGED
|
@@ -6,31 +6,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const core_1 = require("@oclif/core");
|
|
7
7
|
const codegen_1 = __importDefault(require("./codegen"));
|
|
8
8
|
const compile_1 = __importDefault(require("./compile"));
|
|
9
|
+
const functions_1 = __importDefault(require("./functions"));
|
|
9
10
|
class Build extends core_1.Command {
|
|
10
11
|
async run() {
|
|
11
12
|
const { flags } = await this.parse(Build);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
await
|
|
17
|
-
const compileArgs = ['--task', task, '--manifest', manifest, '--output', output];
|
|
18
|
-
await compile_1.default.run(compileArgs);
|
|
13
|
+
await functions_1.default.runFunctions(this, flags, Build.build, 'build');
|
|
14
|
+
}
|
|
15
|
+
static async build(cmd, flags) {
|
|
16
|
+
await codegen_1.default.codegen(cmd, flags);
|
|
17
|
+
await compile_1.default.compile(cmd, flags);
|
|
19
18
|
}
|
|
20
19
|
}
|
|
21
|
-
Build.description = 'Runs code generation and then compiles the
|
|
20
|
+
Build.description = 'Runs code generation and then compiles the function';
|
|
22
21
|
Build.examples = [
|
|
23
|
-
'<%= config.bin %> <%= command.id %> --manifest ./manifest.yaml --
|
|
22
|
+
'<%= config.bin %> <%= command.id %> --manifest ./manifest.yaml --function src/function.ts --build-directory ./build --types-directory ./src/types',
|
|
24
23
|
];
|
|
25
24
|
Build.flags = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
types: core_1.Flags.string({ char: 'y', description: 'output directory for generated types', default: './src/types' }),
|
|
30
|
-
clean: core_1.Flags.boolean({
|
|
31
|
-
char: 'c',
|
|
32
|
-
description: 'remove existing generated types before generating new files',
|
|
33
|
-
default: false,
|
|
34
|
-
}),
|
|
25
|
+
...functions_1.default.flags,
|
|
26
|
+
...codegen_1.default.flags,
|
|
27
|
+
...compile_1.default.flags,
|
|
35
28
|
};
|
|
36
29
|
exports.default = Build;
|
package/dist/commands/codegen.js
CHANGED
|
@@ -42,42 +42,70 @@ const fs = __importStar(require("fs"));
|
|
|
42
42
|
const path_1 = require("path");
|
|
43
43
|
const lib_1 = require("../lib");
|
|
44
44
|
const log_1 = __importDefault(require("../log"));
|
|
45
|
+
const functions_1 = __importStar(require("./functions"));
|
|
45
46
|
class Codegen extends core_1.Command {
|
|
46
47
|
async run() {
|
|
47
48
|
const { flags } = await this.parse(Codegen);
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
await functions_1.default.runFunctions(this, flags, Codegen.codegen, 'code generation');
|
|
50
|
+
}
|
|
51
|
+
static async codegen(cmd, flags) {
|
|
52
|
+
const { manifest: manifestDir, 'types-directory': typesDir, clean } = flags;
|
|
53
|
+
const manifest = lib_1.ManifestHandler.load(cmd, manifestDir);
|
|
50
54
|
if (clean) {
|
|
51
55
|
const shouldDelete = await (0, prompts_1.confirm)({
|
|
52
|
-
message: `Are you sure you want to ${log_1.default.warnText('delete')} all the contents in ${log_1.default.highlightText(
|
|
56
|
+
message: `Are you sure you want to ${log_1.default.warnText('delete')} all the contents in ${log_1.default.highlightText(typesDir)}. This action is ${log_1.default.warnText('irreversible')}`,
|
|
53
57
|
default: false,
|
|
54
58
|
});
|
|
55
59
|
if (!shouldDelete) {
|
|
56
60
|
console.log('You can remove the --clean flag from your command');
|
|
57
61
|
console.log('Stopping initialization...');
|
|
58
|
-
|
|
62
|
+
cmd.exit(0);
|
|
59
63
|
}
|
|
60
|
-
log_1.default.startAction(`Deleting contents of ${
|
|
61
|
-
if (fs.existsSync(
|
|
62
|
-
fs.rmSync(
|
|
64
|
+
log_1.default.startAction(`Deleting contents of ${typesDir}`);
|
|
65
|
+
if (fs.existsSync(typesDir))
|
|
66
|
+
fs.rmSync(typesDir, { recursive: true, force: true });
|
|
63
67
|
}
|
|
64
68
|
log_1.default.startAction('Generating code');
|
|
65
69
|
if (Object.keys(manifest.inputs).length == 0 && Object.keys(manifest.abis).length == 0) {
|
|
66
70
|
log_1.default.stopAction();
|
|
67
71
|
return;
|
|
68
72
|
}
|
|
69
|
-
if (!fs.existsSync(
|
|
70
|
-
fs.mkdirSync(
|
|
71
|
-
generateAbisCode(manifest,
|
|
72
|
-
generateInputsCode(manifest,
|
|
73
|
+
if (!fs.existsSync(typesDir))
|
|
74
|
+
fs.mkdirSync(typesDir, { recursive: true });
|
|
75
|
+
Codegen.generateAbisCode(manifest, typesDir, manifestDir);
|
|
76
|
+
Codegen.generateInputsCode(manifest, typesDir);
|
|
73
77
|
log_1.default.stopAction();
|
|
74
78
|
}
|
|
79
|
+
static generateAbisCode(manifest, typesDir, manifestDir) {
|
|
80
|
+
for (const [contractName, path] of Object.entries(manifest.abis)) {
|
|
81
|
+
const abi = JSON.parse(fs.readFileSync((0, path_1.join)(manifestDir, '../', path), 'utf-8'));
|
|
82
|
+
const abiInterface = lib_1.AbisInterfaceGenerator.generate(abi, contractName);
|
|
83
|
+
if (abiInterface.length > 0)
|
|
84
|
+
fs.writeFileSync(`${typesDir}/${contractName}.ts`, abiInterface);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
static generateInputsCode(manifest, typesDir) {
|
|
88
|
+
const inputsInterface = lib_1.InputsInterfaceGenerator.generate(manifest.inputs);
|
|
89
|
+
if (inputsInterface.length > 0)
|
|
90
|
+
fs.writeFileSync(`${typesDir}/index.ts`, inputsInterface);
|
|
91
|
+
}
|
|
75
92
|
}
|
|
76
93
|
Codegen.description = 'Generates typed interfaces for declared inputs and ABIs from your manifest.yaml file';
|
|
77
|
-
Codegen.examples = [
|
|
94
|
+
Codegen.examples = [
|
|
95
|
+
'<%= config.bin %> <%= command.id %> --manifest ./manifest.yaml --types-directory ./types',
|
|
96
|
+
];
|
|
78
97
|
Codegen.flags = {
|
|
79
|
-
|
|
80
|
-
|
|
98
|
+
...functions_1.default.flags,
|
|
99
|
+
manifest: core_1.Flags.string({
|
|
100
|
+
char: 'm',
|
|
101
|
+
description: 'Specify a custom manifest file path',
|
|
102
|
+
default: functions_1.DefaultFunctionConfig.manifest,
|
|
103
|
+
}),
|
|
104
|
+
'types-directory': core_1.Flags.string({
|
|
105
|
+
char: 't',
|
|
106
|
+
description: 'Output directory for generated types',
|
|
107
|
+
default: functions_1.DefaultFunctionConfig['types-directory'],
|
|
108
|
+
}),
|
|
81
109
|
clean: core_1.Flags.boolean({
|
|
82
110
|
char: 'c',
|
|
83
111
|
description: 'Remove existing generated types before generating new files',
|
|
@@ -85,16 +113,3 @@ Codegen.flags = {
|
|
|
85
113
|
}),
|
|
86
114
|
};
|
|
87
115
|
exports.default = Codegen;
|
|
88
|
-
function generateAbisCode(manifest, outputDir, manifestDir) {
|
|
89
|
-
for (const [contractName, path] of Object.entries(manifest.abis)) {
|
|
90
|
-
const abi = JSON.parse(fs.readFileSync((0, path_1.join)(manifestDir, '../', path), 'utf-8'));
|
|
91
|
-
const abiInterface = lib_1.AbisInterfaceGenerator.generate(abi, contractName);
|
|
92
|
-
if (abiInterface.length > 0)
|
|
93
|
-
fs.writeFileSync(`${outputDir}/${contractName}.ts`, abiInterface);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
function generateInputsCode(manifest, outputDir) {
|
|
97
|
-
const inputsInterface = lib_1.InputsInterfaceGenerator.generate(manifest.inputs);
|
|
98
|
-
if (inputsInterface.length > 0)
|
|
99
|
-
fs.writeFileSync(`${outputDir}/index.ts`, inputsInterface);
|
|
100
|
-
}
|
package/dist/commands/compile.js
CHANGED
|
@@ -42,23 +42,26 @@ const path = __importStar(require("path"));
|
|
|
42
42
|
const ManifestHandler_1 = __importDefault(require("../lib/ManifestHandler"));
|
|
43
43
|
const packageManager_1 = require("../lib/packageManager");
|
|
44
44
|
const log_1 = __importDefault(require("../log"));
|
|
45
|
+
const functions_1 = __importStar(require("./functions"));
|
|
45
46
|
class Compile extends core_1.Command {
|
|
46
47
|
async run() {
|
|
47
48
|
const { flags } = await this.parse(Compile);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
await functions_1.default.runFunctions(this, flags, Compile.compile, 'compilation');
|
|
50
|
+
}
|
|
51
|
+
static async compile(cmd, { function: functionDir, 'build-directory': buildDir, manifest: manifestDir }) {
|
|
52
|
+
const absFunctionFile = path.resolve(functionDir);
|
|
53
|
+
const absBuildDir = path.resolve(buildDir);
|
|
54
|
+
if (!fs.existsSync(absBuildDir))
|
|
55
|
+
fs.mkdirSync(absBuildDir, { recursive: true });
|
|
53
56
|
log_1.default.startAction('Verifying Manifest');
|
|
54
|
-
const manifest = ManifestHandler_1.default.load(
|
|
57
|
+
const manifest = ManifestHandler_1.default.load(cmd, manifestDir);
|
|
55
58
|
log_1.default.startAction('Compiling');
|
|
56
59
|
const ascArgs = [
|
|
57
|
-
|
|
60
|
+
absFunctionFile,
|
|
58
61
|
'--target',
|
|
59
62
|
'release',
|
|
60
63
|
'--outFile',
|
|
61
|
-
path.join(
|
|
64
|
+
path.join(absBuildDir, 'function.wasm'),
|
|
62
65
|
'--optimize',
|
|
63
66
|
'--exportRuntime',
|
|
64
67
|
'--transform',
|
|
@@ -66,22 +69,29 @@ class Compile extends core_1.Command {
|
|
|
66
69
|
];
|
|
67
70
|
const result = (0, packageManager_1.execBinCommand)('asc', ascArgs, process.cwd());
|
|
68
71
|
if (result.status !== 0) {
|
|
69
|
-
|
|
72
|
+
cmd.error('AssemblyScript compilation failed', {
|
|
70
73
|
code: 'BuildError',
|
|
71
74
|
suggestions: ['Check the AssemblyScript file'],
|
|
72
75
|
});
|
|
73
76
|
}
|
|
74
77
|
log_1.default.startAction('Saving files');
|
|
75
|
-
fs.writeFileSync(path.join(
|
|
78
|
+
fs.writeFileSync(path.join(absBuildDir, 'manifest.json'), JSON.stringify(manifest, null, 2));
|
|
76
79
|
log_1.default.stopAction();
|
|
77
|
-
console.log(`Build complete! Artifacts in ${
|
|
80
|
+
console.log(`Build complete! Artifacts in ${absBuildDir}/`);
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
|
-
Compile.description = 'Compiles
|
|
81
|
-
Compile.examples = [
|
|
83
|
+
Compile.description = 'Compiles function';
|
|
84
|
+
Compile.examples = [
|
|
85
|
+
'<%= config.bin %> <%= command.id %> --function src/function.ts --build-directory ./build',
|
|
86
|
+
];
|
|
82
87
|
Compile.flags = {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
...functions_1.default.flags,
|
|
89
|
+
function: core_1.Flags.string({ char: 'f', description: 'Function to compile', default: functions_1.DefaultFunctionConfig.function }),
|
|
90
|
+
manifest: core_1.Flags.string({ char: 'm', description: 'Manifest to validate', default: functions_1.DefaultFunctionConfig.manifest }),
|
|
91
|
+
'build-directory': core_1.Flags.string({
|
|
92
|
+
char: 'b',
|
|
93
|
+
description: 'Output directory for compilation',
|
|
94
|
+
default: functions_1.DefaultFunctionConfig['build-directory'],
|
|
95
|
+
}),
|
|
86
96
|
};
|
|
87
97
|
exports.default = Compile;
|
package/dist/commands/deploy.js
CHANGED
|
@@ -42,53 +42,48 @@ const form_data_1 = __importDefault(require("form-data"));
|
|
|
42
42
|
const fs = __importStar(require("fs"));
|
|
43
43
|
const path_1 = require("path");
|
|
44
44
|
const errors_1 = require("../errors");
|
|
45
|
-
const packageManager_1 = require("../lib/packageManager");
|
|
46
45
|
const log_1 = __importDefault(require("../log"));
|
|
47
46
|
const authenticate_1 = __importDefault(require("./authenticate"));
|
|
47
|
+
const build_1 = __importDefault(require("./build"));
|
|
48
|
+
const functions_1 = __importDefault(require("./functions"));
|
|
48
49
|
const MIMIC_REGISTRY_DEFAULT = 'https://api-protocol.mimic.fi';
|
|
49
|
-
class Deploy extends
|
|
50
|
+
class Deploy extends core_1.Command {
|
|
50
51
|
async run() {
|
|
51
52
|
const { flags } = await this.parse(Deploy);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const compile = (0, packageManager_1.execBinCommand)('mimic', ['compile', '--output', fullInputDir], process.cwd());
|
|
61
|
-
if (compile.status !== 0)
|
|
62
|
-
this.error('Compilation failed', { code: 'BuildError', suggestions: ['Check the task source code'] });
|
|
63
|
-
}
|
|
53
|
+
await functions_1.default.runFunctions(this, flags, Deploy.deploy, 'deployment');
|
|
54
|
+
}
|
|
55
|
+
static async deploy(cmd, flags) {
|
|
56
|
+
const { 'build-directory': buildDir, 'skip-build': skipBuild, url: registryUrl } = flags;
|
|
57
|
+
const absBuildDir = (0, path_1.resolve)(buildDir);
|
|
58
|
+
let credentials = authenticate_1.default.authenticate(cmd, flags);
|
|
59
|
+
if (!skipBuild)
|
|
60
|
+
await build_1.default.build(cmd, flags);
|
|
64
61
|
log_1.default.startAction('Validating');
|
|
65
|
-
if (!fs.existsSync(
|
|
66
|
-
|
|
62
|
+
if (!fs.existsSync(absBuildDir) && skipBuild)
|
|
63
|
+
cmd.error(`Directory ${log_1.default.highlightText(absBuildDir)} does not exist`, {
|
|
67
64
|
code: 'Directory Not Found',
|
|
68
|
-
suggestions: ['Use the --
|
|
65
|
+
suggestions: ['Use the --build-directory flag to specify the correct path'],
|
|
69
66
|
});
|
|
70
|
-
const neededFiles = ['manifest.json', '
|
|
67
|
+
const neededFiles = ['manifest.json', 'function.wasm'].map((file) => (0, path_1.join)(absBuildDir, file));
|
|
71
68
|
for (const file of neededFiles) {
|
|
72
69
|
if (!fs.existsSync(file))
|
|
73
|
-
|
|
70
|
+
cmd.error(`Could not find ${file}`, {
|
|
74
71
|
code: 'File Not Found',
|
|
75
72
|
suggestions: [`Use ${log_1.default.highlightText('mimic compile')} to generate the needed files`],
|
|
76
73
|
});
|
|
77
74
|
}
|
|
78
75
|
log_1.default.startAction('Uploading to Mimic Registry');
|
|
79
|
-
const CID = await
|
|
76
|
+
const CID = await Deploy.uploadToRegistry(cmd, neededFiles, credentials, registryUrl);
|
|
80
77
|
console.log(`IPFS CID: ${log_1.default.highlightText(CID)}`);
|
|
81
78
|
log_1.default.stopAction();
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
console.log(`CID saved at ${log_1.default.highlightText(fullOutputDir)}`);
|
|
86
|
-
console.log(`Task deployed!`);
|
|
79
|
+
fs.writeFileSync((0, path_1.join)(absBuildDir, 'CID.json'), JSON.stringify({ CID }, null, 2));
|
|
80
|
+
console.log(`CID saved at ${log_1.default.highlightText(absBuildDir)}`);
|
|
81
|
+
console.log(`Function deployed!`);
|
|
87
82
|
}
|
|
88
|
-
async uploadToRegistry(files, credentials, registryUrl) {
|
|
83
|
+
static async uploadToRegistry(cmd, files, credentials, registryUrl) {
|
|
89
84
|
try {
|
|
90
|
-
const form = filesToForm(files);
|
|
91
|
-
const { data } = await axios_1.default.post(`${registryUrl}/
|
|
85
|
+
const form = this.filesToForm(files);
|
|
86
|
+
const { data } = await axios_1.default.post(`${registryUrl}/functions`, form, {
|
|
92
87
|
headers: {
|
|
93
88
|
'x-api-key': credentials.apiKey,
|
|
94
89
|
'Content-Type': `multipart/form-data; boundary=${form.getBoundary()}`,
|
|
@@ -97,43 +92,48 @@ class Deploy extends authenticate_1.default {
|
|
|
97
92
|
return data.CID;
|
|
98
93
|
}
|
|
99
94
|
catch (err) {
|
|
100
|
-
this.handleError(err, 'Failed to upload to registry');
|
|
95
|
+
this.handleError(cmd, err, 'Failed to upload to registry');
|
|
101
96
|
}
|
|
102
97
|
}
|
|
103
|
-
handleError(err, message) {
|
|
98
|
+
static handleError(cmd, err, message) {
|
|
104
99
|
if (!(err instanceof axios_1.AxiosError))
|
|
105
|
-
|
|
100
|
+
cmd.error(err);
|
|
106
101
|
const statusCode = err.response?.status;
|
|
107
102
|
if (statusCode === 400) {
|
|
108
103
|
const errMessage = err.response?.data?.content?.message || message;
|
|
109
|
-
|
|
104
|
+
cmd.error(errMessage, { code: 'Bad Request', suggestions: ['Review the uploaded files'] });
|
|
110
105
|
}
|
|
111
106
|
if (statusCode === 401)
|
|
112
|
-
|
|
107
|
+
cmd.error(message, { code: 'Unauthorized', suggestions: ['Review your key'] });
|
|
113
108
|
if (statusCode === 403)
|
|
114
|
-
|
|
115
|
-
|
|
109
|
+
cmd.error(message, { code: 'Invalid api key', suggestions: ['Review your key'] });
|
|
110
|
+
cmd.error(`${message} - ${err.message}`, { code: `${statusCode} Error`, suggestions: errors_1.GENERIC_SUGGESTION });
|
|
111
|
+
}
|
|
112
|
+
static filesToForm(files) {
|
|
113
|
+
return files.reduce((form, file) => {
|
|
114
|
+
const fileStream = fs.createReadStream(file);
|
|
115
|
+
const filename = file.split('/').pop();
|
|
116
|
+
form.append('file', fileStream, { filename });
|
|
117
|
+
return form;
|
|
118
|
+
}, new form_data_1.default());
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
|
-
Deploy.description = 'Uploads your compiled
|
|
121
|
+
Deploy.description = 'Uploads your compiled function artifacts to IPFS and registers it into the Mimic Registry';
|
|
119
122
|
Deploy.examples = [
|
|
120
|
-
'<%= config.bin %> <%= command.id %> --
|
|
123
|
+
'<%= config.bin %> <%= command.id %> --build-directory ./build',
|
|
121
124
|
'<%= config.bin %> <%= command.id %> --profile staging',
|
|
122
|
-
'<%= config.bin %> <%= command.id %> --api-key MY_KEY --
|
|
125
|
+
'<%= config.bin %> <%= command.id %> --api-key MY_KEY --build-directory ./build',
|
|
123
126
|
];
|
|
124
127
|
Deploy.flags = {
|
|
128
|
+
...functions_1.default.flags,
|
|
125
129
|
...authenticate_1.default.flags,
|
|
126
|
-
|
|
127
|
-
|
|
130
|
+
...build_1.default.flags,
|
|
131
|
+
'build-directory': core_1.Flags.string({
|
|
132
|
+
char: 'b',
|
|
133
|
+
description: 'Output directory for compilation, or input directory for deployment when --skip-build is used',
|
|
134
|
+
default: './build',
|
|
135
|
+
}),
|
|
128
136
|
url: core_1.Flags.string({ char: 'u', description: `Mimic Registry base URL`, default: MIMIC_REGISTRY_DEFAULT }),
|
|
129
|
-
'skip-
|
|
137
|
+
'skip-build': core_1.Flags.boolean({ description: 'Skip codegen and compile steps before uploading', default: false }),
|
|
130
138
|
};
|
|
131
139
|
exports.default = Deploy;
|
|
132
|
-
const filesToForm = (files) => {
|
|
133
|
-
return files.reduce((form, file) => {
|
|
134
|
-
const fileStream = fs.createReadStream(file);
|
|
135
|
-
const filename = file.split('/').pop();
|
|
136
|
-
form.append('file', fileStream, { filename });
|
|
137
|
-
return form;
|
|
138
|
-
}, new form_data_1.default());
|
|
139
|
-
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.DefaultFunctionConfig = exports.MimicConfigSchema = exports.FunctionConfigSchema = void 0;
|
|
40
|
+
const core_1 = require("@oclif/core");
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const yaml = __importStar(require("js-yaml"));
|
|
43
|
+
const zod_1 = require("zod");
|
|
44
|
+
const log_1 = __importDefault(require("../log"));
|
|
45
|
+
exports.FunctionConfigSchema = zod_1.z.object({
|
|
46
|
+
name: zod_1.z.string().min(1, 'Function name is required'),
|
|
47
|
+
manifest: zod_1.z.string().min(1, 'Manifest path is required'),
|
|
48
|
+
function: zod_1.z.string().min(1, 'Function path is required'),
|
|
49
|
+
'build-directory': zod_1.z.string().min(1, 'Build directory is required'),
|
|
50
|
+
'types-directory': zod_1.z.string().min(1, 'Types directory is required'),
|
|
51
|
+
});
|
|
52
|
+
exports.MimicConfigSchema = zod_1.z.object({
|
|
53
|
+
functions: zod_1.z.array(exports.FunctionConfigSchema).min(1, 'At least one function is required'),
|
|
54
|
+
});
|
|
55
|
+
exports.DefaultFunctionConfig = {
|
|
56
|
+
name: '',
|
|
57
|
+
manifest: 'manifest.yaml',
|
|
58
|
+
function: 'src/function.ts',
|
|
59
|
+
'build-directory': './build',
|
|
60
|
+
'types-directory': './src/types',
|
|
61
|
+
};
|
|
62
|
+
const MIMIC_CONFIG_FILE = 'mimic.yaml';
|
|
63
|
+
class Functions extends core_1.Command {
|
|
64
|
+
run() {
|
|
65
|
+
throw new Error('Method not implemented.');
|
|
66
|
+
}
|
|
67
|
+
static async runFunctions(cmd, flags, cmdLogic, cmdActions) {
|
|
68
|
+
const functions = Functions.filterFunctions(cmd, flags);
|
|
69
|
+
for (const func of functions) {
|
|
70
|
+
log_1.default.startAction(`\nStarting ${cmdActions} for function ${func.name ? func.name : func.function}`);
|
|
71
|
+
await cmdLogic(cmd, { ...flags, ...func });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
static filterFunctions(cmd, flags) {
|
|
75
|
+
if (flags['no-config']) {
|
|
76
|
+
return [{ ...exports.DefaultFunctionConfig, ...flags }];
|
|
77
|
+
}
|
|
78
|
+
if (!fs.existsSync(flags['config-file'])) {
|
|
79
|
+
if (flags['config-file'] !== MIMIC_CONFIG_FILE) {
|
|
80
|
+
cmd.error(`Could not find ${flags['config-file']}`, { code: 'ConfigNotFound' });
|
|
81
|
+
}
|
|
82
|
+
// If doesn't exist return the default with the flags the user added
|
|
83
|
+
return [{ ...exports.DefaultFunctionConfig, ...flags }];
|
|
84
|
+
}
|
|
85
|
+
const fileContents = fs.readFileSync(flags['config-file'], 'utf8');
|
|
86
|
+
const rawConfig = yaml.load(fileContents);
|
|
87
|
+
if (!rawConfig || (typeof rawConfig === 'object' && Object.keys(rawConfig).length === 0)) {
|
|
88
|
+
cmd.error(`Invalid ${MIMIC_CONFIG_FILE} configuration: file is empty.`);
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
let { functions } = exports.MimicConfigSchema.parse(rawConfig);
|
|
92
|
+
if (flags.include && flags.include.length > 0) {
|
|
93
|
+
Functions.checkMissingFunctions(cmd, functions, flags.include);
|
|
94
|
+
functions = functions.filter((fn) => flags.include.includes(fn.name));
|
|
95
|
+
}
|
|
96
|
+
if (flags.exclude && flags.exclude.length > 0) {
|
|
97
|
+
Functions.checkMissingFunctions(cmd, functions, flags.exclude);
|
|
98
|
+
functions = functions.filter((fn) => !flags.exclude.includes(fn.name));
|
|
99
|
+
}
|
|
100
|
+
return functions;
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
if (error instanceof zod_1.z.ZodError) {
|
|
104
|
+
const errors = error.errors.map((e) => `${e.path.join('.')}: ${e.message}`).join('\n');
|
|
105
|
+
cmd.error(`Invalid ${MIMIC_CONFIG_FILE} configuration:\n${errors}`, { code: 'InvalidConfig' });
|
|
106
|
+
}
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
static checkMissingFunctions(cmd, functions, filteredFunctionNames) {
|
|
111
|
+
const functionNames = new Set(functions.map((fn) => fn.name));
|
|
112
|
+
const missingFunctions = filteredFunctionNames.filter((name) => !functionNames.has(name));
|
|
113
|
+
if (missingFunctions.length > 0) {
|
|
114
|
+
cmd.warn(`Functions not found in ${MIMIC_CONFIG_FILE}: ${missingFunctions.join(', ')}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
Functions.hidden = true;
|
|
119
|
+
Functions.flags = {
|
|
120
|
+
'config-file': core_1.Flags.string({
|
|
121
|
+
description: `Path to the ${MIMIC_CONFIG_FILE} file, this overrides other parameters like build-directory and function`,
|
|
122
|
+
default: MIMIC_CONFIG_FILE,
|
|
123
|
+
}),
|
|
124
|
+
'no-config': core_1.Flags.boolean({
|
|
125
|
+
description: `Do not read ${MIMIC_CONFIG_FILE}; use defaults and explicit flags instead`,
|
|
126
|
+
default: false,
|
|
127
|
+
}),
|
|
128
|
+
include: core_1.Flags.string({
|
|
129
|
+
description: `When ${MIMIC_CONFIG_FILE} exists, only run tasks with these names (space-separated)`,
|
|
130
|
+
multiple: true,
|
|
131
|
+
exclusive: ['exclude'],
|
|
132
|
+
char: 'i',
|
|
133
|
+
}),
|
|
134
|
+
exclude: core_1.Flags.string({
|
|
135
|
+
description: `When ${MIMIC_CONFIG_FILE} exists, exclude tasks with these names (space-separated)`,
|
|
136
|
+
multiple: true,
|
|
137
|
+
exclusive: ['include'],
|
|
138
|
+
char: 'e',
|
|
139
|
+
}),
|
|
140
|
+
};
|
|
141
|
+
exports.default = Functions;
|
package/dist/commands/init.js
CHANGED
|
@@ -46,32 +46,34 @@ const log_1 = __importDefault(require("../log"));
|
|
|
46
46
|
class Init extends core_1.Command {
|
|
47
47
|
async run() {
|
|
48
48
|
const { args, flags } = await this.parse(Init);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
await Init.init(this, { ...flags, ...args });
|
|
50
|
+
}
|
|
51
|
+
static async init(cmd, flags) {
|
|
52
|
+
const { directory, force } = flags;
|
|
53
|
+
const absDir = path.resolve(directory);
|
|
54
|
+
if (force && fs.existsSync(absDir) && fs.readdirSync(absDir).length > 0) {
|
|
53
55
|
const shouldDelete = process.env.NODE_ENV === 'test'
|
|
54
56
|
? true
|
|
55
57
|
: await (0, prompts_1.confirm)({
|
|
56
|
-
message: `Are you sure you want to ${log_1.default.warnText('delete')} all the contents in ${log_1.default.highlightText(
|
|
58
|
+
message: `Are you sure you want to ${log_1.default.warnText('delete')} all the contents in ${log_1.default.highlightText(absDir)}. This action is ${log_1.default.warnText('irreversible')}`,
|
|
57
59
|
default: false,
|
|
58
60
|
});
|
|
59
61
|
if (!shouldDelete) {
|
|
60
62
|
console.log('You can remove the --force flag from your command');
|
|
61
63
|
console.log('Stopping initialization...');
|
|
62
|
-
|
|
64
|
+
cmd.exit(0);
|
|
63
65
|
}
|
|
64
|
-
log_1.default.startAction(`Deleting contents of ${
|
|
66
|
+
log_1.default.startAction(`Deleting contents of ${absDir}`);
|
|
65
67
|
// Delete files individually instead of removing the entire directory to preserve
|
|
66
68
|
// the directory reference. This prevents issues when the directory is the current
|
|
67
69
|
// working directory, as removing it would cause the reference to be lost.
|
|
68
|
-
for (const file of fs.readdirSync(
|
|
69
|
-
fs.rmSync(path.join(
|
|
70
|
+
for (const file of fs.readdirSync(absDir)) {
|
|
71
|
+
fs.rmSync(path.join(absDir, file), { recursive: true, force: true });
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
log_1.default.startAction('Creating files');
|
|
73
|
-
if (fs.existsSync(
|
|
74
|
-
|
|
75
|
+
if (fs.existsSync(absDir) && fs.readdirSync(absDir).length > 0) {
|
|
76
|
+
cmd.error(`Directory ${log_1.default.highlightText(absDir)} is not empty`, {
|
|
75
77
|
code: 'DirectoryNotEmpty',
|
|
76
78
|
suggestions: [
|
|
77
79
|
'You can specify the directory as a positional argument',
|
|
@@ -79,32 +81,32 @@ class Init extends core_1.Command {
|
|
|
79
81
|
],
|
|
80
82
|
});
|
|
81
83
|
}
|
|
82
|
-
if (!fs.existsSync(
|
|
83
|
-
fs.mkdirSync(
|
|
84
|
+
if (!fs.existsSync(absDir)) {
|
|
85
|
+
fs.mkdirSync(absDir, { recursive: true });
|
|
84
86
|
}
|
|
85
87
|
try {
|
|
86
|
-
await (0, simple_git_1.default)().clone('https://github.com/mimic-protocol/init-template.git',
|
|
87
|
-
const gitDir = path.join(
|
|
88
|
+
await (0, simple_git_1.default)().clone('https://github.com/mimic-protocol/init-template.git', absDir);
|
|
89
|
+
const gitDir = path.join(absDir, '.git');
|
|
88
90
|
if (fs.existsSync(gitDir))
|
|
89
91
|
fs.rmSync(gitDir, { recursive: true, force: true });
|
|
90
92
|
}
|
|
91
93
|
catch (error) {
|
|
92
|
-
|
|
94
|
+
cmd.error(`Failed to clone template repository. Details: ${error}`);
|
|
93
95
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
Init.installDependencies(absDir);
|
|
97
|
+
Init.runCodegen(absDir);
|
|
96
98
|
log_1.default.stopAction();
|
|
97
99
|
console.log('New project initialized!');
|
|
98
100
|
}
|
|
99
|
-
installDependencies(
|
|
101
|
+
static installDependencies(absDir) {
|
|
100
102
|
if (process.env.NODE_ENV === 'test')
|
|
101
103
|
return;
|
|
102
|
-
(0, packageManager_1.installDependencies)(
|
|
104
|
+
(0, packageManager_1.installDependencies)(absDir);
|
|
103
105
|
}
|
|
104
|
-
runCodegen(
|
|
106
|
+
static runCodegen(absDir) {
|
|
105
107
|
if (process.env.NODE_ENV === 'test')
|
|
106
108
|
return;
|
|
107
|
-
(0, packageManager_1.execBinCommand)('mimic', ['codegen'],
|
|
109
|
+
(0, packageManager_1.execBinCommand)('mimic', ['codegen'], absDir);
|
|
108
110
|
}
|
|
109
111
|
}
|
|
110
112
|
Init.description = 'Initializes a new Mimic-compatible project structure in the specified directory';
|
package/dist/commands/login.js
CHANGED
|
@@ -8,9 +8,12 @@ const core_1 = require("@oclif/core");
|
|
|
8
8
|
const CredentialsManager_1 = require("../lib/CredentialsManager");
|
|
9
9
|
const log_1 = __importDefault(require("../log"));
|
|
10
10
|
const authenticate_1 = __importDefault(require("./authenticate"));
|
|
11
|
-
class Login extends
|
|
11
|
+
class Login extends core_1.Command {
|
|
12
12
|
async run() {
|
|
13
13
|
const { flags } = await this.parse(Login);
|
|
14
|
+
await Login.login(this, flags);
|
|
15
|
+
}
|
|
16
|
+
static async login(cmd, flags) {
|
|
14
17
|
const { profile: profileInput, 'api-key': apiKeyFlag } = flags;
|
|
15
18
|
let apiKey;
|
|
16
19
|
let profileName = profileInput;
|
|
@@ -47,14 +50,14 @@ class Login extends authenticate_1.default {
|
|
|
47
50
|
catch (error) {
|
|
48
51
|
if (error instanceof Error && error.message.includes('User force closed')) {
|
|
49
52
|
console.log('\nLogin cancelled');
|
|
50
|
-
|
|
53
|
+
cmd.exit(0);
|
|
51
54
|
}
|
|
52
55
|
throw error;
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
|
-
|
|
58
|
+
Login.saveAndConfirm(cmd, profileName || CredentialsManager_1.CredentialsManager.getDefaultProfileName(), apiKey, flags['force-login']);
|
|
56
59
|
}
|
|
57
|
-
async saveAndConfirm(profileName, apiKey, forceLogin) {
|
|
60
|
+
static async saveAndConfirm(cmd, profileName, apiKey, forceLogin) {
|
|
58
61
|
try {
|
|
59
62
|
const credentialsManager = CredentialsManager_1.CredentialsManager.getDefault();
|
|
60
63
|
if (credentialsManager.profileExists(profileName) && !forceLogin) {
|
|
@@ -73,14 +76,14 @@ class Login extends authenticate_1.default {
|
|
|
73
76
|
console.log(`✓ Credentials saved for profile ${log_1.default.highlightText(profileName)}`);
|
|
74
77
|
console.log(` Location: ${log_1.default.highlightText('~/.mimic/credentials')}`);
|
|
75
78
|
console.log();
|
|
76
|
-
console.log(`You can now deploy
|
|
79
|
+
console.log(`You can now deploy functions using: ${log_1.default.highlightText('mimic deploy')}`);
|
|
77
80
|
if (profileName !== CredentialsManager_1.CredentialsManager.getDefaultProfileName()) {
|
|
78
81
|
console.log(`Or with your profile: ${log_1.default.highlightText(`mimic deploy --profile ${profileName}`)}`);
|
|
79
82
|
}
|
|
80
83
|
}
|
|
81
84
|
catch (error) {
|
|
82
85
|
if (error instanceof Error)
|
|
83
|
-
|
|
86
|
+
cmd.error(`Failed to save credentials: ${error.message}`);
|
|
84
87
|
throw error;
|
|
85
88
|
}
|
|
86
89
|
}
|
package/dist/commands/logout.js
CHANGED
|
@@ -10,10 +10,13 @@ const log_1 = __importDefault(require("../log"));
|
|
|
10
10
|
class Logout extends core_1.Command {
|
|
11
11
|
async run() {
|
|
12
12
|
const { flags } = await this.parse(Logout);
|
|
13
|
+
await Logout.logout(this, flags);
|
|
14
|
+
}
|
|
15
|
+
static async logout(cmd, flags) {
|
|
13
16
|
const { profile: profileName, force } = flags;
|
|
14
17
|
const profiles = CredentialsManager_1.CredentialsManager.getDefault().getProfiles();
|
|
15
18
|
if (!profiles.includes(profileName)) {
|
|
16
|
-
|
|
19
|
+
cmd.error(`Profile '${profileName}' does not exist`, {
|
|
17
20
|
code: 'ProfileNotFound',
|
|
18
21
|
suggestions: profiles.length > 0
|
|
19
22
|
? [`Available profiles: ${profiles.join(', ')}`]
|
|
@@ -27,7 +30,7 @@ class Logout extends core_1.Command {
|
|
|
27
30
|
});
|
|
28
31
|
if (!shouldRemove) {
|
|
29
32
|
console.log('Logout cancelled');
|
|
30
|
-
|
|
33
|
+
cmd.exit(0);
|
|
31
34
|
}
|
|
32
35
|
}
|
|
33
36
|
log_1.default.startAction(`Removing credentials for profile ${profileName}`);
|
|
@@ -8,6 +8,9 @@ const CredentialsManager_1 = require("../lib/CredentialsManager");
|
|
|
8
8
|
const log_1 = __importDefault(require("../log"));
|
|
9
9
|
class Profiles extends core_1.Command {
|
|
10
10
|
async run() {
|
|
11
|
+
await Profiles.profiles();
|
|
12
|
+
}
|
|
13
|
+
static async profiles() {
|
|
11
14
|
const profiles = CredentialsManager_1.CredentialsManager.getDefault().getProfiles();
|
|
12
15
|
if (profiles.length === 0) {
|
|
13
16
|
console.log('No profiles found.');
|
package/dist/commands/test.js
CHANGED
|
@@ -32,32 +32,46 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
35
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
39
|
const core_1 = require("@oclif/core");
|
|
37
40
|
const path = __importStar(require("path"));
|
|
38
41
|
const packageManager_1 = require("../lib/packageManager");
|
|
42
|
+
const build_1 = __importDefault(require("./build"));
|
|
43
|
+
const functions_1 = __importDefault(require("./functions"));
|
|
39
44
|
class Test extends core_1.Command {
|
|
40
45
|
async run() {
|
|
41
46
|
const { flags } = await this.parse(Test);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (cp.status !== 0)
|
|
51
|
-
this.exit(cp.status ?? 1);
|
|
52
|
-
}
|
|
47
|
+
await Test.test(this, flags);
|
|
48
|
+
}
|
|
49
|
+
static async test(cmd, flags) {
|
|
50
|
+
const { directory, 'skip-build': skipBuild } = flags;
|
|
51
|
+
const baseDir = path.resolve('./');
|
|
52
|
+
const testPath = path.join(baseDir, directory);
|
|
53
|
+
if (!skipBuild)
|
|
54
|
+
await functions_1.default.runFunctions(cmd, flags, build_1.default.build, 'building');
|
|
53
55
|
const result = (0, packageManager_1.execBinCommand)('tsx', ['./node_modules/mocha/bin/mocha.js', `${testPath}/**/*.spec.ts`], baseDir);
|
|
54
|
-
|
|
56
|
+
cmd.exit(result.status ?? 1);
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
|
-
Test.description = 'Runs
|
|
58
|
-
Test.examples = ['<%= config.bin %> <%= command.id %> --directory ./'];
|
|
59
|
+
Test.description = 'Runs function tests';
|
|
60
|
+
Test.examples = ['<%= config.bin %> <%= command.id %> --directory ./tests'];
|
|
59
61
|
Test.flags = {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
...{
|
|
63
|
+
...functions_1.default.flags,
|
|
64
|
+
include: {
|
|
65
|
+
...functions_1.default.flags.include,
|
|
66
|
+
description: functions_1.default.flags.include.description + '. Only for building, it does not affect testing',
|
|
67
|
+
},
|
|
68
|
+
exclude: {
|
|
69
|
+
...functions_1.default.flags.exclude,
|
|
70
|
+
description: functions_1.default.flags.exclude.description + '. Only for building, it does not affect testing',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
...build_1.default.flags,
|
|
74
|
+
directory: core_1.Flags.string({ char: 'd', description: 'Path to the testing directory', default: './tests' }),
|
|
75
|
+
'skip-build': core_1.Flags.boolean({ description: 'Skip build before testing', default: false }),
|
|
62
76
|
};
|
|
63
77
|
exports.default = Test;
|
|
@@ -129,39 +129,6 @@ class CredentialsManager {
|
|
|
129
129
|
profiles[profileName] = { apiKey };
|
|
130
130
|
this.writeCredentials(profiles);
|
|
131
131
|
}
|
|
132
|
-
getProfile(profileName = DEFAULT_PROFILE) {
|
|
133
|
-
const credentialsDir = this.getBaseDir();
|
|
134
|
-
const credentialsPath = this.getCredentialsPath();
|
|
135
|
-
if (!fs.existsSync(credentialsDir)) {
|
|
136
|
-
throw new Error(`No credentials directory found at ${credentialsDir}. Run 'mimic login' to authenticate.`);
|
|
137
|
-
}
|
|
138
|
-
if (!fs.existsSync(credentialsPath)) {
|
|
139
|
-
throw new Error(`No credentials file found. Run 'mimic login' to authenticate.`);
|
|
140
|
-
}
|
|
141
|
-
const profiles = this.readCredentials();
|
|
142
|
-
if (!profiles[profileName]) {
|
|
143
|
-
const availableProfiles = Object.keys(profiles);
|
|
144
|
-
const suggestion = availableProfiles.length > 0
|
|
145
|
-
? `Available profiles: ${availableProfiles.join(', ')}`
|
|
146
|
-
: `No profiles found. Run 'mimic login' to create one.`;
|
|
147
|
-
throw new Error(`Profile '${profileName}' not found. ${suggestion}`);
|
|
148
|
-
}
|
|
149
|
-
const credentials = profiles[profileName];
|
|
150
|
-
if (!credentials.apiKey || credentials.apiKey.trim() === '') {
|
|
151
|
-
throw new Error(`Profile '${profileName}' has no API key. Run 'mimic login --profile ${profileName}' to update credentials.`);
|
|
152
|
-
}
|
|
153
|
-
return credentials;
|
|
154
|
-
}
|
|
155
|
-
getCredentials(profileName = DEFAULT_PROFILE) {
|
|
156
|
-
try {
|
|
157
|
-
return this.getProfile(profileName);
|
|
158
|
-
}
|
|
159
|
-
catch (error) {
|
|
160
|
-
if (error instanceof Error)
|
|
161
|
-
throw new Error(`Authentication required: ${error.message}`);
|
|
162
|
-
throw error;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
132
|
getProfiles() {
|
|
166
133
|
const profiles = this.readCredentials();
|
|
167
134
|
return Object.keys(profiles);
|
|
@@ -17,7 +17,7 @@ exports.default = {
|
|
|
17
17
|
` ${inputsMapping}`,
|
|
18
18
|
'}',
|
|
19
19
|
'',
|
|
20
|
-
'// The class name is intentionally lowercase and plural to resemble a namespace when used in a
|
|
20
|
+
'// The class name is intentionally lowercase and plural to resemble a namespace when used in a function.',
|
|
21
21
|
'export class inputs {',
|
|
22
22
|
` ${inputsClass}`,
|
|
23
23
|
'}',
|