UNPKG

node-red-contrib-rollun-aws-sp-api

Version:

Node-RED nodes to access AWS Selling Partner API

248 lines (217 loc) 8.69 kB
<script type="text/javascript"> function getMethodName(method, path) { return `${method} ${path}`; } async function fetchModelsList() { if (window.modelsListCache) { return window.modelsListCache; } const result = await fetch('/aws-sp-api/models'); const json = await result.json(); if (result.ok) { return window.modelsListCache = json.models; } else { throw new Error('Failed to fetch models list: ' + JSON.stringify(json)); } } async function fetchVersion(id, version) { if (!window.versionCache) { window.versionCache = {}; } if (window.versionCache[id + version]) { return window.versionCache[id + version]; } const result = await fetch(`/aws-sp-api/models/${id}/versions/${version}`); const json = await result.json(); if (result.ok) { return window.versionCache[id + version] = json; } else { throw new Error('Failed to fetch schema: ' + JSON.stringify(json)); } } RED.nodes.registerType('rollun-aws-sp-api', { category: 'Rollun AWS SP API', inputs: 1, outputs: 2, color: "#bce4d0", icon: "aws-sp-api.png", paletteLabel: 'AWS SP API', defaults: { name: { value: '', required: false, }, config: { value: '', required: true, type: 'rollun-aws-sp-api-credentials', }, schema: { value: '', required: true, }, operation: { value: '', required: true, }, server: { value: 0, }, debug: { value: false, }, body: { value: 'msg|body', }, pathParams: { value: 'msg|pathParams', }, query: { value: 'msg|query', }, }, label: function () { return this.name || this.operation || 'AWS SP API Request'; }, labelStyle: function () { return this.name ? 'node_label_italic' : ''; }, outputLabels: function (index) { return [ 'error', 'success', ][index] }, oneditsave: function() { const node = this; const existingConfig = node._config; const current = node; // for some reason node red does not detect changes in // - schema // - operation // because of this, we need to manually detect changes // and mark node as dirty const somethingChanged = current.schema !== existingConfig.schema || current.operation !== existingConfig.operation; console.log('somethingChanged', somethingChanged); if (somethingChanged) { node.changed = true; RED.events.emit('workspace:dirty', { dirty: true }) } }, oneditprepare: async function () { try { const node = this; window.utils.makeTypedInput('body', [{ value: "msg", label: "msg." }], undefined, this.body); window.utils.makeTypedInput('pathParams', [{ value: "msg", label: "msg." }], undefined, this.pathParams); window.utils.makeTypedInput('query', [{ value: "msg", label: "msg." }], undefined, this.query); function setSchemaDescription(id, version, title, description) { $('#schema-description').html(description || title || ''); const openapiLink = `${window.location.origin}/aws-sp-api/models/${id}/versions/${version}`; const swaggerEditorLink = `https://editor.swagger.io/?url=${openapiLink}`; $('#schema-link').attr('href', swaggerEditorLink); } async function renderInputSchema(schemas, selectFirst = false) { $('#node-input-schema') .html(schemas.map(({ id, name, version, title, description }, schemaIndex) => { const key = `${id}|${version}`; let isSelected = false; if (selectFirst && schemaIndex === 0) { setSchemaDescription(id, version, title, description); isSelected = true; node.schema = key; } else if (key === node.schema){ setSchemaDescription(id, version, title, description); isSelected = true; } return `<option value="${key}" ${isSelected ? 'selected' : ''}>${name} | ${version}</option>`; }).join('\n')); } async function renderInputOperation(selectFirst = false) { if (node.schema) { let firstSelected = false; const [schemaId, schemaVersion] = node.schema.split('|'); const version = await fetchVersion(schemaId, schemaVersion); $('#node-input-operation') .html(Object.entries(version.paths).map(([path, methods], pathIndex) => { return Object.entries(methods).map(([method, { summary, description }]) => { const operation = getMethodName(method, path); let isSelected = false; if (selectFirst && pathIndex === 0 && firstSelected === false) { $('#operation-description').html(summary || description || ''); isSelected = true; firstSelected = true; node.operation = operation; } else if (operation === node.operation){ $('#operation-description').html(summary || description || ''); isSelected = true; } return `<option value="${operation}" ${isSelected ? 'selected' : ''}>${method.toUpperCase()} ${path}</option>`; }) }).join('\n')); } } async function render() { const models = await fetchModelsList(); const flatten = models.map(({id, name, versions}) => versions.map((version) => ({ id, name, ...version }) )).flat(); $('#node-input-schema').on('change', async (e) => { node.schema = e.target.value; await renderInputSchema(flatten); await renderInputOperation(true); }); $('#node-input-operation').on('change', async (e) => { node.operation = e.target.value; await renderInputOperation(); }); await renderInputSchema(flatten, !node.schema); await renderInputOperation(!node.operation); } await render(); } catch (err) { console.error(err); $('#aws-sp-api-errors').html(` <div class="ui-state-error"> <p> <span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span> <strong>ERROR:</strong> <pre>${err.stack}</pre> </p> </div> `); } }, }); </script> <script type="text/html" data-template-name="rollun-aws-sp-api"> <div id="aws-sp-api-errors"></div> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> <span>Name:</span></label> <input type="text" id="node-input-name" /> </div> <div class="form-row" style> <label for="node-input-config"><i class="fa fa-book"></i> <span>Credentials:</span></label> <input type="text" id="node-input-config"> </div> <div class="form-tips"><b>Tip:</b> Rest API Always return errors & payload. This node in case of success sets payload to <strong>msg.payload</strong> and errors to <strong>msg.payload.error</strong></div> <div class="form-row"> <label for="node-input-schema"><i class="fa fa-tasks"></i> <span>Schema:</span></label> <select style="width: 100%" id="node-input-schema"></select> <pre id="schema-description"></pre> <a id="schema-link" style="margin-bottom: 10px; color: cornflowerblue; text-decoration: underline;" target="_blank">Open Swagger UI in new tab</a> </div> <div class="form-row"> <label for="node-input-operation"><i class="fa fa-tasks"></i> <span>Operation:</span></label> <select style="width: 100%" id="node-input-operation"></select> <pre id="operation-description"></pre> <div class="form-row"> <span> Debug: add request to output</span> <input style="margin-left: 5px; margin-bottom: 6px" type="checkbox" id="node-input-debug"> </div> <h3>Inputs:</h3> <div class="form-row" id="body"></div> <div class="form-row" id="pathParams"></div> <div class="form-row" id="query"></div> <div class="form-tips"><b>Tip:</b> If you do not have some of the inputs, leave them empty.</div> </script>