@medusajs/index 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/loaders/index.d.ts +4 -0
- package/dist/loaders/index.d.ts.map +1 -0
- package/dist/loaders/index.js +26 -0
- package/dist/migrations/Migration20231019174230.d.ts +5 -0
- package/dist/migrations/Migration20231019174230.d.ts.map +1 -0
- package/dist/migrations/Migration20231019174230.js +15 -0
- package/dist/models/index-data.d.ts +12 -0
- package/dist/models/index-data.d.ts.map +1 -0
- package/dist/models/index-data.js +51 -0
- package/dist/models/index-relation.d.ts +16 -0
- package/dist/models/index-relation.d.ts.map +1 -0
- package/dist/models/index-relation.js +68 -0
- package/dist/models/index.d.ts +3 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +7 -0
- package/dist/services/index-module-service.d.ts +30 -0
- package/dist/services/index-module-service.d.ts.map +1 -0
- package/dist/services/index-module-service.js +70 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +8 -0
- package/dist/services/postgres-provider.d.ts +132 -0
- package/dist/services/postgres-provider.d.ts.map +1 -0
- package/dist/services/postgres-provider.js +489 -0
- package/dist/types/index.d.ts +22 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/utils/build-config.d.ts +23 -0
- package/dist/utils/build-config.d.ts.map +1 -0
- package/dist/utils/build-config.js +473 -0
- package/dist/utils/create-partitions.d.ts +4 -0
- package/dist/utils/create-partitions.d.ts.map +1 -0
- package/dist/utils/create-partitions.js +31 -0
- package/dist/utils/default-schema.d.ts +2 -0
- package/dist/utils/default-schema.d.ts.map +1 -0
- package/dist/utils/default-schema.js +22 -0
- package/dist/utils/flatten-object-keys.d.ts +23 -0
- package/dist/utils/flatten-object-keys.d.ts.map +1 -0
- package/dist/utils/flatten-object-keys.js +54 -0
- package/dist/utils/gql-to-types.d.ts +2 -0
- package/dist/utils/gql-to-types.d.ts.map +1 -0
- package/dist/utils/gql-to-types.js +89 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +19 -0
- package/dist/utils/normalize-fields-selection.d.ts +2 -0
- package/dist/utils/normalize-fields-selection.d.ts.map +1 -0
- package/dist/utils/normalize-fields-selection.js +10 -0
- package/dist/utils/query-builder.d.ts +42 -0
- package/dist/utils/query-builder.d.ts.map +1 -0
- package/dist/utils/query-builder.js +420 -0
- package/package.json +55 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.gqlSchemaToTypes = void 0;
|
|
27
|
+
const path_1 = require("path");
|
|
28
|
+
const build_config_1 = require("./build-config");
|
|
29
|
+
const modules_sdk_1 = require("@medusajs/modules-sdk");
|
|
30
|
+
const utils_1 = require("@medusajs/utils");
|
|
31
|
+
const process = __importStar(require("process"));
|
|
32
|
+
async function gqlSchemaToTypes(schema) {
|
|
33
|
+
const augmentedSchema = build_config_1.CustomDirectives.Listeners.definition + schema;
|
|
34
|
+
const executableSchema = (0, build_config_1.makeSchemaExecutable)(augmentedSchema);
|
|
35
|
+
const filename = "index-service-entry-points";
|
|
36
|
+
const filenameWithExt = filename + ".d.ts";
|
|
37
|
+
const dir = (0, path_1.join)(process.cwd(), ".medusa");
|
|
38
|
+
await (0, modules_sdk_1.gqlSchemaToTypes)({
|
|
39
|
+
schema: executableSchema,
|
|
40
|
+
filename,
|
|
41
|
+
outputDir: dir,
|
|
42
|
+
});
|
|
43
|
+
const fileSystem = new utils_1.FileSystem(dir);
|
|
44
|
+
let content = await fileSystem.contents(filenameWithExt);
|
|
45
|
+
await fileSystem.remove(filenameWithExt);
|
|
46
|
+
const entryPoints = buildEntryPointsTypeMap(content);
|
|
47
|
+
const indexEntryPoints = `
|
|
48
|
+
declare module '@medusajs/types' {
|
|
49
|
+
interface IndexServiceEntryPoints {
|
|
50
|
+
${entryPoints
|
|
51
|
+
.map((entry) => ` ${entry.entryPoint}: ${entry.entityType}`)
|
|
52
|
+
.join("\n")}
|
|
53
|
+
}
|
|
54
|
+
}`;
|
|
55
|
+
const contentToReplaceMatcher = new RegExp(`declare\\s+module\\s+['"][^'"]+['"]\\s*{([^}]*?)}\\s+}`, "gm");
|
|
56
|
+
content = content.replace(contentToReplaceMatcher, indexEntryPoints);
|
|
57
|
+
await fileSystem.create(filenameWithExt, content);
|
|
58
|
+
}
|
|
59
|
+
exports.gqlSchemaToTypes = gqlSchemaToTypes;
|
|
60
|
+
function buildEntryPointsTypeMap(schema) {
|
|
61
|
+
// build map entry point to there type to be merged and used by the remote query
|
|
62
|
+
const joinerConfigs = modules_sdk_1.MedusaModule.getAllJoinerConfigs();
|
|
63
|
+
return joinerConfigs
|
|
64
|
+
.flatMap((config) => {
|
|
65
|
+
const aliases = Array.isArray(config.alias)
|
|
66
|
+
? config.alias
|
|
67
|
+
: config.alias
|
|
68
|
+
? [config.alias]
|
|
69
|
+
: [];
|
|
70
|
+
return aliases.flatMap((alias) => {
|
|
71
|
+
const names = Array.isArray(alias.name) ? alias.name : [alias.name];
|
|
72
|
+
const entity = alias?.["entity"];
|
|
73
|
+
return names.map((aliasItem) => {
|
|
74
|
+
if (!schema.includes(`export type ${entity} `)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
entryPoint: aliasItem,
|
|
79
|
+
entityType: entity
|
|
80
|
+
? schema.includes(`export type ${entity} `)
|
|
81
|
+
? alias?.["entity"]
|
|
82
|
+
: "any"
|
|
83
|
+
: "any",
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
})
|
|
88
|
+
.filter(Boolean);
|
|
89
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./query-builder"), exports);
|
|
18
|
+
__exportStar(require("./create-partitions"), exports);
|
|
19
|
+
__exportStar(require("./build-config"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-fields-selection.d.ts","sourceRoot":"","sources":["../../src/utils/normalize-fields-selection.ts"],"names":[],"mappings":"AAEA,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,uBAIxD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeFieldsSelection = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/utils");
|
|
5
|
+
function normalizeFieldsSelection(fields) {
|
|
6
|
+
const normalizedFields = fields.map((field) => field.replace(/\.\*/g, ""));
|
|
7
|
+
const fieldsObject = (0, utils_1.objectFromStringPath)(normalizedFields);
|
|
8
|
+
return fieldsObject;
|
|
9
|
+
}
|
|
10
|
+
exports.normalizeFieldsSelection = normalizeFieldsSelection;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { IndexTypes } from "@medusajs/types";
|
|
2
|
+
import { Knex } from "knex";
|
|
3
|
+
import { QueryFormat, QueryOptions } from "../types";
|
|
4
|
+
export declare const OPERATOR_MAP: {
|
|
5
|
+
$eq: string;
|
|
6
|
+
$lt: string;
|
|
7
|
+
$gt: string;
|
|
8
|
+
$lte: string;
|
|
9
|
+
$gte: string;
|
|
10
|
+
$ne: string;
|
|
11
|
+
$in: string;
|
|
12
|
+
$is: string;
|
|
13
|
+
$like: string;
|
|
14
|
+
$ilike: string;
|
|
15
|
+
};
|
|
16
|
+
export declare class QueryBuilder {
|
|
17
|
+
private readonly structure;
|
|
18
|
+
private readonly entityMap;
|
|
19
|
+
private readonly knex;
|
|
20
|
+
private readonly selector;
|
|
21
|
+
private readonly options?;
|
|
22
|
+
private readonly schema;
|
|
23
|
+
constructor(args: {
|
|
24
|
+
schema: IndexTypes.SchemaObjectRepresentation;
|
|
25
|
+
entityMap: Record<string, any>;
|
|
26
|
+
knex: Knex;
|
|
27
|
+
selector: QueryFormat;
|
|
28
|
+
options?: QueryOptions;
|
|
29
|
+
});
|
|
30
|
+
private getStructureKeys;
|
|
31
|
+
private getEntity;
|
|
32
|
+
private getGraphQLType;
|
|
33
|
+
private transformValueToType;
|
|
34
|
+
private getPostgresCastType;
|
|
35
|
+
private parseWhere;
|
|
36
|
+
private buildQueryParts;
|
|
37
|
+
private buildSelectParts;
|
|
38
|
+
private transformOrderBy;
|
|
39
|
+
buildQuery(countAllResults?: boolean, returnIdOnly?: boolean): string;
|
|
40
|
+
buildObjectFromResultset(resultSet: Record<string, any>[]): Record<string, any>[];
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=query-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-builder.d.ts","sourceRoot":"","sources":["../../src/utils/query-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAW,WAAW,EAAE,YAAY,EAAU,MAAM,QAAQ,CAAA;AAEnE,eAAO,MAAM,YAAY;;;;;;;;;;;CAWxB,CAAA;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;gBAElD,IAAI,EAAE;QAChB,MAAM,EAAE,UAAU,CAAC,0BAA0B,CAAA;QAC7C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC9B,IAAI,EAAE,IAAI,CAAA;QACV,QAAQ,EAAE,WAAW,CAAA;QACrB,OAAO,CAAC,EAAE,YAAY,CAAA;KACvB;IASD,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,oBAAoB;IA2B5B,OAAO,CAAC,mBAAmB;IAsB3B,OAAO,CAAC,UAAU;IAoIlB,OAAO,CAAC,eAAe;IA8HvB,OAAO,CAAC,gBAAgB;IA8BxB,OAAO,CAAC,gBAAgB;IAiCjB,UAAU,CAAC,eAAe,UAAO,EAAE,YAAY,UAAQ,GAAG,MAAM;IAiFhE,wBAAwB,CAC7B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAC/B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE;CA+FzB"}
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QueryBuilder = exports.OPERATOR_MAP = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/utils");
|
|
5
|
+
const graphql_1 = require("graphql");
|
|
6
|
+
exports.OPERATOR_MAP = {
|
|
7
|
+
$eq: "=",
|
|
8
|
+
$lt: "<",
|
|
9
|
+
$gt: ">",
|
|
10
|
+
$lte: "<=",
|
|
11
|
+
$gte: ">=",
|
|
12
|
+
$ne: "!=",
|
|
13
|
+
$in: "IN",
|
|
14
|
+
$is: "IS",
|
|
15
|
+
$like: "LIKE",
|
|
16
|
+
$ilike: "ILIKE",
|
|
17
|
+
};
|
|
18
|
+
class QueryBuilder {
|
|
19
|
+
constructor(args) {
|
|
20
|
+
this.schema = args.schema;
|
|
21
|
+
this.entityMap = args.entityMap;
|
|
22
|
+
this.selector = args.selector;
|
|
23
|
+
this.options = args.options;
|
|
24
|
+
this.knex = args.knex;
|
|
25
|
+
this.structure = this.selector.select;
|
|
26
|
+
}
|
|
27
|
+
getStructureKeys(structure) {
|
|
28
|
+
return Object.keys(structure ?? {}).filter((key) => key !== "entity");
|
|
29
|
+
}
|
|
30
|
+
getEntity(path) {
|
|
31
|
+
if (!this.schema._schemaPropertiesMap[path]) {
|
|
32
|
+
throw new Error(`Could not find entity for path: ${path}`);
|
|
33
|
+
}
|
|
34
|
+
return this.schema._schemaPropertiesMap[path];
|
|
35
|
+
}
|
|
36
|
+
getGraphQLType(path, field) {
|
|
37
|
+
const entity = this.getEntity(path)?.ref?.entity;
|
|
38
|
+
const fieldRef = this.entityMap[entity]._fields[field];
|
|
39
|
+
if (!fieldRef) {
|
|
40
|
+
throw new Error(`Field ${field} not found in the entityMap.`);
|
|
41
|
+
}
|
|
42
|
+
let currentType = fieldRef.type;
|
|
43
|
+
let isArray = false;
|
|
44
|
+
while (currentType.ofType) {
|
|
45
|
+
if (currentType instanceof graphql_1.GraphQLList) {
|
|
46
|
+
isArray = true;
|
|
47
|
+
}
|
|
48
|
+
currentType = currentType.ofType;
|
|
49
|
+
}
|
|
50
|
+
return currentType.name + (isArray ? "[]" : "");
|
|
51
|
+
}
|
|
52
|
+
transformValueToType(path, field, value) {
|
|
53
|
+
if (value === null) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const typeToFn = {
|
|
57
|
+
Int: (val) => parseInt(val, 10),
|
|
58
|
+
Float: (val) => parseFloat(val),
|
|
59
|
+
String: (val) => String(val),
|
|
60
|
+
Boolean: (val) => Boolean(val),
|
|
61
|
+
ID: (val) => String(val),
|
|
62
|
+
Date: (val) => new Date(val).toISOString(),
|
|
63
|
+
Time: (val) => new Date(`1970-01-01T${val}Z`).toISOString(),
|
|
64
|
+
};
|
|
65
|
+
const fullPath = [path, ...field];
|
|
66
|
+
const prop = fullPath.pop();
|
|
67
|
+
const fieldPath = fullPath.join(".");
|
|
68
|
+
const graphqlType = this.getGraphQLType(fieldPath, prop).replace("[]", "");
|
|
69
|
+
const fn = typeToFn[graphqlType];
|
|
70
|
+
if (Array.isArray(value)) {
|
|
71
|
+
return value.map((v) => (!fn ? v : fn(v)));
|
|
72
|
+
}
|
|
73
|
+
return !fn ? value : fn(value);
|
|
74
|
+
}
|
|
75
|
+
getPostgresCastType(path, field) {
|
|
76
|
+
const graphqlToPostgresTypeMap = {
|
|
77
|
+
Int: "::int",
|
|
78
|
+
Float: "::double precision",
|
|
79
|
+
Boolean: "::boolean",
|
|
80
|
+
Date: "::timestamp",
|
|
81
|
+
Time: "::time",
|
|
82
|
+
"": "",
|
|
83
|
+
};
|
|
84
|
+
const fullPath = [path, ...field];
|
|
85
|
+
const prop = fullPath.pop();
|
|
86
|
+
const fieldPath = fullPath.join(".");
|
|
87
|
+
let graphqlType = this.getGraphQLType(fieldPath, prop);
|
|
88
|
+
const isList = graphqlType.endsWith("[]");
|
|
89
|
+
graphqlType = graphqlType.replace("[]", "");
|
|
90
|
+
return ((graphqlToPostgresTypeMap[graphqlType] ?? "") + (isList ? "[]" : "") ?? "");
|
|
91
|
+
}
|
|
92
|
+
parseWhere(aliasMapping, obj, builder) {
|
|
93
|
+
const keys = Object.keys(obj);
|
|
94
|
+
const getPathAndField = (key) => {
|
|
95
|
+
const path = key.split(".");
|
|
96
|
+
const field = [path.pop()];
|
|
97
|
+
while (!aliasMapping[path.join(".")] && path.length > 0) {
|
|
98
|
+
field.unshift(path.pop());
|
|
99
|
+
}
|
|
100
|
+
const attr = path.join(".");
|
|
101
|
+
return { field, attr };
|
|
102
|
+
};
|
|
103
|
+
const getPathOperation = (attr, path, value) => {
|
|
104
|
+
const partialPath = path.length > 1 ? path.slice(0, -1) : path;
|
|
105
|
+
const val = this.transformValueToType(attr, partialPath, value);
|
|
106
|
+
const result = path.reduceRight((acc, key) => {
|
|
107
|
+
return { [key]: acc };
|
|
108
|
+
}, val);
|
|
109
|
+
return JSON.stringify(result);
|
|
110
|
+
};
|
|
111
|
+
keys.forEach((key) => {
|
|
112
|
+
let value = obj[key];
|
|
113
|
+
if ((key === "$and" || key === "$or") && !Array.isArray(value)) {
|
|
114
|
+
value = [value];
|
|
115
|
+
}
|
|
116
|
+
if (key === "$and" && Array.isArray(value)) {
|
|
117
|
+
builder.where((qb) => {
|
|
118
|
+
value.forEach((cond) => {
|
|
119
|
+
qb.andWhere((subBuilder) => this.parseWhere(aliasMapping, cond, subBuilder));
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
else if (key === "$or" && Array.isArray(value)) {
|
|
124
|
+
builder.where((qb) => {
|
|
125
|
+
value.forEach((cond) => {
|
|
126
|
+
qb.orWhere((subBuilder) => this.parseWhere(aliasMapping, cond, subBuilder));
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
else if ((0, utils_1.isObject)(value) && !Array.isArray(value)) {
|
|
131
|
+
const subKeys = Object.keys(value);
|
|
132
|
+
subKeys.forEach((subKey) => {
|
|
133
|
+
let operator = exports.OPERATOR_MAP[subKey];
|
|
134
|
+
if (operator) {
|
|
135
|
+
const { field, attr } = getPathAndField(key);
|
|
136
|
+
const nested = new Array(field.length).join("->?");
|
|
137
|
+
const subValue = this.transformValueToType(attr, field, value[subKey]);
|
|
138
|
+
const castType = this.getPostgresCastType(attr, field);
|
|
139
|
+
const val = operator === "IN" ? subValue : [subValue];
|
|
140
|
+
if (operator === "=" && subValue === null) {
|
|
141
|
+
operator = "IS";
|
|
142
|
+
}
|
|
143
|
+
if (operator === "=") {
|
|
144
|
+
builder.whereRaw(`${aliasMapping[attr]}.data @> '${getPathOperation(attr, field, subValue)}'::jsonb`);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
builder.whereRaw(`(${aliasMapping[attr]}.data${nested}->>?)${castType} ${operator} ?`, [...field, ...val]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
throw new Error(`Unsupported operator: ${subKey}`);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const { field, attr } = getPathAndField(key);
|
|
157
|
+
const nested = new Array(field.length).join("->?");
|
|
158
|
+
value = this.transformValueToType(attr, field, value);
|
|
159
|
+
if (Array.isArray(value)) {
|
|
160
|
+
const castType = this.getPostgresCastType(attr, field);
|
|
161
|
+
const inPlaceholders = value.map(() => "?").join(",");
|
|
162
|
+
builder.whereRaw(`(${aliasMapping[attr]}.data${nested}->>?)${castType} IN (${inPlaceholders})`, [...field, ...value]);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
const operator = value === null ? "IS" : "=";
|
|
166
|
+
if (operator === "=") {
|
|
167
|
+
builder.whereRaw(`${aliasMapping[attr]}.data @> '${getPathOperation(attr, field, value)}'::jsonb`);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
const castType = this.getPostgresCastType(attr, field);
|
|
171
|
+
builder.whereRaw(`(${aliasMapping[attr]}.data${nested}->>?)${castType} ${operator} ?`, [...field, value]);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
return builder;
|
|
177
|
+
}
|
|
178
|
+
buildQueryParts(structure, parentAlias, parentEntity, parentProperty, aliasPath = [], level = 0, aliasMapping = {}) {
|
|
179
|
+
const currentAliasPath = [...aliasPath, parentProperty].join(".");
|
|
180
|
+
const entities = this.getEntity(currentAliasPath);
|
|
181
|
+
const mainEntity = entities.ref.entity;
|
|
182
|
+
const mainAlias = mainEntity.toLowerCase() + level;
|
|
183
|
+
const allEntities = [];
|
|
184
|
+
if (!entities.shortCutOf) {
|
|
185
|
+
allEntities.push({
|
|
186
|
+
entity: mainEntity,
|
|
187
|
+
parEntity: parentEntity,
|
|
188
|
+
parAlias: parentAlias,
|
|
189
|
+
alias: mainAlias,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
const intermediateAlias = entities.shortCutOf.split(".");
|
|
194
|
+
for (let i = intermediateAlias.length - 1, x = 0; i >= 0; i--, x++) {
|
|
195
|
+
const intermediateEntity = this.getEntity(intermediateAlias.join("."));
|
|
196
|
+
intermediateAlias.pop();
|
|
197
|
+
if (intermediateEntity.ref.entity === parentEntity) {
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
const parentIntermediateEntity = this.getEntity(intermediateAlias.join("."));
|
|
201
|
+
const alias = intermediateEntity.ref.entity.toLowerCase() + level + "_" + x;
|
|
202
|
+
const parAlias = parentIntermediateEntity.ref.entity === parentEntity
|
|
203
|
+
? parentAlias
|
|
204
|
+
: parentIntermediateEntity.ref.entity.toLowerCase() +
|
|
205
|
+
level +
|
|
206
|
+
"_" +
|
|
207
|
+
(x + 1);
|
|
208
|
+
if (x === 0) {
|
|
209
|
+
aliasMapping[currentAliasPath] = alias;
|
|
210
|
+
}
|
|
211
|
+
allEntities.unshift({
|
|
212
|
+
entity: intermediateEntity.ref.entity,
|
|
213
|
+
parEntity: parentIntermediateEntity.ref.entity,
|
|
214
|
+
parAlias,
|
|
215
|
+
alias,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
let queryParts = [];
|
|
220
|
+
for (const join of allEntities) {
|
|
221
|
+
const { alias, entity, parEntity, parAlias } = join;
|
|
222
|
+
aliasMapping[currentAliasPath] = alias;
|
|
223
|
+
if (level > 0) {
|
|
224
|
+
const subQuery = this.knex.queryBuilder();
|
|
225
|
+
const knex = this.knex;
|
|
226
|
+
subQuery
|
|
227
|
+
.select(`${alias}.id`, `${alias}.data`)
|
|
228
|
+
.from("index_data AS " + alias)
|
|
229
|
+
.join(`index_relation AS ${alias}_ref`, function () {
|
|
230
|
+
this.on(`${alias}_ref.pivot`, "=", knex.raw("?", [`${parEntity}-${entity}`]))
|
|
231
|
+
.andOn(`${alias}_ref.parent_id`, "=", `${parAlias}.id`)
|
|
232
|
+
.andOn(`${alias}.id`, "=", `${alias}_ref.child_id`);
|
|
233
|
+
})
|
|
234
|
+
.where(`${alias}.name`, "=", knex.raw("?", [entity]));
|
|
235
|
+
const joinWhere = this.selector.joinWhere ?? {};
|
|
236
|
+
const joinKey = Object.keys(joinWhere).find((key) => {
|
|
237
|
+
const k = key.split(".");
|
|
238
|
+
k.pop();
|
|
239
|
+
return k.join(".") === currentAliasPath;
|
|
240
|
+
});
|
|
241
|
+
if (joinKey) {
|
|
242
|
+
this.parseWhere(aliasMapping, { [joinKey]: joinWhere[joinKey] }, subQuery);
|
|
243
|
+
}
|
|
244
|
+
queryParts.push(`LEFT JOIN LATERAL (
|
|
245
|
+
${subQuery.toQuery()}
|
|
246
|
+
) ${alias} ON TRUE`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const children = this.getStructureKeys(structure);
|
|
250
|
+
for (const child of children) {
|
|
251
|
+
const childStructure = structure[child];
|
|
252
|
+
queryParts = queryParts.concat(this.buildQueryParts(childStructure, mainAlias, mainEntity, child, aliasPath.concat(parentProperty), level + 1, aliasMapping));
|
|
253
|
+
}
|
|
254
|
+
return queryParts;
|
|
255
|
+
}
|
|
256
|
+
buildSelectParts(structure, parentProperty, aliasMapping, aliasPath = [], selectParts = {}) {
|
|
257
|
+
const currentAliasPath = [...aliasPath, parentProperty].join(".");
|
|
258
|
+
const alias = aliasMapping[currentAliasPath];
|
|
259
|
+
selectParts[currentAliasPath] = `${alias}.data`;
|
|
260
|
+
selectParts[currentAliasPath + ".id"] = `${alias}.id`;
|
|
261
|
+
const children = this.getStructureKeys(structure);
|
|
262
|
+
for (const child of children) {
|
|
263
|
+
const childStructure = structure[child];
|
|
264
|
+
this.buildSelectParts(childStructure, child, aliasMapping, aliasPath.concat(parentProperty), selectParts);
|
|
265
|
+
}
|
|
266
|
+
return selectParts;
|
|
267
|
+
}
|
|
268
|
+
transformOrderBy(arr) {
|
|
269
|
+
const result = {};
|
|
270
|
+
const map = new Map();
|
|
271
|
+
map.set(true, "ASC");
|
|
272
|
+
map.set(1, "ASC");
|
|
273
|
+
map.set("ASC", "ASC");
|
|
274
|
+
map.set(false, "DESC");
|
|
275
|
+
map.set(-1, "DESC");
|
|
276
|
+
map.set("DESC", "DESC");
|
|
277
|
+
function nested(obj, prefix = "") {
|
|
278
|
+
const keys = Object.keys(obj);
|
|
279
|
+
if (!keys.length) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
else if (keys.length > 1) {
|
|
283
|
+
throw new Error("Order by only supports one key per object.");
|
|
284
|
+
}
|
|
285
|
+
const key = keys[0];
|
|
286
|
+
let value = obj[key];
|
|
287
|
+
if ((0, utils_1.isObject)(value)) {
|
|
288
|
+
nested(value, prefix + key + ".");
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
if ((0, utils_1.isString)(value)) {
|
|
292
|
+
value = value.toUpperCase();
|
|
293
|
+
}
|
|
294
|
+
result[prefix + key] = map.get(value) ?? "ASC";
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
arr.forEach((obj) => nested(obj));
|
|
298
|
+
return result;
|
|
299
|
+
}
|
|
300
|
+
buildQuery(countAllResults = true, returnIdOnly = false) {
|
|
301
|
+
const queryBuilder = this.knex.queryBuilder();
|
|
302
|
+
const structure = this.structure;
|
|
303
|
+
const filter = this.selector.where ?? {};
|
|
304
|
+
const { orderBy: order, skip, take } = this.options ?? {};
|
|
305
|
+
const orderBy = this.transformOrderBy((order && !Array.isArray(order) ? [order] : order) ?? []);
|
|
306
|
+
const rootKey = this.getStructureKeys(structure)[0];
|
|
307
|
+
const rootStructure = structure[rootKey];
|
|
308
|
+
const entity = this.getEntity(rootKey).ref.entity;
|
|
309
|
+
const rootEntity = entity.toLowerCase();
|
|
310
|
+
const aliasMapping = {};
|
|
311
|
+
const joinParts = this.buildQueryParts(rootStructure, "", entity, rootKey, [], 0, aliasMapping);
|
|
312
|
+
const rootAlias = aliasMapping[rootKey];
|
|
313
|
+
const selectParts = !returnIdOnly
|
|
314
|
+
? this.buildSelectParts(rootStructure, rootKey, aliasMapping)
|
|
315
|
+
: { [rootKey + ".id"]: `${rootAlias}.id` };
|
|
316
|
+
if (countAllResults) {
|
|
317
|
+
selectParts["offset_"] = this.knex.raw(`DENSE_RANK() OVER (ORDER BY ${rootEntity}0.id)`);
|
|
318
|
+
}
|
|
319
|
+
queryBuilder.select(selectParts);
|
|
320
|
+
queryBuilder.from(`index_data AS ${rootEntity}0`);
|
|
321
|
+
joinParts.forEach((joinPart) => {
|
|
322
|
+
queryBuilder.joinRaw(joinPart);
|
|
323
|
+
});
|
|
324
|
+
queryBuilder.where(`${aliasMapping[rootEntity]}.name`, "=", entity);
|
|
325
|
+
// WHERE clause
|
|
326
|
+
this.parseWhere(aliasMapping, filter, queryBuilder);
|
|
327
|
+
// ORDER BY clause
|
|
328
|
+
for (const aliasPath in orderBy) {
|
|
329
|
+
const path = aliasPath.split(".");
|
|
330
|
+
const field = path.pop();
|
|
331
|
+
const attr = path.join(".");
|
|
332
|
+
const alias = aliasMapping[attr];
|
|
333
|
+
const direction = orderBy[aliasPath];
|
|
334
|
+
queryBuilder.orderByRaw(`${alias}.data->>'${field}' ${direction}`);
|
|
335
|
+
}
|
|
336
|
+
let sql = `WITH data AS (${queryBuilder.toQuery()})
|
|
337
|
+
SELECT * ${countAllResults ? ", (SELECT max(offset_) FROM data) AS count" : ""}
|
|
338
|
+
FROM data`;
|
|
339
|
+
let take_ = !isNaN(+take) ? +take : 15;
|
|
340
|
+
let skip_ = !isNaN(+skip) ? +skip : 0;
|
|
341
|
+
if (typeof take === "number" || typeof skip === "number") {
|
|
342
|
+
sql += `
|
|
343
|
+
WHERE offset_ > ${skip_}
|
|
344
|
+
AND offset_ <= ${skip_ + take_}
|
|
345
|
+
`;
|
|
346
|
+
}
|
|
347
|
+
return sql;
|
|
348
|
+
}
|
|
349
|
+
buildObjectFromResultset(resultSet) {
|
|
350
|
+
const structure = this.structure;
|
|
351
|
+
const rootKey = this.getStructureKeys(structure)[0];
|
|
352
|
+
const maps = {};
|
|
353
|
+
const isListMap = {};
|
|
354
|
+
const referenceMap = {};
|
|
355
|
+
const pathDetails = {};
|
|
356
|
+
const initializeMaps = (structure, path) => {
|
|
357
|
+
const currentPath = path.join(".");
|
|
358
|
+
maps[currentPath] = {};
|
|
359
|
+
if (path.length > 1) {
|
|
360
|
+
const property = path[path.length - 1];
|
|
361
|
+
const parents = path.slice(0, -1);
|
|
362
|
+
const parentPath = parents.join(".");
|
|
363
|
+
isListMap[currentPath] = !!this.getEntity(currentPath).ref.parents.find((p) => p.targetProp === property)?.isList;
|
|
364
|
+
pathDetails[currentPath] = { property, parents, parentPath };
|
|
365
|
+
}
|
|
366
|
+
const children = this.getStructureKeys(structure);
|
|
367
|
+
for (const key of children) {
|
|
368
|
+
initializeMaps(structure[key], [...path, key]);
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
initializeMaps(structure[rootKey], [rootKey]);
|
|
372
|
+
function buildReferenceKey(path, id, row) {
|
|
373
|
+
let current = "";
|
|
374
|
+
let key = "";
|
|
375
|
+
for (const p of path) {
|
|
376
|
+
current += `${p}`;
|
|
377
|
+
key += row[`${current}.id`] + ".";
|
|
378
|
+
current += ".";
|
|
379
|
+
}
|
|
380
|
+
return key + id;
|
|
381
|
+
}
|
|
382
|
+
resultSet.forEach((row) => {
|
|
383
|
+
for (const path in maps) {
|
|
384
|
+
const id = row[`${path}.id`];
|
|
385
|
+
// root level
|
|
386
|
+
if (!pathDetails[path]) {
|
|
387
|
+
if (!maps[path][id]) {
|
|
388
|
+
maps[path][id] = row[path] || undefined;
|
|
389
|
+
}
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
const { property, parents, parentPath } = pathDetails[path];
|
|
393
|
+
const referenceKey = buildReferenceKey(parents, id, row);
|
|
394
|
+
if (referenceMap[referenceKey]) {
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
maps[path][id] = row[path] || undefined;
|
|
398
|
+
const parentObj = maps[parentPath][row[`${parentPath}.id`]];
|
|
399
|
+
if (!parentObj) {
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
const isList = isListMap[parentPath + "." + property];
|
|
403
|
+
if (isList) {
|
|
404
|
+
parentObj[property] ??= [];
|
|
405
|
+
}
|
|
406
|
+
if (maps[path][id] !== undefined) {
|
|
407
|
+
if (isList) {
|
|
408
|
+
parentObj[property].push(maps[path][id]);
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
parentObj[property] = maps[path][id];
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
referenceMap[referenceKey] = true;
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
return Object.values(maps[rootKey] ?? {});
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
exports.QueryBuilder = QueryBuilder;
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@medusajs/index",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Medusa Index module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=20"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/medusajs/medusa",
|
|
16
|
+
"directory": "packages/index"
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"author": "Medusa",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"scripts": {
|
|
24
|
+
"watch": "tsc --build --watch",
|
|
25
|
+
"watch:test": "tsc --build tsconfig.spec.json --watch",
|
|
26
|
+
"build": "rimraf dist && tsc -p ./tsconfig.spec.json --noEmit && tsc -p ./tsconfig.build.json && tsc-alias -p ./tsconfig.build.json",
|
|
27
|
+
"test": "jest --passWithNoTests ./src",
|
|
28
|
+
"test:integration": "jest --runInBand --forceExit -- integration-tests/**/__tests__/**/*.ts",
|
|
29
|
+
"migration:generate": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:generate",
|
|
30
|
+
"migration:initial": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create --initial",
|
|
31
|
+
"migration:create": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create",
|
|
32
|
+
"migration:up": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:up",
|
|
33
|
+
"orm:cache:clear": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm cache:clear"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@medusajs/types": "^1.11.16",
|
|
37
|
+
"@mikro-orm/cli": "5.9.7",
|
|
38
|
+
"cross-env": "^5.2.1",
|
|
39
|
+
"jest": "^29.7.0",
|
|
40
|
+
"medusa-test-utils": "^1.1.44",
|
|
41
|
+
"rimraf": "^3.0.2",
|
|
42
|
+
"ts-node": "^10.9.1",
|
|
43
|
+
"tsc-alias": "^1.8.6",
|
|
44
|
+
"typescript": "^5.1.6"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@medusajs/utils": "^1.11.9"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@mikro-orm/core": "5.9.7",
|
|
51
|
+
"@mikro-orm/migrations": "5.9.7",
|
|
52
|
+
"@mikro-orm/postgresql": "5.9.7",
|
|
53
|
+
"awilix": "^8.0.1"
|
|
54
|
+
}
|
|
55
|
+
}
|