Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ spec/support/templates/fooTemplate/bar/cfg/cfg.txt

# logs
*.log

# python
*.pyc
38 changes: 22 additions & 16 deletions packages/ant-cli/spec/bin/ant.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -773,14 +773,15 @@ ant.js --help plugin add`)
._ant
.pluginController
.getPlugin('Core')
.addFunction = jest.fn(async (name, func, runtime, type, isGlobal) => {
.addFunction = jest.fn(async (name, func, runtime, version, type, isGlobal) => {
expect(name).toBe('myfunc');
expect(func).toBe('path/to/myfunc');
expect(runtime).toBe('nodejs');
expect(version).toBe('6');
expect(type).toBe('lib');
expect(isGlobal).toBe(false);
});
antCli._yargs.parse('function add myfunc path/to/myfunc nodejs');
antCli._yargs.parse('function add myfunc path/to/myfunc nodejs 6');
});

test('should work with global flag', done => {
Expand All @@ -797,14 +798,15 @@ ant.js --help plugin add`)
._ant
.pluginController
.getPlugin('Core')
.addFunction = jest.fn(async (name, path, runtime, type, isGlobal) => {
.addFunction = jest.fn(async (name, path, runtime, version, type, isGlobal) => {
expect(name).toBe('myfunc');
expect(path).toBe('/path/to/myfunc');
expect(runtime).toBe('nodejs');
expect(version).toBe('6');
expect(type).toBe('lib');
expect(isGlobal).toBe(true);
});
antCli._yargs.parse('function add myfunc /path/to/myfunc nodejs --global');
antCli._yargs.parse('function add myfunc /path/to/myfunc nodejs 6 --global');
});

test('should work with template', done => {
Expand All @@ -821,7 +823,7 @@ ant.js --help plugin add`)
._ant
.pluginController
.getPlugin('Core')
.addFunction = jest.fn(async (name, path, runtime, type, isGlobal, template) => {
.addFunction = jest.fn(async (name, path, runtime, version, type, isGlobal, template) => {
expect(name).toBe('myfunc');
expect(template).toBe('/path/to/my/template');
});
Expand Down Expand Up @@ -1062,13 +1064,14 @@ ant.js --help plugin add`)
._ant
.pluginController
.getPlugin('Core')
.addRuntime = jest.fn(async (name, bin, extensions, isGlobal) => {
.addRuntime = jest.fn(async (name, version, bin, extensions, isGlobal) => {
expect(name).toBe('myruntime');
expect(version).toBe('10');
expect(bin).toBe(path.resolve(process.cwd(), bin));
expect(extensions).toEqual(['nodejs', 'python']);
expect(extensions).toEqual(['foo', 'bar']);
expect(isGlobal).toBe(false);
});
antCli._yargs.parse('runtime add myruntime path/to/myruntime nodejs python');
antCli._yargs.parse('runtime add myruntime 10 path/to/myruntime foo bar');
});

test('should work with global flag', done => {
Expand All @@ -1085,14 +1088,15 @@ ant.js --help plugin add`)
._ant
.pluginController
.getPlugin('Core')
.addRuntime = jest.fn(async (name, bin, extensions, isGlobal) => {
.addRuntime = jest.fn(async (name, version, bin, extensions, isGlobal) => {
expect(name).toBe('myruntime');
expect(version).toBe('10');
expect(bin).toBe('/path/to/myruntime');
console.log(extensions);
expect(extensions).toEqual(['nodejs', 'python']);
expect(isGlobal).toBe(true);
});
antCli._yargs.parse('runtime add myruntime /path/to/myruntime nodejs python --global');
antCli._yargs.parse('runtime add myruntime 10 /path/to/myruntime nodejs python --global');
});

test('should handle any errors', done => {
Expand All @@ -1113,7 +1117,7 @@ ant.js --help plugin add`)
.addRuntime = jest.fn(async () => {
throw new Error('Mocked error');
});
antCli._yargs.parse('runtime add myruntime /path/to/myruntime nodejs python');
antCli._yargs.parse('runtime add myruntime 10 /path/to/myruntime nodejs python');
});
});

