Skip to content

Commit

Permalink
feat(core) Update extendAppRaw to override arrays as well as objects …
Browse files Browse the repository at this point in the history
…[PDE-5114] (#813)

* update extendAppRaw and tests
  • Loading branch information
kreddlear authored Jul 2, 2024
1 parent fa58f80 commit 480684e
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 38 deletions.
119 changes: 111 additions & 8 deletions packages/core/integration-test/integration-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,21 @@ const doTest = (runner) => {
});
});

it('should handle array of [appRawOverrideHash, appRawExtension]', () => {
it('should handle array of [appRawOverrideHash, appRawExtension] and override inputFields', () => {
const definition = {
creates: {
foo: {
key: 'foo',
noun: 'Foo',
operation: {
perform: { source: 'return [{id: 12345}]' },
inputFields: [{ key: 'name', type: 'string' }],
inputFields: [
{ key: 'name', type: 'string' },
{ key: 'testing', type: 'string' },
],
sample: {
id: 123,
},
},
},
},
Expand All @@ -209,11 +215,13 @@ const doTest = (runner) => {
const definitionExtension = {
creates: {
foo: {
noun: 'Foobar',
key: 'foo',
noun: 'Foo',
operation: {
perform: { source: 'return [{id: 12345}]' },
inputFields: [{ key: 'message', type: 'string' }],
sample: {
id: 678,
name: 'sample',
},
},
},
Expand All @@ -234,10 +242,105 @@ const doTest = (runner) => {
};

return runner(event).then((response) => {
response.results.should.eql([
{ key: 'name', type: 'string' },
{ key: 'message', type: 'string' },
]);
response.results.should.eql([{ key: 'message', type: 'string' }]);
});
});

it('should handle array of [appRawOverrideHash, appRawExtension] and override specific inputField', () => {
const definition = {
creates: {
foo: {
key: 'foo',
noun: 'Foo',
operation: {
perform: { source: 'return [{id: 12345}]' },
inputFields: [{ key: 'message', type: 'integer' }],
},
},
},
};

mocky.mockRpcCall(definition);

const definitionExtension = {
creates: {
foo: {
noun: 'Foobar',
operation: {
inputFields: [{ key: 'message', type: 'string' }],
},
},
},
};

const definitionHash = crypto
.createHash('md5')
.update(JSON.stringify(definition))
.digest('hex');

const event = {
command: 'execute',
method: 'creates.foo.operation.inputFields',
appRawOverride: [definitionHash, definitionExtension],
rpc_base: 'https://mock.zapier.com/platform/rpc/cli',
token: 'fake',
};

return runner(event).then((response) => {
response.results.should.eql([{ key: 'message', type: 'string' }]);
});
});

it('should handle array of [appRawOverrideHash, appRawExtension] and overrides with an operation create key', () => {
const definition = {
creates: {
operation: {
key: 'operation',
operation: {
perform: { source: 'return [{id: 12345}]' },
inputFields: [
{ key: 'name', type: 'string' },
{ key: 'testing', type: 'string' },
],
sample: {
id: 123,
},
},
},
},
};

mocky.mockRpcCall(definition);

const definitionExtension = {
creates: {
operation: {
operation: {
perform: { source: 'return [{id: 123}]' },
inputFields: [{ key: 'message', type: 'string' }],
sample: {
name: 'sample',
},
},
},
},
};

const definitionHash = crypto
.createHash('md5')
.update(JSON.stringify(definition))
.digest('hex');

const event = {
command: 'execute',
method: 'creates.operation.operation.inputFields',
appRawOverride: [definitionHash, definitionExtension],
rpc_base: 'https://mock.zapier.com/platform/rpc/cli',
token: 'fake',
};

return runner(event).then((response) => {
response.results.should.eql([{ key: 'message', type: 'string' }]);
});
});

Expand Down
61 changes: 31 additions & 30 deletions packages/core/src/tools/create-lambda-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,43 @@ const environmentTools = require('./environment');
const schemaTools = require('./schema');
const ZapierPromise = require('./promise');

const RequestSchema = require('zapier-platform-schema/lib/schemas/RequestSchema');
const FunctionSchema = require('zapier-platform-schema/lib/schemas/FunctionSchema');

const isRequestOrFunction = (obj) => {
const isDefinedPrimitive = (value) => {
return (
RequestSchema.validate(obj).valid || FunctionSchema.validate(obj).valid
value === null ||
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'boolean'
);
};

const extendAppRaw = (base, extension) => {
const keysToOverride = [
'test',
'perform',
'performList',
'performSubscribe',
'performUnsubscribe',
];
const concatArrayAndOverrideKeys = (objValue, srcValue, key) => {
if (Array.isArray(objValue) && Array.isArray(srcValue)) {
return objValue.concat(srcValue);
}
const shouldFullyReplace = (path) => {
// covers inputFields, outputFields, sample, throttle, etc
const isOperation = path[path.length - 2] === 'operation';
return isOperation;
};

if (
// Do full replacement when it comes to keysToOverride
keysToOverride.indexOf(key) !== -1 &&
_.isPlainObject(srcValue) &&
_.isPlainObject(objValue) &&
isRequestOrFunction(srcValue) &&
isRequestOrFunction(objValue)
) {
return srcValue;
const extendAppRaw = (base, extension, path) => {
if (extension === undefined) {
return base;
} else if (isDefinedPrimitive(extension)) {
return extension;
} else if (Array.isArray(extension)) {
return [...extension];
} else if (_.isPlainObject(extension)) {
path = path || [];
if (shouldFullyReplace(path)) {
return extension;
} else {
const baseObject = _.isPlainObject(base) ? base : {};
const result = { ...baseObject };
for (const [key, value] of Object.entries(extension)) {
const newPath = [...path, key];
result[key] = extendAppRaw(baseObject[key], value, newPath);
}
return result;
}

return undefined;
};
return _.mergeWith(base, extension, concatArrayAndOverrideKeys);
}
throw new TypeError('Unexpected type');
};

const getAppRawOverride = (rpc, appRawOverride) => {
Expand Down

0 comments on commit 480684e

Please sign in to comment.