@objectql/core 0.1.0
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/dist/driver.d.ts +17 -0
- package/dist/driver.js +3 -0
- package/dist/driver.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +115 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +2 -0
- package/dist/loader.js +143 -0
- package/dist/loader.js.map +1 -0
- package/dist/metadata.d.ts +102 -0
- package/dist/metadata.js +3 -0
- package/dist/metadata.js.map +1 -0
- package/dist/query.d.ts +10 -0
- package/dist/query.js +3 -0
- package/dist/query.js.map +1 -0
- package/dist/repository.d.ts +26 -0
- package/dist/repository.js +209 -0
- package/dist/repository.js.map +1 -0
- package/dist/types.d.ts +75 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/jest.config.js +5 -0
- package/package.json +14 -0
- package/src/driver.ts +24 -0
- package/src/index.ts +107 -0
- package/src/loader.ts +120 -0
- package/src/metadata.ts +141 -0
- package/src/query.ts +11 -0
- package/src/repository.ts +232 -0
- package/src/types.ts +107 -0
- package/test/fixtures/project.object.yml +41 -0
- package/test/loader.test.ts +14 -0
- package/test/metadata.test.ts +49 -0
- package/test/mock-driver.ts +86 -0
- package/test/repository.test.ts +150 -0
- package/tsconfig.json +8 -0
- package/tsconfig.tsbuildinfo +1 -0
package/dist/driver.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface Driver {
|
|
2
|
+
find(objectName: string, query: any, options?: any): Promise<any[]>;
|
|
3
|
+
findOne(objectName: string, id: string | number, query?: any, options?: any): Promise<any>;
|
|
4
|
+
create(objectName: string, data: any, options?: any): Promise<any>;
|
|
5
|
+
update(objectName: string, id: string | number, data: any, options?: any): Promise<any>;
|
|
6
|
+
delete(objectName: string, id: string | number, options?: any): Promise<any>;
|
|
7
|
+
count(objectName: string, filters: any, options?: any): Promise<number>;
|
|
8
|
+
aggregate?(objectName: string, query: any, options?: any): Promise<any>;
|
|
9
|
+
distinct?(objectName: string, field: string, filters?: any, options?: any): Promise<any[]>;
|
|
10
|
+
createMany?(objectName: string, data: any[], options?: any): Promise<any>;
|
|
11
|
+
updateMany?(objectName: string, filters: any, data: any, options?: any): Promise<any>;
|
|
12
|
+
deleteMany?(objectName: string, filters: any, options?: any): Promise<any>;
|
|
13
|
+
findOneAndUpdate?(objectName: string, filters: any, update: any, options?: any): Promise<any>;
|
|
14
|
+
beginTransaction?(): Promise<any>;
|
|
15
|
+
commitTransaction?(trx: any): Promise<void>;
|
|
16
|
+
rollbackTransaction?(trx: any): Promise<void>;
|
|
17
|
+
}
|
package/dist/driver.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":""}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from './metadata';
|
|
2
|
+
export * from './types';
|
|
3
|
+
export * from './driver';
|
|
4
|
+
export * from './repository';
|
|
5
|
+
export * from './query';
|
|
6
|
+
import { ObjectConfig } from './metadata';
|
|
7
|
+
import { ObjectQLContext, ObjectQLContextOptions, IObjectQL, ObjectQLConfig } from './types';
|
|
8
|
+
import { Driver } from './driver';
|
|
9
|
+
export declare class ObjectQL implements IObjectQL {
|
|
10
|
+
private objects;
|
|
11
|
+
private datasources;
|
|
12
|
+
constructor(config: ObjectQLConfig);
|
|
13
|
+
loadFromDirectory(dir: string): void;
|
|
14
|
+
createContext(options: ObjectQLContextOptions): ObjectQLContext;
|
|
15
|
+
registerObject(object: ObjectConfig): void;
|
|
16
|
+
getObject(name: string): ObjectConfig | undefined;
|
|
17
|
+
getConfigs(): Record<string, ObjectConfig>;
|
|
18
|
+
datasource(name: string): Driver;
|
|
19
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
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
|
+
exports.ObjectQL = void 0;
|
|
18
|
+
__exportStar(require("./metadata"), exports);
|
|
19
|
+
__exportStar(require("./types"), exports);
|
|
20
|
+
__exportStar(require("./driver"), exports);
|
|
21
|
+
__exportStar(require("./repository"), exports);
|
|
22
|
+
__exportStar(require("./query"), exports);
|
|
23
|
+
const repository_1 = require("./repository");
|
|
24
|
+
const loader_1 = require("./loader");
|
|
25
|
+
class ObjectQL {
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.objects = {};
|
|
28
|
+
this.datasources = {};
|
|
29
|
+
this.datasources = config.datasources;
|
|
30
|
+
if (config.objects) {
|
|
31
|
+
for (const obj of Object.values(config.objects)) {
|
|
32
|
+
this.registerObject(obj);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
loadFromDirectory(dir) {
|
|
37
|
+
const objects = (0, loader_1.loadObjectConfigs)(dir);
|
|
38
|
+
for (const obj of Object.values(objects)) {
|
|
39
|
+
this.registerObject(obj);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
createContext(options) {
|
|
43
|
+
const ctx = {
|
|
44
|
+
userId: options.userId,
|
|
45
|
+
spaceId: options.spaceId,
|
|
46
|
+
roles: options.roles || [],
|
|
47
|
+
isSystem: options.isSystem,
|
|
48
|
+
ignoreTriggers: options.ignoreTriggers,
|
|
49
|
+
object: (name) => {
|
|
50
|
+
return new repository_1.ObjectRepository(name, ctx, this);
|
|
51
|
+
},
|
|
52
|
+
transaction: async (callback) => {
|
|
53
|
+
const driver = this.datasources['default'];
|
|
54
|
+
if (!driver || !driver.beginTransaction) {
|
|
55
|
+
return callback(ctx);
|
|
56
|
+
}
|
|
57
|
+
let trx;
|
|
58
|
+
try {
|
|
59
|
+
trx = await driver.beginTransaction();
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
// If beginTransaction fails, fail.
|
|
63
|
+
throw e;
|
|
64
|
+
}
|
|
65
|
+
const trxCtx = {
|
|
66
|
+
...ctx,
|
|
67
|
+
transactionHandle: trx,
|
|
68
|
+
// Nested transaction simply reuses the current one (flat transaction)
|
|
69
|
+
transaction: async (cb) => cb(trxCtx)
|
|
70
|
+
};
|
|
71
|
+
try {
|
|
72
|
+
const result = await callback(trxCtx);
|
|
73
|
+
if (driver.commitTransaction)
|
|
74
|
+
await driver.commitTransaction(trx);
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (driver.rollbackTransaction)
|
|
79
|
+
await driver.rollbackTransaction(trx);
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
sudo: () => {
|
|
84
|
+
return this.createContext({ ...options, isSystem: true });
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
return ctx;
|
|
88
|
+
}
|
|
89
|
+
registerObject(object) {
|
|
90
|
+
// Normalize fields
|
|
91
|
+
if (object.fields) {
|
|
92
|
+
for (const [key, field] of Object.entries(object.fields)) {
|
|
93
|
+
if (!field.name) {
|
|
94
|
+
field.name = key;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
this.objects[object.name] = object;
|
|
99
|
+
}
|
|
100
|
+
getObject(name) {
|
|
101
|
+
return this.objects[name];
|
|
102
|
+
}
|
|
103
|
+
getConfigs() {
|
|
104
|
+
return this.objects;
|
|
105
|
+
}
|
|
106
|
+
datasource(name) {
|
|
107
|
+
const driver = this.datasources[name];
|
|
108
|
+
if (!driver) {
|
|
109
|
+
throw new Error(`Datasource '${name}' not found`);
|
|
110
|
+
}
|
|
111
|
+
return driver;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.ObjectQL = ObjectQL;
|
|
115
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/loader.d.ts
ADDED
package/dist/loader.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
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 () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.loadObjectConfigs = loadObjectConfigs;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const yaml = __importStar(require("js-yaml"));
|
|
40
|
+
const glob = __importStar(require("fast-glob"));
|
|
41
|
+
function loadObjectConfigs(dir) {
|
|
42
|
+
const configs = {};
|
|
43
|
+
// 1. Load YAML Configs
|
|
44
|
+
const files = glob.sync(['**/*.object.yml', '**/*.object.yaml'], {
|
|
45
|
+
cwd: dir,
|
|
46
|
+
absolute: true
|
|
47
|
+
});
|
|
48
|
+
for (const file of files) {
|
|
49
|
+
try {
|
|
50
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
51
|
+
const doc = yaml.load(content);
|
|
52
|
+
if (doc.name && doc.fields) {
|
|
53
|
+
configs[doc.name] = doc;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
for (const [key, value] of Object.entries(doc)) {
|
|
57
|
+
if (typeof value === 'object' && value.fields) {
|
|
58
|
+
configs[key] = value;
|
|
59
|
+
if (!configs[key].name)
|
|
60
|
+
configs[key].name = key;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
console.error(`Error loading object config from ${file}:`, e);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// 2. Load Hooks (.hook.js, .hook.ts)
|
|
70
|
+
// We only load .js if running in node, or .ts if ts-node/register is present.
|
|
71
|
+
// simpler: look for both, require will handle extension resolution if we are careful.
|
|
72
|
+
// Actually, in `dist` we only find .js. In `src` (test) we find .ts.
|
|
73
|
+
const hookFiles = glob.sync(['**/*.hook.{js,ts}'], {
|
|
74
|
+
cwd: dir,
|
|
75
|
+
absolute: true
|
|
76
|
+
});
|
|
77
|
+
for (const file of hookFiles) {
|
|
78
|
+
try {
|
|
79
|
+
// Check if we should ignore .ts if .js exists?
|
|
80
|
+
// Or assume env handles it.
|
|
81
|
+
// If we are in `dist`, `src` shouldn't be there usually.
|
|
82
|
+
const hookModule = require(file);
|
|
83
|
+
// Default export or named exports?
|
|
84
|
+
// Convention: export const listenTo = 'objectName';
|
|
85
|
+
// or filename based: 'project.hook.js' -> 'project' (flaky)
|
|
86
|
+
let objectName = hookModule.listenTo;
|
|
87
|
+
if (!objectName) {
|
|
88
|
+
// Try to guess from filename?
|
|
89
|
+
// project.hook.ts -> project
|
|
90
|
+
const basename = path.basename(file);
|
|
91
|
+
const match = basename.match(/^(.+)\.hook\.(ts|js)$/);
|
|
92
|
+
if (match) {
|
|
93
|
+
objectName = match[1];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (objectName && configs[objectName]) {
|
|
97
|
+
if (!configs[objectName].listeners) {
|
|
98
|
+
configs[objectName].listeners = {};
|
|
99
|
+
}
|
|
100
|
+
const listeners = configs[objectName].listeners;
|
|
101
|
+
// Merge exported functions into listeners
|
|
102
|
+
// Common hooks: beforeFind, afterFind, beforeCreate, etc.
|
|
103
|
+
const hookNames = [
|
|
104
|
+
'beforeFind', 'afterFind',
|
|
105
|
+
'beforeCreate', 'afterCreate',
|
|
106
|
+
'beforeUpdate', 'afterUpdate',
|
|
107
|
+
'beforeDelete', 'afterDelete'
|
|
108
|
+
];
|
|
109
|
+
for (const name of hookNames) {
|
|
110
|
+
if (typeof hookModule[name] === 'function') {
|
|
111
|
+
listeners[name] = hookModule[name];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Support default export having listeners object?
|
|
115
|
+
if (hookModule.default && typeof hookModule.default === 'object') {
|
|
116
|
+
Object.assign(listeners, hookModule.default);
|
|
117
|
+
}
|
|
118
|
+
// Load Actions
|
|
119
|
+
// Convention: export const actions = { myAction: (ctx, params) => ... }
|
|
120
|
+
// OR export function myAction(ctx, params) ... (Ambiguous with hooks? No, hooks have explicit names)
|
|
121
|
+
// Safer: look for `actions` export.
|
|
122
|
+
if (hookModule.actions && typeof hookModule.actions === 'object') {
|
|
123
|
+
if (!configs[objectName].actions) {
|
|
124
|
+
configs[objectName].actions = {};
|
|
125
|
+
}
|
|
126
|
+
for (const [actionName, handler] of Object.entries(hookModule.actions)) {
|
|
127
|
+
// We might have metadata from YAML already
|
|
128
|
+
if (!configs[objectName].actions[actionName]) {
|
|
129
|
+
configs[objectName].actions[actionName] = {};
|
|
130
|
+
}
|
|
131
|
+
// Attach handler
|
|
132
|
+
configs[objectName].actions[actionName].handler = handler;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (e) {
|
|
138
|
+
console.error(`Error loading hook from ${file}:`, e);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return configs;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the supported field data types in the ObjectQL schema.
|
|
3
|
+
* These types determine how data is stored, validated, and rendered.
|
|
4
|
+
*
|
|
5
|
+
* - `text`: Simple string.
|
|
6
|
+
* - `textarea`: Long string.
|
|
7
|
+
* - `select`: Choice from a list.
|
|
8
|
+
* - `lookup`: Relationship to another object.
|
|
9
|
+
*/
|
|
10
|
+
export type FieldType = 'text' | 'textarea' | 'html' | 'select' | 'multiselect' | 'date' | 'datetime' | 'number' | 'currency' | 'boolean' | 'lookup' | 'master_detail' | 'password' | 'object' | 'grid';
|
|
11
|
+
/**
|
|
12
|
+
* Defines a single option for select/multiselect fields.
|
|
13
|
+
*/
|
|
14
|
+
export interface FieldOption {
|
|
15
|
+
/** The display label for the option. */
|
|
16
|
+
label: string;
|
|
17
|
+
/** The actual value stored in the database. */
|
|
18
|
+
value: string | number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Configuration for a single field on an object.
|
|
22
|
+
* This defines the schema, validation rules, and UI hints for the attribute.
|
|
23
|
+
*/
|
|
24
|
+
export interface FieldConfig {
|
|
25
|
+
/**
|
|
26
|
+
* The unique API name of the field.
|
|
27
|
+
* If defined within an object map, this is often automatically populated from the key.
|
|
28
|
+
*/
|
|
29
|
+
name?: string;
|
|
30
|
+
/** The human-readable label used in UIs. */
|
|
31
|
+
label?: string;
|
|
32
|
+
/** The data type of the field. */
|
|
33
|
+
type: FieldType;
|
|
34
|
+
/** Whether the field is mandatory. Defaults to false. */
|
|
35
|
+
required?: boolean;
|
|
36
|
+
/** The default value if not provided during creation. */
|
|
37
|
+
defaultValue?: any;
|
|
38
|
+
/**
|
|
39
|
+
* Options available for `select` or `multiselect` types.
|
|
40
|
+
* Can be an array of strings or {@link FieldOption} objects.
|
|
41
|
+
*/
|
|
42
|
+
options?: FieldOption[] | string[];
|
|
43
|
+
/** Number of decimal places for `currency` types (e.g., 2). */
|
|
44
|
+
scale?: number;
|
|
45
|
+
/** Total number of digits for `number` types. */
|
|
46
|
+
precision?: number;
|
|
47
|
+
/**
|
|
48
|
+
* The API name of the target object.
|
|
49
|
+
* Required when type is `lookup` or `master_detail`.
|
|
50
|
+
*/
|
|
51
|
+
reference_to?: string;
|
|
52
|
+
/** Implementation hint: Whether this field should be indexed for search. */
|
|
53
|
+
searchable?: boolean;
|
|
54
|
+
/** Implementation hint: Whether this field is sortable in lists. */
|
|
55
|
+
sortable?: boolean;
|
|
56
|
+
/** Implementation hint: Whether to create a database index for this column. */
|
|
57
|
+
index?: boolean;
|
|
58
|
+
/** Description for documentation purposes. */
|
|
59
|
+
description?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Configuration for a custom action (RPC).
|
|
63
|
+
*/
|
|
64
|
+
export interface ActionConfig {
|
|
65
|
+
label?: string;
|
|
66
|
+
description?: string;
|
|
67
|
+
/** Output/Result type definition. */
|
|
68
|
+
result?: {
|
|
69
|
+
type: FieldType;
|
|
70
|
+
};
|
|
71
|
+
/** Input parameters schema. */
|
|
72
|
+
params?: Record<string, FieldConfig>;
|
|
73
|
+
/** Implementation of the action. */
|
|
74
|
+
handler?: (ctx: any, params: any) => Promise<any>;
|
|
75
|
+
}
|
|
76
|
+
import { HookFunction } from './types';
|
|
77
|
+
export interface ObjectListeners {
|
|
78
|
+
beforeCreate?: HookFunction;
|
|
79
|
+
afterCreate?: HookFunction;
|
|
80
|
+
beforeUpdate?: HookFunction;
|
|
81
|
+
afterUpdate?: HookFunction;
|
|
82
|
+
beforeDelete?: HookFunction;
|
|
83
|
+
afterDelete?: HookFunction;
|
|
84
|
+
beforeFind?: HookFunction;
|
|
85
|
+
afterFind?: HookFunction;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Configuration for a business object (Entity).
|
|
89
|
+
* Analogous to a Database Table or MongoDB Collection.
|
|
90
|
+
*/
|
|
91
|
+
export interface ObjectConfig {
|
|
92
|
+
name: string;
|
|
93
|
+
datasource?: string;
|
|
94
|
+
label?: string;
|
|
95
|
+
icon?: string;
|
|
96
|
+
description?: string;
|
|
97
|
+
fields: Record<string, FieldConfig>;
|
|
98
|
+
/** Custom Actions (RPC) defined on this object. */
|
|
99
|
+
actions?: Record<string, ActionConfig>;
|
|
100
|
+
/** Lifecycle hooks. */
|
|
101
|
+
listeners?: ObjectListeners;
|
|
102
|
+
}
|
package/dist/metadata.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":""}
|
package/dist/query.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type FilterCriterion = [string, string, any];
|
|
2
|
+
export type FilterExpression = FilterCriterion | 'and' | 'or' | FilterExpression[];
|
|
3
|
+
export interface UnifiedQuery {
|
|
4
|
+
fields?: string[];
|
|
5
|
+
filters?: FilterExpression[];
|
|
6
|
+
sort?: [string, 'asc' | 'desc'][];
|
|
7
|
+
skip?: number;
|
|
8
|
+
limit?: number;
|
|
9
|
+
expand?: Record<string, UnifiedQuery>;
|
|
10
|
+
}
|
package/dist/query.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ObjectQLContext, IObjectQL } from './types';
|
|
2
|
+
import { ObjectConfig } from './metadata';
|
|
3
|
+
import { UnifiedQuery } from './query';
|
|
4
|
+
export declare class ObjectRepository {
|
|
5
|
+
private objectName;
|
|
6
|
+
private context;
|
|
7
|
+
private app;
|
|
8
|
+
constructor(objectName: string, context: ObjectQLContext, app: IObjectQL);
|
|
9
|
+
private getDriver;
|
|
10
|
+
private getOptions;
|
|
11
|
+
getSchema(): ObjectConfig;
|
|
12
|
+
private executeHook;
|
|
13
|
+
find(query?: UnifiedQuery): Promise<any[]>;
|
|
14
|
+
findOne(idOrQuery: string | number | UnifiedQuery): Promise<any>;
|
|
15
|
+
count(filters: any): Promise<number>;
|
|
16
|
+
create(doc: any): Promise<any>;
|
|
17
|
+
update(id: string | number, doc: any, options?: any): Promise<any>;
|
|
18
|
+
delete(id: string | number): Promise<any>;
|
|
19
|
+
aggregate(query: any): Promise<any>;
|
|
20
|
+
distinct(field: string, filters?: any): Promise<any[]>;
|
|
21
|
+
findOneAndUpdate(filters: any, update: any, options?: any): Promise<any>;
|
|
22
|
+
createMany(data: any[]): Promise<any>;
|
|
23
|
+
updateMany(filters: any, data: any): Promise<any>;
|
|
24
|
+
deleteMany(filters: any): Promise<any>;
|
|
25
|
+
call(actionName: string, params: any): Promise<any>;
|
|
26
|
+
}
|