@ivfuture/ecomm-orchestration
Advanced tools
Comparing version 1.0.1 to 1.1.0
export * from "./joiner"; | ||
export * from "./transaction"; | ||
export * from "./workflow"; |
@@ -18,2 +18,4 @@ "use strict"; | ||
__exportStar(require("./joiner"), exports); | ||
__exportStar(require("./transaction"), exports); | ||
__exportStar(require("./workflow"), exports); | ||
//# sourceMappingURL=index.js.map |
import { RemoteJoinerQuery } from "@ivfuture/ecomm-types"; | ||
declare class GraphQLParser { | ||
private variables?; | ||
private variables; | ||
private ast; | ||
constructor(input: string, variables?: { | ||
[key: string]: unknown; | ||
} | undefined); | ||
constructor(input: string, variables?: Record<string, unknown>); | ||
private parseValueNode; | ||
private parseArguments; | ||
private parseDirectives; | ||
private createDirectivesMap; | ||
private extractEntities; | ||
@@ -11,0 +11,0 @@ parseQuery(): RemoteJoinerQuery; |
"use strict"; | ||
var __values = (this && this.__values) || function(o) { | ||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
if (m) return m.call(o); | ||
if (o && typeof o.length === "number") return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var graphql_1 = require("graphql"); | ||
var GraphQLParser = /** @class */ (function () { | ||
function GraphQLParser(input, variables) { | ||
const graphql_1 = require("graphql"); | ||
class GraphQLParser { | ||
constructor(input, variables = {}) { | ||
this.variables = variables; | ||
this.ast = (0, graphql_1.parse)(input); | ||
this.variables = variables || {}; | ||
this.variables = variables; | ||
} | ||
GraphQLParser.prototype.parseValueNode = function (valueNode) { | ||
var e_1, _a; | ||
var _this = this; | ||
parseValueNode(valueNode) { | ||
switch (valueNode.kind) { | ||
case graphql_1.Kind.VARIABLE: | ||
var variableName = valueNode.name.value; | ||
const variableName = valueNode.name.value; | ||
return this.variables ? this.variables[variableName] : undefined; | ||
@@ -65,18 +27,8 @@ case graphql_1.Kind.INT: | ||
case graphql_1.Kind.LIST: | ||
return valueNode.values.map(function (v) { return _this.parseValueNode(v); }); | ||
return valueNode.values.map((v) => this.parseValueNode(v)); | ||
case graphql_1.Kind.OBJECT: | ||
var obj = {}; | ||
try { | ||
for (var _b = __values(valueNode.fields), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var field = _c.value; | ||
obj[field.name.value] = this.parseValueNode(field.value); | ||
} | ||
let obj = {}; | ||
for (const field of valueNode.fields) { | ||
obj[field.name.value] = this.parseValueNode(field.value); | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
return obj; | ||
@@ -86,10 +38,9 @@ default: | ||
} | ||
}; | ||
GraphQLParser.prototype.parseArguments = function (args) { | ||
var _this = this; | ||
} | ||
parseArguments(args) { | ||
if (!args.length) { | ||
return; | ||
} | ||
return args.map(function (arg) { | ||
var value = _this.parseValueNode(arg.value); | ||
return args.map((arg) => { | ||
const value = this.parseValueNode(arg.value); | ||
return { | ||
@@ -100,36 +51,54 @@ name: arg.name.value, | ||
}); | ||
}; | ||
GraphQLParser.prototype.extractEntities = function (node, parentName, mainService) { | ||
var _this = this; | ||
if (parentName === void 0) { parentName = ""; } | ||
if (mainService === void 0) { mainService = ""; } | ||
var entities = []; | ||
node.selections.forEach(function (selection) { | ||
} | ||
parseDirectives(directives) { | ||
return directives.map((directive) => ({ | ||
name: directive.name.value, | ||
args: this.parseArguments(directive.arguments || []), | ||
})); | ||
} | ||
createDirectivesMap(selectionSet) { | ||
const directivesMap = {}; | ||
let hasDirectives = false; | ||
selectionSet.selections.forEach((field) => { | ||
const fieldName = field.name.value; | ||
const fieldDirectives = this.parseDirectives(field.directives || []); | ||
if (fieldDirectives.length > 0) { | ||
hasDirectives = true; | ||
directivesMap[fieldName] = fieldDirectives; | ||
} | ||
}); | ||
return hasDirectives ? directivesMap : undefined; | ||
} | ||
extractEntities(node, parentName = "", mainService = "") { | ||
const entities = []; | ||
node.selections.forEach((selection) => { | ||
if (selection.kind === "Field") { | ||
var fieldNode = selection; | ||
if (fieldNode.selectionSet) { | ||
var entityName = parentName | ||
? "".concat(parentName, ".").concat(fieldNode.name.value) | ||
: fieldNode.name.value; | ||
var nestedEntity = { | ||
property: entityName.replace("".concat(mainService, "."), ""), | ||
fields: fieldNode.selectionSet.selections.map(function (field) { return field.name.value; }), | ||
args: _this.parseArguments(fieldNode.arguments), | ||
}; | ||
entities.push(nestedEntity); | ||
entities.push.apply(entities, __spreadArray([], __read(_this.extractEntities(fieldNode.selectionSet, entityName, mainService)), false)); | ||
const fieldNode = selection; | ||
if (!fieldNode.selectionSet) { | ||
return; | ||
} | ||
const propName = fieldNode.name.value; | ||
const entityName = parentName ? `${parentName}.${propName}` : propName; | ||
const nestedEntity = { | ||
property: entityName.replace(`${mainService}.`, ""), | ||
fields: fieldNode.selectionSet.selections.map((field) => field.name.value), | ||
args: this.parseArguments(fieldNode.arguments || []), | ||
directives: this.createDirectivesMap(fieldNode.selectionSet), | ||
}; | ||
entities.push(nestedEntity); | ||
entities.push(...this.extractEntities(fieldNode.selectionSet, entityName, mainService)); | ||
} | ||
}); | ||
return entities; | ||
}; | ||
GraphQLParser.prototype.parseQuery = function () { | ||
var queryDefinition = this.ast.definitions.find(function (definition) { return definition.kind === "OperationDefinition"; }); | ||
} | ||
parseQuery() { | ||
const queryDefinition = this.ast.definitions.find((definition) => definition.kind === "OperationDefinition"); | ||
if (!queryDefinition) { | ||
throw new Error("No query found"); | ||
} | ||
var rootFieldNode = queryDefinition.selectionSet | ||
const rootFieldNode = queryDefinition.selectionSet | ||
.selections[0]; | ||
var remoteJoinConfig = { | ||
service: rootFieldNode.name.value, | ||
const propName = rootFieldNode.name.value; | ||
const remoteJoinConfig = { | ||
alias: propName, | ||
fields: [], | ||
@@ -142,10 +111,10 @@ expands: [], | ||
if (rootFieldNode.selectionSet) { | ||
remoteJoinConfig.fields = rootFieldNode.selectionSet.selections.map(function (field) { return field.name.value; }); | ||
remoteJoinConfig.expands = this.extractEntities(rootFieldNode.selectionSet, rootFieldNode.name.value, rootFieldNode.name.value); | ||
remoteJoinConfig.fields = rootFieldNode.selectionSet.selections.map((field) => field.name.value); | ||
remoteJoinConfig.directives = this.createDirectivesMap(rootFieldNode.selectionSet); | ||
remoteJoinConfig.expands = this.extractEntities(rootFieldNode.selectionSet, propName, propName); | ||
} | ||
return remoteJoinConfig; | ||
}; | ||
return GraphQLParser; | ||
}()); | ||
} | ||
} | ||
exports.default = GraphQLParser; | ||
//# sourceMappingURL=graphql-ast.js.map |
@@ -0,1 +1,2 @@ | ||
export * from "./helpers"; | ||
export * from "./remote-joiner"; |
@@ -17,3 +17,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./helpers"), exports); | ||
__exportStar(require("./remote-joiner"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -1,19 +0,24 @@ | ||
import { JoinerServiceConfig, RemoteExpandProperty, RemoteJoinerQuery } from "@ivfuture/ecomm-types"; | ||
import { ModuleJoinerConfig, RemoteExpandProperty, RemoteJoinerQuery } from "@ivfuture/ecomm-types"; | ||
export type RemoteFetchDataCallback = (expand: RemoteExpandProperty, keyField: string, ids?: (unknown | unknown[])[], relationship?: any) => Promise<{ | ||
data: unknown[] | { | ||
[path: string]: unknown; | ||
}; | ||
path?: string; | ||
}>; | ||
export declare class RemoteJoiner { | ||
private serviceConfigs; | ||
private remoteFetchData; | ||
private serviceConfigs; | ||
private serviceConfigCache; | ||
private implodeMapping; | ||
private static filterFields; | ||
private static getNestedItems; | ||
private static createRelatedDataMap; | ||
static parseQuery(graphqlQuery: string, variables?: any): RemoteJoinerQuery; | ||
constructor(serviceConfigs: JoinerServiceConfig[], remoteFetchData: (expand: RemoteExpandProperty, pkField: string, ids?: (unknown | unknown[])[], relationship?: any) => Promise<{ | ||
data: unknown[] | { | ||
[path: string]: unknown[]; | ||
}; | ||
path?: string; | ||
}>); | ||
static parseQuery(graphqlQuery: string, variables?: Record<string, unknown>): RemoteJoinerQuery; | ||
constructor(serviceConfigs: ModuleJoinerConfig[], remoteFetchData: RemoteFetchDataCallback); | ||
setFetchDataCallback(remoteFetchData: RemoteFetchDataCallback): void; | ||
private buildReferences; | ||
private findServiceConfig; | ||
private getServiceConfig; | ||
private cacheServiceConfig; | ||
private fetchData; | ||
private handleFieldAliases; | ||
private handleExpands; | ||
@@ -20,0 +25,0 @@ private expandProperty; |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __values = (this && this.__values) || function(o) { | ||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
if (m) return m.call(o); | ||
if (o && typeof o.length === "number") return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -90,49 +7,43 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
exports.RemoteJoiner = void 0; | ||
var ecomm_utils_1 = require("@ivfuture/ecomm-utils"); | ||
var graphql_ast_1 = __importDefault(require("./graphql-ast")); | ||
var BASE_PATH = "_root"; | ||
var RemoteJoiner = /** @class */ (function () { | ||
function RemoteJoiner(serviceConfigs, remoteFetchData) { | ||
this.remoteFetchData = remoteFetchData; | ||
this.serviceConfigCache = new Map(); | ||
this.serviceConfigs = this.buildReferences(serviceConfigs); | ||
} | ||
RemoteJoiner.filterFields = function (data, fields, expands) { | ||
if (!fields) { | ||
const ecomm_utils_1 = require("@ivfuture/ecomm-utils"); | ||
const graphql_ast_1 = __importDefault(require("./graphql-ast")); | ||
const BASE_PATH = "_root"; | ||
class RemoteJoiner { | ||
static filterFields(data, fields, expands) { | ||
if (!fields || !data) { | ||
return data; | ||
} | ||
var filteredData = fields.reduce(function (acc, field) { | ||
acc[field] = data === null || data === void 0 ? void 0 : data[field]; | ||
const filteredData = fields.reduce((acc, field) => { | ||
const fieldValue = data?.[field]; | ||
if ((0, ecomm_utils_1.isDefined)(fieldValue)) { | ||
acc[field] = data?.[field]; | ||
} | ||
return acc; | ||
}, {}); | ||
if (expands) { | ||
var _loop_1 = function (key) { | ||
var expand = expands[key]; | ||
for (const key in expands) { | ||
const expand = expands[key]; | ||
if (expand) { | ||
if (Array.isArray(data[key])) { | ||
filteredData[key] = data[key].map(function (item) { | ||
return RemoteJoiner.filterFields(item, expand.fields, expand.expands); | ||
}); | ||
filteredData[key] = data[key].map((item) => RemoteJoiner.filterFields(item, expand.fields, expand.expands)); | ||
} | ||
else { | ||
filteredData[key] = RemoteJoiner.filterFields(data[key], expand.fields, expand.expands); | ||
const filteredFields = RemoteJoiner.filterFields(data[key], expand.fields, expand.expands); | ||
if ((0, ecomm_utils_1.isDefined)(filteredFields)) { | ||
filteredData[key] = RemoteJoiner.filterFields(data[key], expand.fields, expand.expands); | ||
} | ||
} | ||
} | ||
}; | ||
for (var key in expands) { | ||
_loop_1(key); | ||
} | ||
} | ||
return filteredData; | ||
}; | ||
RemoteJoiner.getNestedItems = function (items, property) { | ||
return items | ||
.flatMap(function (item) { return item[property]; }) | ||
.filter(function (item) { return item !== undefined; }); | ||
}; | ||
RemoteJoiner.createRelatedDataMap = function (relatedDataArray, joinFields) { | ||
return relatedDataArray.reduce(function (acc, data) { | ||
var joinValues = joinFields.map(function (field) { return data[field]; }); | ||
var key = joinValues.length === 1 ? joinValues[0] : joinValues.join(","); | ||
var isArray = Array.isArray(acc[key]); | ||
return (Object.keys(filteredData).length && filteredData) || undefined; | ||
} | ||
static getNestedItems(items, property) { | ||
return items.flatMap((item) => item?.[property]); | ||
} | ||
static createRelatedDataMap(relatedDataArray, joinFields) { | ||
return relatedDataArray.reduce((acc, data) => { | ||
const joinValues = joinFields.map((field) => data[field]); | ||
const key = joinValues.length === 1 ? joinValues[0] : joinValues.join(","); | ||
let isArray = Array.isArray(acc[key]); | ||
if ((0, ecomm_utils_1.isDefined)(acc[key]) && !isArray) { | ||
@@ -150,476 +61,477 @@ acc[key] = [acc[key]]; | ||
}, {}); | ||
}; | ||
RemoteJoiner.parseQuery = function (graphqlQuery, variables) { | ||
var parser = new graphql_ast_1.default(graphqlQuery, variables); | ||
} | ||
static parseQuery(graphqlQuery, variables) { | ||
const parser = new graphql_ast_1.default(graphqlQuery, variables); | ||
return parser.parseQuery(); | ||
}; | ||
RemoteJoiner.prototype.buildReferences = function (serviceConfigs) { | ||
var e_1, _a, e_2, _b, e_3, _c; | ||
var _d, _e; | ||
var expandedRelationships = new Map(); | ||
try { | ||
for (var serviceConfigs_1 = __values(serviceConfigs), serviceConfigs_1_1 = serviceConfigs_1.next(); !serviceConfigs_1_1.done; serviceConfigs_1_1 = serviceConfigs_1.next()) { | ||
var service = serviceConfigs_1_1.value; | ||
// self-reference | ||
var propName = service.serviceName.toLowerCase(); | ||
if (!service.relationships) { | ||
service.relationships = []; | ||
} | ||
constructor(serviceConfigs, remoteFetchData) { | ||
this.serviceConfigs = serviceConfigs; | ||
this.remoteFetchData = remoteFetchData; | ||
this.serviceConfigCache = new Map(); | ||
this.implodeMapping = []; | ||
this.serviceConfigs = this.buildReferences(serviceConfigs); | ||
} | ||
setFetchDataCallback(remoteFetchData) { | ||
this.remoteFetchData = remoteFetchData; | ||
} | ||
buildReferences(serviceConfigs) { | ||
const expandedRelationships = new Map(); | ||
for (const service of serviceConfigs) { | ||
if (this.serviceConfigCache.has(service.serviceName)) { | ||
throw new Error(`Service "${service.serviceName}" is already defined.`); | ||
} | ||
service.fieldAlias ?? (service.fieldAlias = {}); | ||
service.relationships ?? (service.relationships = []); | ||
service.extends ?? (service.extends = []); | ||
// add aliases | ||
const isReadOnlyDefinition = service.serviceName === undefined || service.isReadOnlyLink; | ||
if (!isReadOnlyDefinition) { | ||
if (!service.alias) { | ||
service.alias = [{ name: service.serviceName.toLowerCase() }]; | ||
} | ||
(_d = service.relationships) === null || _d === void 0 ? void 0 : _d.push({ | ||
alias: propName, | ||
foreignKey: propName + "_id", | ||
primaryKey: "id", | ||
serviceName: service.serviceName, | ||
}); | ||
this.serviceConfigCache.set(service.serviceName, service); | ||
if (!service.extends) { | ||
continue; | ||
else if (!Array.isArray(service.alias)) { | ||
service.alias = [service.alias]; | ||
} | ||
try { | ||
for (var _f = (e_2 = void 0, __values(service.extends)), _g = _f.next(); !_g.done; _g = _f.next()) { | ||
var extend = _g.value; | ||
if (!expandedRelationships.has(extend.serviceName)) { | ||
expandedRelationships.set(extend.serviceName, []); | ||
} | ||
expandedRelationships.get(extend.serviceName).push(extend.resolve); | ||
// self-reference | ||
for (const alias of service.alias) { | ||
if (this.serviceConfigCache.has(`alias_${alias.name}}`)) { | ||
const defined = this.serviceConfigCache.get(`alias_${alias.name}}`); | ||
throw new Error(`Cannot add alias "${alias.name}" for "${service.serviceName}". It is already defined for Service "${defined?.serviceName}".`); | ||
} | ||
const args = service.args || alias.args | ||
? { ...service.args, ...alias.args } | ||
: undefined; | ||
service.relationships?.push({ | ||
alias: alias.name, | ||
foreignKey: alias.name + "_id", | ||
primaryKey: "id", | ||
serviceName: service.serviceName, | ||
args, | ||
}); | ||
this.cacheServiceConfig(serviceConfigs, undefined, alias.name); | ||
} | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
try { | ||
if (_g && !_g.done && (_b = _f.return)) _b.call(_f); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
this.cacheServiceConfig(serviceConfigs, service.serviceName); | ||
} | ||
for (const extend of service.extends) { | ||
if (!expandedRelationships.has(extend.serviceName)) { | ||
expandedRelationships.set(extend.serviceName, { | ||
fieldAlias: {}, | ||
relationships: [], | ||
}); | ||
} | ||
const service_ = expandedRelationships.get(extend.serviceName); | ||
service_.relationships.push(extend.relationship); | ||
Object.assign(service_.fieldAlias ?? {}, extend.fieldAlias); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (serviceConfigs_1_1 && !serviceConfigs_1_1.done && (_a = serviceConfigs_1.return)) _a.call(serviceConfigs_1); | ||
for (const [serviceName, { fieldAlias, relationships },] of expandedRelationships) { | ||
if (!this.serviceConfigCache.has(serviceName)) { | ||
// If true, the relationship is an internal service from the medusa core | ||
// If modules are being used ouside of the core, we should not be throwing | ||
// errors when the core services are not found in cache. | ||
// TODO: Remove when there are no more "internal" services | ||
const isInternalServicePresent = relationships.some((rel) => rel.isInternalService === true); | ||
if (isInternalServicePresent) | ||
continue; | ||
throw new Error(`Service "${serviceName}" was not found`); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
const service_ = this.serviceConfigCache.get(serviceName); | ||
service_.relationships?.push(...relationships); | ||
Object.assign(service_.fieldAlias, fieldAlias ?? {}); | ||
if (Object.keys(service_.fieldAlias).length) { | ||
const conflictAliases = service_.relationships.filter((relationship) => { | ||
return fieldAlias[relationship.alias]; | ||
}); | ||
if (conflictAliases.length) { | ||
throw new Error(`Conflict configuration for service "${serviceName}". The following aliases are already defined as relationships: ${conflictAliases | ||
.map((relationship) => relationship.alias) | ||
.join(", ")}`); | ||
} | ||
} | ||
} | ||
try { | ||
for (var expandedRelationships_1 = __values(expandedRelationships), expandedRelationships_1_1 = expandedRelationships_1.next(); !expandedRelationships_1_1.done; expandedRelationships_1_1 = expandedRelationships_1.next()) { | ||
var _h = __read(expandedRelationships_1_1.value, 2), serviceName = _h[0], relationships = _h[1]; | ||
if (!this.serviceConfigCache.has(serviceName)) { | ||
throw new Error("Service ".concat(serviceName, " not found")); | ||
return serviceConfigs; | ||
} | ||
getServiceConfig(serviceName, serviceAlias) { | ||
if (serviceAlias) { | ||
const name = `alias_${serviceAlias}`; | ||
return this.serviceConfigCache.get(name); | ||
} | ||
return this.serviceConfigCache.get(serviceName); | ||
} | ||
cacheServiceConfig(serviceConfigs, serviceName, serviceAlias) { | ||
if (serviceAlias) { | ||
const name = `alias_${serviceAlias}`; | ||
if (!this.serviceConfigCache.has(name)) { | ||
let aliasConfig; | ||
const config = serviceConfigs.find((conf) => { | ||
const aliases = conf.alias; | ||
const hasArgs = aliases?.find((alias) => alias.name === serviceAlias); | ||
aliasConfig = hasArgs; | ||
return hasArgs; | ||
}); | ||
if (config) { | ||
const serviceConfig = { ...config }; | ||
if (aliasConfig) { | ||
serviceConfig.args = { ...config?.args, ...aliasConfig?.args }; | ||
} | ||
this.serviceConfigCache.set(name, serviceConfig); | ||
} | ||
var service = this.serviceConfigCache.get(serviceName); | ||
(_e = service.relationships) === null || _e === void 0 ? void 0 : _e.push.apply(_e, __spreadArray([], __read(relationships), false)); | ||
} | ||
return; | ||
} | ||
catch (e_3_1) { e_3 = { error: e_3_1 }; } | ||
finally { | ||
try { | ||
if (expandedRelationships_1_1 && !expandedRelationships_1_1.done && (_c = expandedRelationships_1.return)) _c.call(expandedRelationships_1); | ||
const config = serviceConfigs.find((config) => config.serviceName === serviceName); | ||
this.serviceConfigCache.set(serviceName, config); | ||
} | ||
async fetchData(expand, pkField, ids, relationship) { | ||
let uniqueIds = Array.isArray(ids) ? ids : ids ? [ids] : undefined; | ||
if (uniqueIds) { | ||
const isCompositeKey = Array.isArray(uniqueIds[0]); | ||
if (isCompositeKey) { | ||
const seen = new Set(); | ||
uniqueIds = uniqueIds.filter((idArray) => { | ||
const key = JSON.stringify(idArray); | ||
const isNew = !seen.has(key); | ||
seen.add(key); | ||
return isNew; | ||
}); | ||
} | ||
finally { if (e_3) throw e_3.error; } | ||
else { | ||
uniqueIds = Array.from(new Set(uniqueIds.flat())); | ||
} | ||
uniqueIds = uniqueIds.filter((id) => id !== undefined); | ||
} | ||
return serviceConfigs; | ||
}; | ||
RemoteJoiner.prototype.findServiceConfig = function (serviceName) { | ||
if (!this.serviceConfigCache.has(serviceName)) { | ||
var config = this.serviceConfigs.find(function (config) { return config.serviceName === serviceName; }); | ||
this.serviceConfigCache.set(serviceName, config); | ||
if (relationship) { | ||
pkField = relationship.inverse | ||
? relationship.foreignKey.split(".").pop() | ||
: relationship.primaryKey; | ||
} | ||
return this.serviceConfigCache.get(serviceName); | ||
}; | ||
RemoteJoiner.prototype.fetchData = function (expand, pkField, ids, relationship) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var uniqueIds, isCompositeKey, seen_1, response, isObj, resData, filteredDataArray; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
uniqueIds = Array.isArray(ids) ? ids : ids ? [ids] : undefined; | ||
if (uniqueIds) { | ||
isCompositeKey = Array.isArray(uniqueIds[0]); | ||
if (isCompositeKey) { | ||
seen_1 = new Set(); | ||
uniqueIds = uniqueIds.filter(function (idArray) { | ||
var key = JSON.stringify(idArray); | ||
var isNew = !seen_1.has(key); | ||
seen_1.add(key); | ||
return isNew; | ||
}); | ||
} | ||
else { | ||
uniqueIds = Array.from(new Set(uniqueIds.flat())); | ||
} | ||
} | ||
if (relationship) { | ||
pkField = relationship.inverse | ||
? relationship.foreignKey.split(".").pop() | ||
: relationship.primaryKey; | ||
} | ||
return [4 /*yield*/, this.remoteFetchData(expand, pkField, uniqueIds, relationship)]; | ||
case 1: | ||
response = _a.sent(); | ||
isObj = (0, ecomm_utils_1.isDefined)(response.path); | ||
resData = isObj ? response.data[response.path] : response.data; | ||
filteredDataArray = resData.map(function (data) { | ||
return RemoteJoiner.filterFields(data, expand.fields, expand.expands); | ||
}); | ||
if (isObj) { | ||
response.data[response.path] = filteredDataArray; | ||
} | ||
else { | ||
response.data = filteredDataArray; | ||
} | ||
return [2 /*return*/, response]; | ||
const response = await this.remoteFetchData(expand, pkField, uniqueIds, relationship); | ||
const isObj = (0, ecomm_utils_1.isDefined)(response.path); | ||
const resData = isObj ? response.data[response.path] : response.data; | ||
const filteredDataArray = resData.map((data) => RemoteJoiner.filterFields(data, expand.fields, expand.expands)); | ||
if (isObj) { | ||
response.data[response.path] = filteredDataArray; | ||
} | ||
else { | ||
response.data = filteredDataArray; | ||
} | ||
return response; | ||
} | ||
handleFieldAliases(items, parsedExpands) { | ||
const getChildren = (item, prop) => { | ||
if (Array.isArray(item)) { | ||
return item.flatMap((currentItem) => currentItem[prop]); | ||
} | ||
else { | ||
return item[prop]; | ||
} | ||
}; | ||
const removeChildren = (item, prop) => { | ||
if (Array.isArray(item)) { | ||
item.forEach((currentItem) => delete currentItem[prop]); | ||
} | ||
else { | ||
delete item[prop]; | ||
} | ||
}; | ||
const cleanup = []; | ||
for (const alias of this.implodeMapping) { | ||
const propPath = alias.path; | ||
let itemsLocation = items; | ||
for (const locationProp of alias.location) { | ||
propPath.shift(); | ||
itemsLocation = RemoteJoiner.getNestedItems(itemsLocation, locationProp); | ||
} | ||
itemsLocation.forEach((locationItem) => { | ||
if (!locationItem) { | ||
return; | ||
} | ||
}); | ||
}); | ||
}; | ||
RemoteJoiner.prototype.handleExpands = function (items, query, parsedExpands) { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var stack, _b, currentItems, currentQuery, currentParsedExpands, basePath, resolvedPaths, _loop_2, this_1, _c, _d, _e, expandedPath, expand, e_4_1; | ||
var e_4, _f; | ||
return __generator(this, function (_g) { | ||
switch (_g.label) { | ||
case 0: | ||
if (!parsedExpands) { | ||
return [2 /*return*/]; | ||
} | ||
stack = [[items, query, parsedExpands, "", new Set()]]; | ||
_g.label = 1; | ||
case 1: | ||
if (!(stack.length > 0)) return [3 /*break*/, 10]; | ||
_b = __read(stack.pop(), 5), currentItems = _b[0], currentQuery = _b[1], currentParsedExpands = _b[2], basePath = _b[3], resolvedPaths = _b[4]; | ||
_loop_2 = function (expandedPath, expand) { | ||
var isImmediateChildPath, property, parentServiceConfig, relationship, nestedItems, nextProp; | ||
return __generator(this, function (_h) { | ||
switch (_h.label) { | ||
case 0: | ||
isImmediateChildPath = expandedPath.startsWith(basePath) && | ||
expandedPath.split(".").length === basePath.split(".").length + 1; | ||
if (!isImmediateChildPath || resolvedPaths.has(expandedPath)) { | ||
return [2 /*return*/, "continue"]; | ||
} | ||
resolvedPaths.add(expandedPath); | ||
property = expand.property || ""; | ||
parentServiceConfig = this_1.findServiceConfig(currentQuery.service); | ||
return [4 /*yield*/, this_1.expandProperty(currentItems, parentServiceConfig, expand)]; | ||
case 1: | ||
_h.sent(); | ||
relationship = (_a = parentServiceConfig === null || parentServiceConfig === void 0 ? void 0 : parentServiceConfig.relationships) === null || _a === void 0 ? void 0 : _a.find(function (relation) { return relation.alias === property; }); | ||
nestedItems = RemoteJoiner.getNestedItems(currentItems, property); | ||
if (nestedItems.length > 0) { | ||
nextProp = relationship | ||
? __assign(__assign({}, currentQuery), { service: relationship.serviceName }) : currentQuery; | ||
stack.push([ | ||
nestedItems, | ||
nextProp, | ||
currentParsedExpands, | ||
expandedPath, | ||
new Set(), | ||
]); | ||
} | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}; | ||
this_1 = this; | ||
_g.label = 2; | ||
case 2: | ||
_g.trys.push([2, 7, 8, 9]); | ||
_c = (e_4 = void 0, __values(currentParsedExpands.entries())), _d = _c.next(); | ||
_g.label = 3; | ||
case 3: | ||
if (!!_d.done) return [3 /*break*/, 6]; | ||
_e = __read(_d.value, 2), expandedPath = _e[0], expand = _e[1]; | ||
return [5 /*yield**/, _loop_2(expandedPath, expand)]; | ||
case 4: | ||
_g.sent(); | ||
_g.label = 5; | ||
case 5: | ||
_d = _c.next(); | ||
return [3 /*break*/, 3]; | ||
case 6: return [3 /*break*/, 9]; | ||
case 7: | ||
e_4_1 = _g.sent(); | ||
e_4 = { error: e_4_1 }; | ||
return [3 /*break*/, 9]; | ||
case 8: | ||
try { | ||
if (_d && !_d.done && (_f = _c.return)) _f.call(_c); | ||
} | ||
finally { if (e_4) throw e_4.error; } | ||
return [7 /*endfinally*/]; | ||
case 9: return [3 /*break*/, 1]; | ||
case 10: return [2 /*return*/]; | ||
let currentItems = locationItem; | ||
let parentRemoveItems = null; | ||
const curPath = [BASE_PATH].concat(alias.location); | ||
for (const prop of propPath) { | ||
if (currentItems === undefined) { | ||
break; | ||
} | ||
curPath.push(prop); | ||
const config = parsedExpands.get(curPath.join(".")); | ||
if (config?.isAliasMapping && parentRemoveItems === null) { | ||
parentRemoveItems = [currentItems, prop]; | ||
} | ||
currentItems = getChildren(currentItems, prop); | ||
} | ||
if (Array.isArray(currentItems)) { | ||
if (currentItems.length < 2) { | ||
locationItem[alias.property] = currentItems.shift(); | ||
} | ||
else { | ||
locationItem[alias.property] = currentItems; | ||
} | ||
} | ||
else { | ||
locationItem[alias.property] = currentItems; | ||
} | ||
if (parentRemoveItems !== null) { | ||
cleanup.push(parentRemoveItems); | ||
} | ||
}); | ||
}); | ||
}; | ||
RemoteJoiner.prototype.expandProperty = function (items, parentServiceConfig, expand) { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var relationship; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
if (!expand) { | ||
return [2 /*return*/]; | ||
} | ||
relationship = (_a = parentServiceConfig === null || parentServiceConfig === void 0 ? void 0 : parentServiceConfig.relationships) === null || _a === void 0 ? void 0 : _a.find(function (relation) { return relation.alias === expand.property; }); | ||
if (!relationship) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, this.expandRelationshipProperty(items, expand, relationship)]; | ||
case 1: | ||
_b.sent(); | ||
_b.label = 2; | ||
case 2: return [2 /*return*/]; | ||
} | ||
for (const parentRemoveItems of cleanup) { | ||
const [remItems, path] = parentRemoveItems; | ||
removeChildren(remItems, path); | ||
} | ||
} | ||
async handleExpands(items, parsedExpands) { | ||
if (!parsedExpands) { | ||
return; | ||
} | ||
for (const [expandedPath, expand] of parsedExpands.entries()) { | ||
if (expandedPath === BASE_PATH) { | ||
continue; | ||
} | ||
let nestedItems = items; | ||
const expandedPathLevels = expandedPath.split("."); | ||
for (let idx = 1; idx < expandedPathLevels.length - 1; idx++) { | ||
nestedItems = RemoteJoiner.getNestedItems(nestedItems, expandedPathLevels[idx]); | ||
} | ||
if (nestedItems.length > 0) { | ||
await this.expandProperty(nestedItems, expand.parentConfig, expand); | ||
} | ||
} | ||
this.handleFieldAliases(items, parsedExpands); | ||
} | ||
async expandProperty(items, parentServiceConfig, expand) { | ||
if (!expand) { | ||
return; | ||
} | ||
const relationship = parentServiceConfig?.relationships?.find((relation) => relation.alias === expand.property); | ||
if (relationship) { | ||
await this.expandRelationshipProperty(items, expand, relationship); | ||
} | ||
} | ||
async expandRelationshipProperty(items, expand, relationship) { | ||
const field = relationship.inverse | ||
? relationship.primaryKey | ||
: relationship.foreignKey.split(".").pop(); | ||
const fieldsArray = field.split(","); | ||
const idsToFetch = []; | ||
items.forEach((item) => { | ||
const values = fieldsArray.map((field) => item?.[field]); | ||
if (values.length === fieldsArray.length && !item?.[relationship.alias]) { | ||
if (fieldsArray.length === 1) { | ||
if (!idsToFetch.includes(values[0])) { | ||
idsToFetch.push(values[0]); | ||
} | ||
} | ||
}); | ||
else { | ||
// composite key | ||
const valuesString = values.join(","); | ||
if (!idsToFetch.some((id) => id.join(",") === valuesString)) { | ||
idsToFetch.push(values); | ||
} | ||
} | ||
} | ||
}); | ||
}; | ||
RemoteJoiner.prototype.expandRelationshipProperty = function (items, expand, relationship) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var field, fieldsArray, idsToFetch, relatedDataArray, joinFields, relData, relatedDataMap; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
field = relationship.inverse | ||
? relationship.primaryKey | ||
: relationship.foreignKey.split(".").pop(); | ||
fieldsArray = field.split(","); | ||
idsToFetch = []; | ||
items.forEach(function (item) { | ||
var values = fieldsArray | ||
.map(function (field) { return item[field]; }) | ||
.filter(function (value) { return value !== undefined; }); | ||
if (values.length === fieldsArray.length && !item[relationship.alias]) { | ||
if (fieldsArray.length === 1) { | ||
if (!idsToFetch.includes(values[0])) { | ||
idsToFetch.push(values[0]); | ||
} | ||
} | ||
else { | ||
// composite key | ||
var valuesString_1 = values.join(","); | ||
if (!idsToFetch.some(function (id) { return id.join(",") === valuesString_1; })) { | ||
idsToFetch.push(values); | ||
} | ||
} | ||
} | ||
}); | ||
if (idsToFetch.length === 0) { | ||
return [2 /*return*/]; | ||
} | ||
return [4 /*yield*/, this.fetchData(expand, field, idsToFetch, relationship)]; | ||
case 1: | ||
relatedDataArray = _a.sent(); | ||
joinFields = relationship.inverse | ||
? relationship.foreignKey.split(",") | ||
: relationship.primaryKey.split(","); | ||
relData = relatedDataArray.path | ||
? relatedDataArray.data[relatedDataArray.path] | ||
: relatedDataArray.data; | ||
relatedDataMap = RemoteJoiner.createRelatedDataMap(relData, joinFields); | ||
items.forEach(function (item) { | ||
if (!item[relationship.alias]) { | ||
var itemKey = fieldsArray.map(function (field) { return item[field]; }).join(","); | ||
if (Array.isArray(item[field])) { | ||
item[relationship.alias] = item[field] | ||
.map(function (id) { return relatedDataMap[id]; }) | ||
.filter(function (relatedItem) { return relatedItem !== undefined; }); | ||
} | ||
else { | ||
item[relationship.alias] = relatedDataMap[itemKey]; | ||
} | ||
} | ||
}); | ||
return [2 /*return*/]; | ||
if (idsToFetch.length === 0) { | ||
return; | ||
} | ||
const relatedDataArray = await this.fetchData(expand, field, idsToFetch, relationship); | ||
const joinFields = relationship.inverse | ||
? relationship.foreignKey.split(",") | ||
: relationship.primaryKey.split(","); | ||
const relData = relatedDataArray.path | ||
? relatedDataArray.data[relatedDataArray.path] | ||
: relatedDataArray.data; | ||
const relatedDataMap = RemoteJoiner.createRelatedDataMap(relData, joinFields); | ||
items.forEach((item) => { | ||
if (!item || item[relationship.alias]) { | ||
return; | ||
} | ||
const itemKey = fieldsArray.map((field) => item[field]).join(","); | ||
if (Array.isArray(item[field])) { | ||
item[relationship.alias] = item[field].map((id) => { | ||
if (relationship.isList && !Array.isArray(relatedDataMap[id])) { | ||
relatedDataMap[id] = | ||
relatedDataMap[id] !== undefined ? [relatedDataMap[id]] : []; | ||
} | ||
return relatedDataMap[id]; | ||
}); | ||
} | ||
else { | ||
if (relationship.isList && !Array.isArray(relatedDataMap[itemKey])) { | ||
relatedDataMap[itemKey] = | ||
relatedDataMap[itemKey] !== undefined | ||
? [relatedDataMap[itemKey]] | ||
: []; | ||
} | ||
}); | ||
item[relationship.alias] = relatedDataMap[itemKey]; | ||
} | ||
}); | ||
}; | ||
RemoteJoiner.prototype.parseExpands = function (initialService, query, serviceConfig, expands) { | ||
var parsedExpands = this.parseProperties(initialService, query, serviceConfig, expands); | ||
var groupedExpands = this.groupExpands(parsedExpands); | ||
} | ||
parseExpands(initialService, query, serviceConfig, expands) { | ||
const parsedExpands = this.parseProperties(initialService, query, serviceConfig, expands); | ||
const groupedExpands = this.groupExpands(parsedExpands); | ||
return groupedExpands; | ||
}; | ||
RemoteJoiner.prototype.parseProperties = function (initialService, query, serviceConfig, expands) { | ||
var e_5, _a, e_6, _b; | ||
var parsedExpands = new Map(); | ||
} | ||
parseProperties(initialService, query, serviceConfig, expands) { | ||
const parsedExpands = new Map(); | ||
parsedExpands.set(BASE_PATH, initialService); | ||
try { | ||
for (var _c = __values(expands || []), _d = _c.next(); !_d.done; _d = _c.next()) { | ||
var expand = _d.value; | ||
var properties = expand.property.split("."); | ||
var currentServiceConfig = serviceConfig; | ||
var currentPath = []; | ||
var _loop_3 = function (prop) { | ||
var fullPath = __spreadArray(__spreadArray([BASE_PATH], __read(currentPath), false), [prop], false).join("."); | ||
var relationship = currentServiceConfig.relationships.find(function (relation) { return relation.alias === prop; }); | ||
var fields = fullPath === BASE_PATH + "." + expand.property | ||
? expand.fields | ||
: undefined; | ||
var args = fullPath === BASE_PATH + "." + expand.property | ||
? expand.args | ||
: undefined; | ||
if (relationship) { | ||
var parentExpand = parsedExpands.get(__spreadArray([BASE_PATH], __read(currentPath), false).join(".")) || query; | ||
if (parentExpand) { | ||
if (parentExpand.fields) { | ||
var relField = relationship.inverse | ||
? relationship.primaryKey | ||
: relationship.foreignKey.split(".").pop(); | ||
parentExpand.fields = parentExpand.fields | ||
.concat(relField.split(",")) | ||
.filter(function (field) { return field !== relationship.alias; }); | ||
parentExpand.fields = __spreadArray([], __read(new Set(parentExpand.fields)), false); | ||
} | ||
if (fields) { | ||
var relField = relationship.inverse | ||
? relationship.foreignKey.split(".").pop() | ||
: relationship.primaryKey; | ||
fields = fields.concat(relField.split(",")); | ||
fields = __spreadArray([], __read(new Set(fields)), false); | ||
} | ||
let forwardArgumentsOnPath = []; | ||
for (const expand of expands || []) { | ||
const properties = expand.property.split("."); | ||
let currentServiceConfig = serviceConfig; | ||
const currentPath = []; | ||
for (const prop of properties) { | ||
const fieldAlias = currentServiceConfig.fieldAlias ?? {}; | ||
if (fieldAlias[prop]) { | ||
const alias = fieldAlias[prop]; | ||
const path = (0, ecomm_utils_1.isString)(alias) ? alias : alias.path; | ||
const fullPath = [...new Set(currentPath.concat(path.split(".")))]; | ||
forwardArgumentsOnPath = forwardArgumentsOnPath.concat((alias?.forwardArgumentsOnPath || []).map((forPath) => BASE_PATH + "." + currentPath.concat(forPath).join("."))); | ||
this.implodeMapping.push({ | ||
location: currentPath, | ||
property: prop, | ||
path: fullPath, | ||
}); | ||
const extMapping = expands; | ||
const middlePath = path.split(".").slice(0, -1); | ||
let curMiddlePath = currentPath; | ||
for (const path of middlePath) { | ||
curMiddlePath = curMiddlePath.concat(path); | ||
extMapping.push({ | ||
args: expand.args, | ||
property: curMiddlePath.join("."), | ||
isAliasMapping: true, | ||
}); | ||
} | ||
extMapping.push({ | ||
...expand, | ||
property: fullPath.join("."), | ||
isAliasMapping: true, | ||
}); | ||
continue; | ||
} | ||
const fullPath = [BASE_PATH, ...currentPath, prop].join("."); | ||
const relationship = currentServiceConfig.relationships?.find((relation) => relation.alias === prop); | ||
let fields = fullPath === BASE_PATH + "." + expand.property | ||
? expand.fields ?? [] | ||
: undefined; | ||
const args = fullPath === BASE_PATH + "." + expand.property | ||
? expand.args | ||
: undefined; | ||
if (relationship) { | ||
const parentExpand = parsedExpands.get([BASE_PATH, ...currentPath].join(".")) || query; | ||
if (parentExpand) { | ||
const relField = relationship.inverse | ||
? relationship.primaryKey | ||
: relationship.foreignKey.split(".").pop(); | ||
parentExpand.fields ?? (parentExpand.fields = []); | ||
parentExpand.fields = parentExpand.fields | ||
.concat(relField.split(",")) | ||
.filter((field) => field !== relationship.alias); | ||
parentExpand.fields = [...new Set(parentExpand.fields)]; | ||
if (fields) { | ||
const relField = relationship.inverse | ||
? relationship.foreignKey.split(".").pop() | ||
: relationship.primaryKey; | ||
fields = fields.concat(relField.split(",")); | ||
} | ||
currentServiceConfig = this_2.findServiceConfig(relationship.serviceName); | ||
if (!currentServiceConfig) { | ||
throw new Error("Target service not found: ".concat(relationship.serviceName)); | ||
} | ||
} | ||
if (!parsedExpands.has(fullPath)) { | ||
parsedExpands.set(fullPath, { | ||
property: prop, | ||
serviceConfig: currentServiceConfig, | ||
fields: fields, | ||
args: args, | ||
}); | ||
currentServiceConfig = this.getServiceConfig(relationship.serviceName); | ||
if (!currentServiceConfig) { | ||
throw new Error(`Target service not found: ${relationship.serviceName}`); | ||
} | ||
currentPath.push(prop); | ||
}; | ||
var this_2 = this; | ||
try { | ||
for (var properties_1 = (e_6 = void 0, __values(properties)), properties_1_1 = properties_1.next(); !properties_1_1.done; properties_1_1 = properties_1.next()) { | ||
var prop = properties_1_1.value; | ||
_loop_3(prop); | ||
} | ||
} | ||
catch (e_6_1) { e_6 = { error: e_6_1 }; } | ||
finally { | ||
try { | ||
if (properties_1_1 && !properties_1_1.done && (_b = properties_1.return)) _b.call(properties_1); | ||
const isAliasMapping = expand.isAliasMapping; | ||
if (!parsedExpands.has(fullPath)) { | ||
const parentPath = [BASE_PATH, ...currentPath].join("."); | ||
parsedExpands.set(fullPath, { | ||
property: prop, | ||
serviceConfig: currentServiceConfig, | ||
fields, | ||
args: isAliasMapping | ||
? forwardArgumentsOnPath.includes(fullPath) | ||
? args | ||
: undefined | ||
: args, | ||
isAliasMapping: isAliasMapping, | ||
parent: parentPath, | ||
parentConfig: parsedExpands.get(parentPath).serviceConfig, | ||
}); | ||
} | ||
else { | ||
const exp = parsedExpands.get(fullPath); | ||
if (forwardArgumentsOnPath.includes(fullPath) && args) { | ||
exp.args = (exp.args || []).concat(args); | ||
} | ||
finally { if (e_6) throw e_6.error; } | ||
if (fields) { | ||
exp.fields = (exp.fields || []).concat(fields); | ||
} | ||
} | ||
currentPath.push(prop); | ||
} | ||
} | ||
catch (e_5_1) { e_5 = { error: e_5_1 }; } | ||
finally { | ||
try { | ||
if (_d && !_d.done && (_a = _c.return)) _a.call(_c); | ||
} | ||
finally { if (e_5) throw e_5.error; } | ||
} | ||
return parsedExpands; | ||
}; | ||
RemoteJoiner.prototype.groupExpands = function (parsedExpands) { | ||
var e_7, _a, e_8, _b; | ||
var sortedParsedExpands = new Map(Array.from(parsedExpands.entries()).sort()); | ||
var mergedExpands = new Map(sortedParsedExpands); | ||
var mergedPaths = new Map(); | ||
var lastServiceName = ""; | ||
try { | ||
for (var _c = __values(sortedParsedExpands.entries()), _d = _c.next(); !_d.done; _d = _c.next()) { | ||
var _e = __read(_d.value, 2), path = _e[0], expand = _e[1]; | ||
var currentServiceName = expand.serviceConfig.serviceName; | ||
var parentPath = path.split(".").slice(0, -1).join("."); | ||
// Check if the parentPath was merged before | ||
while (mergedPaths.has(parentPath)) { | ||
parentPath = mergedPaths.get(parentPath); | ||
} | ||
groupExpands(parsedExpands) { | ||
var _a; | ||
const mergedExpands = new Map(parsedExpands); | ||
const mergedPaths = new Map(); | ||
for (const [path, expand] of mergedExpands.entries()) { | ||
const currentServiceName = expand.serviceConfig.serviceName; | ||
let parentPath = expand.parent; | ||
while (parentPath) { | ||
const parentExpand = mergedExpands.get(parentPath) ?? mergedPaths.get(parentPath); | ||
if (!parentExpand || | ||
parentExpand.serviceConfig.serviceName !== currentServiceName) { | ||
break; | ||
} | ||
var canMerge = currentServiceName === lastServiceName; | ||
if (mergedExpands.has(parentPath) && canMerge) { | ||
var parentExpand = mergedExpands.get(parentPath); | ||
if (parentExpand.serviceConfig.serviceName === currentServiceName) { | ||
var nestedKeys = path.split(".").slice(parentPath.split(".").length); | ||
var targetExpand = parentExpand; | ||
try { | ||
for (var nestedKeys_1 = (e_8 = void 0, __values(nestedKeys)), nestedKeys_1_1 = nestedKeys_1.next(); !nestedKeys_1_1.done; nestedKeys_1_1 = nestedKeys_1.next()) { | ||
var key = nestedKeys_1_1.value; | ||
if (!targetExpand.expands) { | ||
targetExpand.expands = {}; | ||
} | ||
if (!targetExpand.expands[key]) { | ||
targetExpand.expands[key] = {}; | ||
} | ||
targetExpand = targetExpand.expands[key]; | ||
} | ||
} | ||
catch (e_8_1) { e_8 = { error: e_8_1 }; } | ||
finally { | ||
try { | ||
if (nestedKeys_1_1 && !nestedKeys_1_1.done && (_b = nestedKeys_1.return)) _b.call(nestedKeys_1); | ||
} | ||
finally { if (e_8) throw e_8.error; } | ||
} | ||
targetExpand.fields = expand.fields; | ||
targetExpand.args = expand.args; | ||
mergedPaths.set(path, parentPath); | ||
} | ||
// Merge the current expand into its parent | ||
const nestedKeys = path.split(".").slice(parentPath.split(".").length); | ||
let targetExpand = parentExpand; | ||
for (const key of nestedKeys) { | ||
targetExpand.expands ?? (targetExpand.expands = {}); | ||
targetExpand = (_a = targetExpand.expands)[key] ?? (_a[key] = {}); | ||
} | ||
else { | ||
lastServiceName = currentServiceName; | ||
} | ||
targetExpand.fields = [...new Set(expand.fields)]; | ||
targetExpand.args = expand.args; | ||
mergedExpands.delete(path); | ||
mergedPaths.set(path, expand); | ||
parentPath = parentExpand.parent; | ||
} | ||
} | ||
catch (e_7_1) { e_7 = { error: e_7_1 }; } | ||
finally { | ||
try { | ||
if (_d && !_d.done && (_a = _c.return)) _a.call(_c); | ||
return mergedExpands; | ||
} | ||
async query(queryObj) { | ||
const serviceConfig = this.getServiceConfig(queryObj.service, queryObj.alias); | ||
if (!serviceConfig) { | ||
if (queryObj.alias) { | ||
throw new Error(`Service with alias "${queryObj.alias}" was not found.`); | ||
} | ||
finally { if (e_7) throw e_7.error; } | ||
throw new Error(`Service "${queryObj.service}" was not found.`); | ||
} | ||
return mergedExpands; | ||
}; | ||
RemoteJoiner.prototype.query = function (queryObj) { | ||
var _a, _b; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var serviceConfig, pkName, primaryKeyArg, otherArgs, parsedExpands, root, response, data; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
queryObj.service = (0, ecomm_utils_1.toPascalCase)(queryObj.service); | ||
serviceConfig = this.findServiceConfig(queryObj.service); | ||
if (!serviceConfig) { | ||
throw new Error("Service not found: ".concat(queryObj.service)); | ||
} | ||
pkName = serviceConfig.primaryKeys[0]; | ||
primaryKeyArg = (_a = queryObj.args) === null || _a === void 0 ? void 0 : _a.find(function (arg) { | ||
var inc = serviceConfig.primaryKeys.includes(arg.name); | ||
if (inc) { | ||
pkName = arg.name; | ||
} | ||
return inc; | ||
}); | ||
otherArgs = (_b = queryObj.args) === null || _b === void 0 ? void 0 : _b.filter(function (arg) { return !serviceConfig.primaryKeys.includes(arg.name); }); | ||
parsedExpands = this.parseExpands({ | ||
property: "", | ||
serviceConfig: serviceConfig, | ||
fields: queryObj.fields, | ||
args: otherArgs, | ||
}, queryObj, serviceConfig, queryObj.expands); | ||
root = parsedExpands.get(BASE_PATH); | ||
return [4 /*yield*/, this.fetchData(root, pkName, primaryKeyArg === null || primaryKeyArg === void 0 ? void 0 : primaryKeyArg.value, undefined)]; | ||
case 1: | ||
response = _c.sent(); | ||
data = response.path ? response.data[response.path] : response.data; | ||
return [4 /*yield*/, this.handleExpands(Array.isArray(data) ? data : [data], queryObj, parsedExpands)]; | ||
case 2: | ||
_c.sent(); | ||
return [2 /*return*/, response.data]; | ||
} | ||
}); | ||
let pkName = serviceConfig.primaryKeys[0]; | ||
const primaryKeyArg = queryObj.args?.find((arg) => { | ||
const inc = serviceConfig.primaryKeys.includes(arg.name); | ||
if (inc) { | ||
pkName = arg.name; | ||
} | ||
return inc; | ||
}); | ||
}; | ||
return RemoteJoiner; | ||
}()); | ||
const otherArgs = queryObj.args?.filter((arg) => !serviceConfig.primaryKeys.includes(arg.name)); | ||
const parsedExpands = this.parseExpands({ | ||
property: "", | ||
parent: "", | ||
serviceConfig: serviceConfig, | ||
fields: queryObj.fields, | ||
args: otherArgs, | ||
}, queryObj, serviceConfig, queryObj.expands); | ||
const root = parsedExpands.get(BASE_PATH); | ||
const response = await this.fetchData(root, pkName, primaryKeyArg?.value, undefined); | ||
const data = response.path ? response.data[response.path] : response.data; | ||
await this.handleExpands(Array.isArray(data) ? data : [data], parsedExpands); | ||
return response.data; | ||
} | ||
} | ||
exports.RemoteJoiner = RemoteJoiner; | ||
//# sourceMappingURL=remote-joiner.js.map |
{ | ||
"name": "@ivfuture/ecomm-orchestration", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "Medusa utilities to orchestrate modules", | ||
@@ -20,18 +20,21 @@ "main": "dist/index.js", | ||
"devDependencies": { | ||
"@ivfuture/ecomm-types": "^1.0.1", | ||
"@ivfuture/ecomm-types": "^1.1.0", | ||
"cross-env": "^5.2.1", | ||
"jest": "^25.5.4", | ||
"ts-jest": "^25.5.1", | ||
"typescript": "^4.4.4" | ||
"jest": "^29.6.3", | ||
"rimraf": "^5.0.1", | ||
"ts-jest": "^29.1.1", | ||
"typescript": "^5.1.6" | ||
}, | ||
"dependencies": { | ||
"@ivfuture/ecomm-utils": "^1.1.1", | ||
"@ivfuture/ecomm-types": "^1.1.0", | ||
"@ivfuture/ecomm-utils": "^1.2.0", | ||
"awilix": "^8.0.0", | ||
"graphql": "^16.6.0" | ||
}, | ||
"scripts": { | ||
"prepare": "cross-env NODE_ENV=production yarn run build", | ||
"build": "tsc --build", | ||
"prepublishOnly": "cross-env NODE_ENV=production tsc --build", | ||
"build": "rimraf dist && tsc --build", | ||
"watch": "tsc --build --watch", | ||
"test": "jest" | ||
"test": "jest --runInBand --bail --forceExit" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
179297
46
2516
4
6
1
+ Added@ivfuture/ecomm-types@^1.1.0
+ Addedawilix@^8.0.0
+ Added@ivfuture/ecomm-types@1.56.3(transitive)
+ Added@nodelib/fs.scandir@2.1.5(transitive)
+ Added@nodelib/fs.stat@2.0.5(transitive)
+ Added@nodelib/fs.walk@1.2.8(transitive)
+ Addedawilix@8.0.1(transitive)
+ Addedbraces@3.0.3(transitive)
+ Addedcamel-case@4.1.2(transitive)
+ Addedfast-glob@3.3.2(transitive)
+ Addedfastq@1.17.1(transitive)
+ Addedfill-range@7.1.1(transitive)
+ Addedglob-parent@5.1.2(transitive)
+ Addedis-extglob@2.1.1(transitive)
+ Addedis-glob@4.0.3(transitive)
+ Addedis-number@7.0.0(transitive)
+ Addedlower-case@2.0.2(transitive)
+ Addedmerge2@1.4.1(transitive)
+ Addedmicromatch@4.0.8(transitive)
+ Addedno-case@3.0.4(transitive)
+ Addedpascal-case@3.1.2(transitive)
+ Addedpicomatch@2.3.1(transitive)
+ Addedqueue-microtask@1.2.3(transitive)
+ Addedreusify@1.0.4(transitive)
+ Addedrun-parallel@1.2.0(transitive)
+ Addedto-regex-range@5.0.1(transitive)
+ Addedtslib@2.8.1(transitive)
Updated@ivfuture/ecomm-utils@^1.2.0