From a096a982fe20666c98afe91198b11663a1fa477d Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Wed, 30 Oct 2024 14:25:18 +0100 Subject: [PATCH 1/3] Build .mjs (ES Modules) as well Use these to use import over require --- dist/alchemy-json_api.js | 78 ++++++++++++----------------- dist/alchemy-json_api.mjs | 100 ++++++++++++++++++++++++++++++++++++++ dist/deserialize.js | 47 ++++++------------ dist/deserialize.mjs | 62 +++++++++++++++++++++++ package.json | 1 + rollup.config.js | 18 +++++-- 6 files changed, 223 insertions(+), 83 deletions(-) create mode 100644 dist/alchemy-json_api.mjs create mode 100644 dist/deserialize.mjs diff --git a/dist/alchemy-json_api.js b/dist/alchemy-json_api.js index 3123e91..d63102d 100644 --- a/dist/alchemy-json_api.js +++ b/dist/alchemy-json_api.js @@ -9,51 +9,40 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau var structuredClone__default = /*#__PURE__*/_interopDefaultLegacy(structuredClone); function deserialize(originalResponse) { - var response = structuredClone__default["default"](originalResponse); - - var included = response.included || []; - + const response = structuredClone__default["default"](originalResponse); + const included = response.included || []; if (Array.isArray(response.data)) { - return response.data.map(function (data) { + return response.data.map(data => { return parseJsonApiSimpleResourceData(data, included, false); }); } else { return parseJsonApiSimpleResourceData(response.data, included, false); } } - function parseJsonApiSimpleResourceData(data, included, useCache, options) { if (!included.cached) { included.cached = {}; } - if (!(data.type in included.cached)) { included.cached[data.type] = {}; } - if (useCache && data.id in included.cached[data.type]) { return included.cached[data.type][data.id]; } - - var attributes = data.attributes || {}; - var resource = attributes; + const attributes = data.attributes || {}; + const resource = attributes; resource.id = data.id; included.cached[data.type][data.id] = resource; - if (data.relationships) { - for (var _i = 0, _Object$keys = Object.keys(data.relationships); _i < _Object$keys.length; _i++) { - var relationName = _Object$keys[_i]; - var relationRef = data.relationships[relationName]; - + for (const relationName of Object.keys(data.relationships)) { + const relationRef = data.relationships[relationName]; if (Array.isArray(relationRef.data)) { - (function () { - var items = []; - relationRef.data.forEach(function (relationData) { - var item = findJsonApiIncluded(included, relationData.type, relationData.id); - items.push(item); - }); - resource[relationName] = items; - })(); + const items = []; + relationRef.data.forEach(relationData => { + const item = findJsonApiIncluded(included, relationData.type, relationData.id); + items.push(item); + }); + resource[relationName] = items; } else if (relationRef && relationRef.data) { resource[relationName] = findJsonApiIncluded(included, relationRef.data.type, relationRef.data.id); } else { @@ -61,63 +50,56 @@ function parseJsonApiSimpleResourceData(data, included, useCache, options) { } } } - return resource; } - function findJsonApiIncluded(included, type, id, options) { - var found = null; - included.forEach(function (item) { + let found = null; + included.forEach(item => { if (item.type === type && item.id === id) { found = parseJsonApiSimpleResourceData(item, included, true); } }); - if (!found) { found = { - id: id + id }; } - return found; } +// Recursively filters all deprecated elements and essences from collection function filterDeprecatedElements(elements) { - var els = []; - elements.forEach(function (element) { - var _element$nested_eleme, _element$nestedElemen, _element$essences; - - if (((_element$nested_eleme = element.nested_elements) === null || _element$nested_eleme === void 0 ? void 0 : _element$nested_eleme.length) > 0) { + const els = []; + elements.forEach(element => { + if (element.nested_elements?.length > 0) { element.nested_elements = filterDeprecatedElements(element.nested_elements); } - - if (((_element$nestedElemen = element.nestedElements) === null || _element$nestedElemen === void 0 ? void 0 : _element$nestedElemen.length) > 0) { + if (element.nestedElements?.length > 0) { element.nestedElements = filterDeprecatedElements(element.nestedElements); } - - if (((_element$essences = element.essences) === null || _element$essences === void 0 ? void 0 : _element$essences.length) > 0) { - element.essences = element.essences.filter(function (essence) { + if (element.essences?.length > 0) { + element.essences = element.essences.filter(essence => { return !essence.deprecated; }); } - if (!element.deprecated) { els.push(element); } }); return els; -} // Returns deserialized page without deprecated content - +} +// Returns deserialized page without deprecated content function deserializePage(pageData) { - var page = deserialize(pageData); + const page = deserialize(pageData); page.elements = filterDeprecatedElements(page.elements); return page; -} // Returns deserialized pages without deprecated content +} +// Returns deserialized pages without deprecated content function deserializePages(pagesData) { - var pages = deserialize(pagesData); - pages.forEach(function (page) { + const pages = deserialize(pagesData); + pages.forEach(page => { page.elements = filterDeprecatedElements(page.elements); }); return pages; diff --git a/dist/alchemy-json_api.mjs b/dist/alchemy-json_api.mjs new file mode 100644 index 0000000..c498ffc --- /dev/null +++ b/dist/alchemy-json_api.mjs @@ -0,0 +1,100 @@ +import structuredClone from '@ungap/structured-clone'; + +function deserialize(originalResponse) { + const response = structuredClone(originalResponse); + const included = response.included || []; + if (Array.isArray(response.data)) { + return response.data.map(data => { + return parseJsonApiSimpleResourceData(data, included, false); + }); + } else { + return parseJsonApiSimpleResourceData(response.data, included, false); + } +} +function parseJsonApiSimpleResourceData(data, included, useCache, options) { + if (!included.cached) { + included.cached = {}; + } + if (!(data.type in included.cached)) { + included.cached[data.type] = {}; + } + if (useCache && data.id in included.cached[data.type]) { + return included.cached[data.type][data.id]; + } + const attributes = data.attributes || {}; + const resource = attributes; + resource.id = data.id; + included.cached[data.type][data.id] = resource; + if (data.relationships) { + for (const relationName of Object.keys(data.relationships)) { + const relationRef = data.relationships[relationName]; + if (Array.isArray(relationRef.data)) { + const items = []; + relationRef.data.forEach(relationData => { + const item = findJsonApiIncluded(included, relationData.type, relationData.id); + items.push(item); + }); + resource[relationName] = items; + } else if (relationRef && relationRef.data) { + resource[relationName] = findJsonApiIncluded(included, relationRef.data.type, relationRef.data.id); + } else { + resource[relationName] = null; + } + } + } + return resource; +} +function findJsonApiIncluded(included, type, id, options) { + let found = null; + included.forEach(item => { + if (item.type === type && item.id === id) { + found = parseJsonApiSimpleResourceData(item, included, true); + } + }); + if (!found) { + found = { + id + }; + } + return found; +} + +// Recursively filters all deprecated elements and essences from collection +function filterDeprecatedElements(elements) { + const els = []; + elements.forEach(element => { + if (element.nested_elements?.length > 0) { + element.nested_elements = filterDeprecatedElements(element.nested_elements); + } + if (element.nestedElements?.length > 0) { + element.nestedElements = filterDeprecatedElements(element.nestedElements); + } + if (element.essences?.length > 0) { + element.essences = element.essences.filter(essence => { + return !essence.deprecated; + }); + } + if (!element.deprecated) { + els.push(element); + } + }); + return els; +} + +// Returns deserialized page without deprecated content +function deserializePage(pageData) { + const page = deserialize(pageData); + page.elements = filterDeprecatedElements(page.elements); + return page; +} + +// Returns deserialized pages without deprecated content +function deserializePages(pagesData) { + const pages = deserialize(pagesData); + pages.forEach(page => { + page.elements = filterDeprecatedElements(page.elements); + }); + return pages; +} + +export { deserialize, deserializePage, deserializePages }; diff --git a/dist/deserialize.js b/dist/deserialize.js index 866faee..b8b77ae 100644 --- a/dist/deserialize.js +++ b/dist/deserialize.js @@ -9,51 +9,40 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau var structuredClone__default = /*#__PURE__*/_interopDefaultLegacy(structuredClone); function deserialize(originalResponse) { - var response = structuredClone__default["default"](originalResponse); - - var included = response.included || []; - + const response = structuredClone__default["default"](originalResponse); + const included = response.included || []; if (Array.isArray(response.data)) { - return response.data.map(function (data) { + return response.data.map(data => { return parseJsonApiSimpleResourceData(data, included, false); }); } else { return parseJsonApiSimpleResourceData(response.data, included, false); } } - function parseJsonApiSimpleResourceData(data, included, useCache, options) { if (!included.cached) { included.cached = {}; } - if (!(data.type in included.cached)) { included.cached[data.type] = {}; } - if (useCache && data.id in included.cached[data.type]) { return included.cached[data.type][data.id]; } - - var attributes = data.attributes || {}; - var resource = attributes; + const attributes = data.attributes || {}; + const resource = attributes; resource.id = data.id; included.cached[data.type][data.id] = resource; - if (data.relationships) { - for (var _i = 0, _Object$keys = Object.keys(data.relationships); _i < _Object$keys.length; _i++) { - var relationName = _Object$keys[_i]; - var relationRef = data.relationships[relationName]; - + for (const relationName of Object.keys(data.relationships)) { + const relationRef = data.relationships[relationName]; if (Array.isArray(relationRef.data)) { - (function () { - var items = []; - relationRef.data.forEach(function (relationData) { - var item = findJsonApiIncluded(included, relationData.type, relationData.id); - items.push(item); - }); - resource[relationName] = items; - })(); + const items = []; + relationRef.data.forEach(relationData => { + const item = findJsonApiIncluded(included, relationData.type, relationData.id); + items.push(item); + }); + resource[relationName] = items; } else if (relationRef && relationRef.data) { resource[relationName] = findJsonApiIncluded(included, relationRef.data.type, relationRef.data.id); } else { @@ -61,24 +50,20 @@ function parseJsonApiSimpleResourceData(data, included, useCache, options) { } } } - return resource; } - function findJsonApiIncluded(included, type, id, options) { - var found = null; - included.forEach(function (item) { + let found = null; + included.forEach(item => { if (item.type === type && item.id === id) { found = parseJsonApiSimpleResourceData(item, included, true); } }); - if (!found) { found = { - id: id + id }; } - return found; } diff --git a/dist/deserialize.mjs b/dist/deserialize.mjs new file mode 100644 index 0000000..9290883 --- /dev/null +++ b/dist/deserialize.mjs @@ -0,0 +1,62 @@ +import structuredClone from '@ungap/structured-clone'; + +function deserialize(originalResponse) { + const response = structuredClone(originalResponse); + const included = response.included || []; + if (Array.isArray(response.data)) { + return response.data.map(data => { + return parseJsonApiSimpleResourceData(data, included, false); + }); + } else { + return parseJsonApiSimpleResourceData(response.data, included, false); + } +} +function parseJsonApiSimpleResourceData(data, included, useCache, options) { + if (!included.cached) { + included.cached = {}; + } + if (!(data.type in included.cached)) { + included.cached[data.type] = {}; + } + if (useCache && data.id in included.cached[data.type]) { + return included.cached[data.type][data.id]; + } + const attributes = data.attributes || {}; + const resource = attributes; + resource.id = data.id; + included.cached[data.type][data.id] = resource; + if (data.relationships) { + for (const relationName of Object.keys(data.relationships)) { + const relationRef = data.relationships[relationName]; + if (Array.isArray(relationRef.data)) { + const items = []; + relationRef.data.forEach(relationData => { + const item = findJsonApiIncluded(included, relationData.type, relationData.id); + items.push(item); + }); + resource[relationName] = items; + } else if (relationRef && relationRef.data) { + resource[relationName] = findJsonApiIncluded(included, relationRef.data.type, relationRef.data.id); + } else { + resource[relationName] = null; + } + } + } + return resource; +} +function findJsonApiIncluded(included, type, id, options) { + let found = null; + included.forEach(item => { + if (item.type === type && item.id === id) { + found = parseJsonApiSimpleResourceData(item, included, true); + } + }); + if (!found) { + found = { + id + }; + } + return found; +} + +export { deserialize }; diff --git a/package.json b/package.json index f205cd2..e5d6247 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "Thomas von Deyen" ], "main": "dist/alchemy-json_api.js", + "module": "dist/alchemy-json_api.mjs", "files": [ "dist" ], diff --git a/rollup.config.js b/rollup.config.js index 86e9f4c..37f838b 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -10,6 +10,10 @@ export default [ { file: "dist/alchemy-json_api.js", format: "cjs" + }, + { + file: "dist/alchemy-json_api.mjs", + format: "esm" } ], plugins, @@ -17,10 +21,16 @@ export default [ }, { input: "src/deserialize.js", - output: { - file: "dist/deserialize.js", - format: "cjs" - }, + output: [ + { + file: "dist/deserialize.js", + format: "cjs" + }, + { + file: "dist/deserialize.mjs", + format: "esm" + } + ], plugins, external } From d6170b465963c85e8882d756b5c8f202f801bb8d Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Wed, 30 Oct 2024 15:37:42 +0100 Subject: [PATCH 2/3] CI: Run lint with Alchemy 7.3 The main branch (which is the default branch if the ALCHEMY_BRANCH env is not set) does not work with this Gem yet. We do not need the latest version of Alchemy for the linting to work. --- .github/workflows/lint.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 50ced0b..aaa5b71 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,6 +9,8 @@ concurrency: jobs: Standard: runs-on: ubuntu-latest + env: + ALCHEMY_BRANCH: 7.3-stable steps: - name: Checkout code uses: actions/checkout@v4 From bff068f38d9b9200c269c88f99d25190e5f74cb8 Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Wed, 30 Oct 2024 15:41:30 +0100 Subject: [PATCH 3/3] chore: Fix linting --- app/controllers/alchemy/json_api/base_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/alchemy/json_api/base_controller.rb b/app/controllers/alchemy/json_api/base_controller.rb index 10eb88d..cc4e924 100644 --- a/app/controllers/alchemy/json_api/base_controller.rb +++ b/app/controllers/alchemy/json_api/base_controller.rb @@ -26,7 +26,7 @@ def log_error(exception) logger = Rails.logger return unless logger - message = +"\n#{exception.class} (#{exception.message}):\n" + message = "\n#{exception.class} (#{exception.message}):\n" message << exception.annotated_source_code.to_s if exception.respond_to?(:annotated_source_code) message << " " << exception.backtrace.join("\n ") logger.fatal("#{message}\n\n")