Expand All @@ -1132,11 +1136,12 @@ ant.js --help plugin add`)
._ant
.pluginController
.getPlugin('Core')
.removeRuntime = jest.fn(async (name, isGlobal) => {
.removeRuntime = jest.fn(async (name, version, isGlobal) => {
expect(name).toBe('myruntime');
expect(version).toBe('5');
expect(isGlobal).toBe(false);
});
antCli._yargs.parse('runtime remove myruntime');
antCli._yargs.parse('runtime remove myruntime 5');
});

test('should work with global flag', done => {
Expand All @@ -1153,11 +1158,12 @@ ant.js --help plugin add`)
._ant
.pluginController
.getPlugin('Core')
.removeRuntime = jest.fn(async (name, isGlobal) => {
.removeRuntime = jest.fn(async (name, version, isGlobal) => {
expect(name).toBe('myruntime');
expect(version).toBe('5');
expect(isGlobal).toBe(true);
});
antCli._yargs.parse('runtime remove myruntime --global');
antCli._yargs.parse('runtime remove myruntime 5 --global');
});

test('should handle any errors', done => {
Expand All @@ -1178,7 +1184,7 @@ ant.js --help plugin add`)
.removeRuntime = jest.fn(async () => {
throw new Error('Mocked error');
});
antCli._yargs.parse('runtime remove myruntime');
antCli._yargs.parse('runtime remove myruntime 5');
});
});

Expand Down
15 changes: 15 additions & 0 deletions packages/ant-util-tests/functions/objectLibFunction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @fileoverview Object lib function for testing purposes.
*/

const { Observable } = require('rxjs');

module.exports = () => {
return Observable.create(
subscriber => {
subscriber.next({ foo: 'bar' });
subscriber.complete();
return () => {};
}
);
};
50 changes: 31 additions & 19 deletions packages/ant/lib/config/Config.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,11 @@ template remove command should do nothing`);
* Adds a {@link BinFunction} or {@link LibFunction} into this configuration.
*
* @param {!BinFunction|LibFunction} antFunction The function to be added
* @param {Boolean} specifyRuntimeVersion Flag indicating the runtime version
* should be specified
* @returns {Config} This configuration instance.
*/
addFunction(antFunction) {
addFunction(antFunction, specifyRuntimeVersion = false) {
assert(antFunction, 'Param "antFunction" is required');
assert((antFunction instanceof BinFunction || antFunction instanceof LibFunction),
'Param "antFunction" must be an instance of BinFunction or LibFunction');
Expand Down Expand Up @@ -318,7 +320,9 @@ function add command will OVERRIDE the current function`);
attributes.items.push(new Pair(new Scalar('bin'), new Scalar(bin)));
} else {
attributes.items.push(new Pair(new Scalar('handler'), new Scalar(handler)));
attributes.items.push(new Pair(new Scalar('runtime'), new Scalar(runtime.name)));
attributes.items.push(new Pair(new Scalar('runtime'), new Scalar(
specifyRuntimeVersion ? `${runtime.name} ${runtime.version}` : runtime.name
)));
}
console.log(`Function "${name}" successfully added on configuration file ${this._path}`);
// Document has changed, resets the cached JSON
Expand Down Expand Up @@ -371,21 +375,21 @@ function remove command should do nothing`);
assert(runtime, 'Param "runtime" is required');
assert(runtime instanceof Runtime,
'Param "runtime" must be an instance of Runtime');
const { name, bin, extensions } = runtime;
const { name, bin, extensions, version } = runtime;

// Ensure the "runtimes" root element exists,
// and it is a Pair<"runtimes", Map>
const runtimes = this._ensureRootCollectionNode('runtimes', Map);

if (this._filterNodeFromCollectionByKey(runtimes, name)) {
console.log(`Runtime "${name}" already found on the configuration file. \
const entryName = `${name} ${version}`;
if (this._filterNodeFromCollectionByKey(runtimes, entryName)) {
console.log(`Runtime "${entryName}" already found on the configuration file. \
runtime add command will OVERRIDE the current runtime`);
}
logger.log(`Adding runtime ${name} into configuration file ${this._path}`);
logger.log(`Adding runtime ${entryName} into configuration file ${this._path}`);

// Creates the brand new Runtime node and adds its to the runtimes Map.
runtimes.items.push(new Pair(
new Scalar(name),
new Scalar(entryName),
this._createAttributeMap({ bin, extensions })
));

Expand All @@ -398,28 +402,35 @@ runtime add command will OVERRIDE the current runtime`);
* Removes an {@link Runtime} from this configuration.
*
* @param {!String} runtime The name of the {@link Runtime} to be removed
* @param {!String} version The version of the {@link Runtime} to be removed
* @returns {Config} This configuration instance.
*/
removeRuntime(runtime) {
removeRuntime(runtime, version) {
assert(runtime, 'Could not remove runtime: param "runtime" is required');
assert(
typeof runtime === 'string',
'Could not remove runtime: param "runtime" should be String'
);
assert(version, 'Could not remove runtime: param "version" is required');
assert(
typeof version === 'string',
'Could not remove runtime: param "version" should be String'
);
const runtimes = this._findRootCollectionNode('runtimes', Map);
if (!runtimes) {
console.log('No "runtimes" was found on configuration file. runtime \
remove command should do nothing');
return this;
}
if(this._filterNodeFromCollectionByKey(runtimes, runtime)) {
console.log(`Runtime "${runtime}" successfully removed from \
const entryName = `${runtime} ${version}`;
if(this._filterNodeFromCollectionByKey(runtimes, entryName)) {
console.log(`Runtime "${entryName}" successfully removed from \
configuration file ${this._path}`);

// Document has changed, resets the cached JSON
this._cachedJson = null;
} else {
console.log(`Runtime "${runtime}" was not found on configuration file. \
console.log(`Runtime "${entryName}" was not found on configuration file. \
runtime remove command should do nothing`);
}
return this;
Expand Down Expand Up @@ -668,21 +679,22 @@ provider "${providerName}"`
}
return Object.keys(functions).map(name => {
const func = functions[name];
const { bin, handler, runtime } = func;
const { bin, handler, runtime, args } = func;
try {
if (bin) {
return new BinFunction(runtimeController.ant, name, bin);
} else if (handler) {
let runtimeInstance;
if (runtime) {
runtimeInstance = runtimeController.getRuntime(runtime);
const [name, version] = runtime.split(' ');
runtimeInstance = runtimeController.getRuntime(name, version);
if (!runtimeInstance) {
throw new AntError(`Runtime ${runtime} was not found`);
throw new AntError(`Runtime ${name} ${version} was not found`);
}
} else {
runtimeInstance = runtimeController.defaultRuntime;
}
return new LibFunction(runtimeController.ant, name, handler, runtimeInstance);
return new LibFunction(runtimeController.ant, name, handler, runtimeInstance, args);
}
throw new AntError(`Function type unknown: ${JSON.stringify(func)}`);
} catch (e) {
Expand All @@ -705,14 +717,14 @@ configuration file', e);
return [];
}
return Object.keys(runtimes).map(
name => new Runtime(ant, name, runtimes[name].bin, runtimes[name].extensions)
key => new Runtime(ant, key.split(' ')[0], runtimes[key].bin, runtimes[key].extensions, undefined, key.split(' ')[1])
);
}

/**
* Parses the {@link Runtime} from the configuration file "defaultRuntime" string.
* Parses the {@link Runtime} from the configuration file "runtime" string.
*
* @param {Object} defaultRuntime The "defaultRuntime" object from the configuration file
* @param {String} defaultRuntime The "runtime" value from the configuration file
* @param {!RuntimeController} runtimeController The {@link RuntimeController}
* used to find the default {@link Runtime}
* @returns {Runtime} The {@link Runtime} instance, given the default runtime name
Expand Down
28 changes: 25 additions & 3 deletions packages/ant/lib/functions/LibFunction.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class LibFunction extends AntFunction {
* @throws {AssertionError} If "ant", "name", "handler" or "runtime" params
* are not valid.
*/
constructor(ant, name, handler, runtime) {
constructor(ant, name, handler, runtime, args) {
super(ant, name);

assert(
Expand All @@ -51,6 +51,13 @@ class LibFunction extends AntFunction {
* @private
*/
this._runtime = runtime;

/**
* Contains the fixed arguments that will be used when running the function.
* @type {Array<String>}
* @private
*/
this._args = args || [];
}

/**
Expand All @@ -71,6 +78,15 @@ class LibFunction extends AntFunction {
return this._runtime;
}

/**
* Contains the function fixed execution argumnets.
* @type {Array<String>}
* @readonly
*/
get args() {
return this._args;
}

/**
* Runs the function. It can receive different arguments depending on the
* function instance.
Expand All @@ -80,16 +96,22 @@ class LibFunction extends AntFunction {
run() {
logger.log(`Running lib function ${this.name}...`);

const args = JSON.stringify(
this._args.concat(Array.from(arguments))
);
try {
return this._runtime.run([
this._handler,
JSON.stringify(Array.from(arguments))
args
]).pipe(map(data => {
// JSON fails to parse 'undefined', but not '"undefined"'
try {
return JSON.parse(data);
} catch (e) {
return undefined;
if (typeof data === 'string' && data.trim() === 'undefined') {
return undefined;
}
return data;
}
}));
} catch (e) {
Expand Down
Loading