kodzero-front-sdk-alfa 0.0.2
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/.eslintrc.cjs +13 -0
- package/.eslintrc.json +16 -0
- package/README.md +313 -0
- package/dist/Kodzero.d.ts +33 -0
- package/dist/Kodzero.js +22 -0
- package/dist/auth/base.d.ts +15 -0
- package/dist/auth/base.js +18 -0
- package/dist/auth/email.d.ts +23 -0
- package/dist/auth/email.js +70 -0
- package/dist/auth/index.d.ts +13 -0
- package/dist/auth/index.js +21 -0
- package/dist/auth/tokens.d.ts +10 -0
- package/dist/auth/tokens.js +22 -0
- package/dist/errors/KodzeroApiError.d.ts +7 -0
- package/dist/errors/KodzeroApiError.js +10 -0
- package/dist/errors/KodzeroValidationError.d.ts +5 -0
- package/dist/errors/KodzeroValidationError.js +8 -0
- package/dist/fetcher/InterceptorManager.d.ts +9 -0
- package/dist/fetcher/InterceptorManager.js +42 -0
- package/dist/fetcher/MiddlewareManager.d.ts +9 -0
- package/dist/fetcher/MiddlewareManager.js +42 -0
- package/dist/fetcher/index.d.ts +77 -0
- package/dist/fetcher/index.js +194 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +49 -0
- package/dist/model/BaseModel.d.ts +38 -0
- package/dist/model/BaseModel.js +119 -0
- package/dist/model/baseModelOptionsSchema.d.ts +2 -0
- package/dist/model/baseModelOptionsSchema.js +10 -0
- package/dist/model/configSchema.d.ts +0 -0
- package/dist/model/configSchema.js +1 -0
- package/dist/model/constants.d.ts +8 -0
- package/dist/model/constants.js +7 -0
- package/dist/model/createModel.d.ts +28 -0
- package/dist/model/createModel.js +159 -0
- package/dist/model/errors/KodzeroApiError.d.ts +7 -0
- package/dist/model/errors/KodzeroApiError.js +10 -0
- package/dist/model/index.d.ts +4 -0
- package/dist/model/index.js +4 -0
- package/dist/model/modelFactory.d.ts +50 -0
- package/dist/model/modelFactory.js +41 -0
- package/dist/model/modelSchema.d.ts +0 -0
- package/dist/model/modelSchema.js +1 -0
- package/dist/model/schemas/baseModel.d.ts +6 -0
- package/dist/model/schemas/baseModel.js +25 -0
- package/dist/model/schemas/baseModelOptionsSchema.d.ts +2 -0
- package/dist/model/schemas/baseModelOptionsSchema.js +10 -0
- package/dist/model/statics/getAll.d.ts +2 -0
- package/dist/model/statics/getAll.js +4 -0
- package/dist/model/utils/processUrl.d.ts +2 -0
- package/dist/model/utils/processUrl.js +7 -0
- package/dist/model/utils/validateApiResponse.d.ts +2 -0
- package/dist/model/utils/validateApiResponse.js +14 -0
- package/dist/schemas/baseAuth.d.ts +6 -0
- package/dist/schemas/baseAuth.js +18 -0
- package/dist/schemas/baseModel copy.d.ts +6 -0
- package/dist/schemas/baseModel copy.js +25 -0
- package/dist/schemas/baseModel.d.ts +6 -0
- package/dist/schemas/baseModel.js +25 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/responses.d.ts +14 -0
- package/dist/types/responses.js +1 -0
- package/dist/utils/buildURL.d.ts +2 -0
- package/dist/utils/buildURL.js +7 -0
- package/dist/utils/buildURL_rename.d.ts +2 -0
- package/dist/utils/buildURL_rename.js +7 -0
- package/dist/utils/processUrl.d.ts +2 -0
- package/dist/utils/processUrl.js +7 -0
- package/dist/utils/validateApiResponse.d.ts +2 -0
- package/dist/utils/validateApiResponse.js +14 -0
- package/jest.config.ts +190 -0
- package/nodemon.json +4 -0
- package/package.json +29 -0
- package/src/Kodzero.ts +35 -0
- package/src/auth/base.ts +37 -0
- package/src/auth/email.ts +123 -0
- package/src/auth/index.ts +43 -0
- package/src/auth/tokens.ts +49 -0
- package/src/errors/KodzeroApiError.ts +17 -0
- package/src/errors/KodzeroValidationError.ts +12 -0
- package/src/model/BaseModel.ts +210 -0
- package/src/model/constants.ts +7 -0
- package/src/model/createModel.ts +237 -0
- package/src/model/index.ts +12 -0
- package/src/schemas/baseAuth.ts +28 -0
- package/src/schemas/baseModel.ts +35 -0
- package/src/tsconfig.json +103 -0
- package/src/types/module.d.ts +2 -0
- package/src/types/responses.ts +14 -0
- package/src/utils/buildURL_rename.ts +8 -0
- package/src/utils/validateApiResponse.ts +17 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class MiddlewareManager {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.handlers = [];
|
|
4
|
+
this.idCounter = 0;
|
|
5
|
+
}
|
|
6
|
+
use(fulfilled, rejected) {
|
|
7
|
+
const id = this.idCounter++;
|
|
8
|
+
this.handlers.push({
|
|
9
|
+
fulfilled,
|
|
10
|
+
rejected,
|
|
11
|
+
id
|
|
12
|
+
});
|
|
13
|
+
return id;
|
|
14
|
+
}
|
|
15
|
+
eject(id) {
|
|
16
|
+
const index = this.handlers.findIndex(handler => handler.id === id);
|
|
17
|
+
if (index !== -1) {
|
|
18
|
+
this.handlers.splice(index, 1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
clear() {
|
|
22
|
+
this.handlers = [];
|
|
23
|
+
}
|
|
24
|
+
async runMiddlewares(value) {
|
|
25
|
+
let result = value;
|
|
26
|
+
for (const handler of this.handlers) {
|
|
27
|
+
try {
|
|
28
|
+
result = await handler.fulfilled(result);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (handler.rejected) {
|
|
32
|
+
result = await handler.rejected(error);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export default MiddlewareManager;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare class MiddlewareManager<T> {
|
|
2
|
+
private handlers;
|
|
3
|
+
private idCounter;
|
|
4
|
+
use(fulfilled: (value: T) => Promise<T> | T, rejected?: (error: any) => any): number;
|
|
5
|
+
eject(id: number): void;
|
|
6
|
+
clear(): void;
|
|
7
|
+
runMiddlewares(value: T): Promise<T>;
|
|
8
|
+
}
|
|
9
|
+
export default MiddlewareManager;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class MiddlewareManager {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.handlers = [];
|
|
4
|
+
this.idCounter = 0;
|
|
5
|
+
}
|
|
6
|
+
use(fulfilled, rejected) {
|
|
7
|
+
const id = this.idCounter++;
|
|
8
|
+
this.handlers.push({
|
|
9
|
+
fulfilled,
|
|
10
|
+
rejected,
|
|
11
|
+
id
|
|
12
|
+
});
|
|
13
|
+
return id;
|
|
14
|
+
}
|
|
15
|
+
eject(id) {
|
|
16
|
+
const index = this.handlers.findIndex(handler => handler.id === id);
|
|
17
|
+
if (index !== -1) {
|
|
18
|
+
this.handlers.splice(index, 1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
clear() {
|
|
22
|
+
this.handlers = [];
|
|
23
|
+
}
|
|
24
|
+
async runMiddlewares(value) {
|
|
25
|
+
let result = value;
|
|
26
|
+
for (const handler of this.handlers) {
|
|
27
|
+
try {
|
|
28
|
+
result = await handler.fulfilled(result);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (handler.rejected) {
|
|
32
|
+
result = await handler.rejected(error);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export default MiddlewareManager;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import MiddlewareManager from './MiddlewareManager.js';
|
|
2
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
3
|
+
declare class TimeoutError extends Error {
|
|
4
|
+
constructor(message: string);
|
|
5
|
+
}
|
|
6
|
+
interface RequestConfig {
|
|
7
|
+
headers?: Record<string, string>;
|
|
8
|
+
params?: Record<string, string | number | boolean>;
|
|
9
|
+
cache?: boolean | number;
|
|
10
|
+
timeout?: number;
|
|
11
|
+
}
|
|
12
|
+
interface RequestMiddleware {
|
|
13
|
+
(request: Request): Promise<Request> | Request;
|
|
14
|
+
}
|
|
15
|
+
interface ResponseMiddleware {
|
|
16
|
+
(response: Response): Promise<Response> | Response;
|
|
17
|
+
}
|
|
18
|
+
interface Middlewares {
|
|
19
|
+
request: RequestMiddleware[];
|
|
20
|
+
response: ResponseMiddleware[];
|
|
21
|
+
}
|
|
22
|
+
interface Request {
|
|
23
|
+
method: HttpMethod;
|
|
24
|
+
url: string;
|
|
25
|
+
data: any | null;
|
|
26
|
+
headers: Record<string, string>;
|
|
27
|
+
params: Record<string, string | number | boolean>;
|
|
28
|
+
cache?: boolean | number;
|
|
29
|
+
timeout?: number;
|
|
30
|
+
abortController: AbortController;
|
|
31
|
+
}
|
|
32
|
+
declare class FluidFetch {
|
|
33
|
+
private cache;
|
|
34
|
+
private pendingRequests;
|
|
35
|
+
middlewares: {
|
|
36
|
+
request: MiddlewareManager<Request>;
|
|
37
|
+
response: MiddlewareManager<Response>;
|
|
38
|
+
};
|
|
39
|
+
interceptors: Middlewares & {
|
|
40
|
+
request: MiddlewareManager<Request>;
|
|
41
|
+
response: MiddlewareManager<Response>;
|
|
42
|
+
};
|
|
43
|
+
constructor();
|
|
44
|
+
get<T = any>(url: string, config?: RequestConfig): FluidFetchRequest<T>;
|
|
45
|
+
post<T = any>(url: string, data?: any, config?: RequestConfig): FluidFetchRequest<T>;
|
|
46
|
+
put<T = any>(url: string, data?: any, config?: RequestConfig): FluidFetchRequest<T>;
|
|
47
|
+
delete<T = any>(url: string, config?: RequestConfig): FluidFetchRequest<T>;
|
|
48
|
+
private _createRequest;
|
|
49
|
+
_getCacheKey(request: Request): string;
|
|
50
|
+
_buildUrl(url: string, params: Record<string, string | number | boolean> | undefined): string;
|
|
51
|
+
getCachedResponse(cacheKey: string): Response | undefined;
|
|
52
|
+
getPendingRequest(cacheKey: string): AbortController | undefined;
|
|
53
|
+
registerPendingRequest(cacheKey: string, controller: AbortController): void;
|
|
54
|
+
removePendingRequest(cacheKey: string): void;
|
|
55
|
+
cacheResponse(cacheKey: string, response: Response, ttl?: number): void;
|
|
56
|
+
clearRequestMiddlewares(): void;
|
|
57
|
+
clearResponseMiddlewares(): void;
|
|
58
|
+
clearRequestInterceptors(): void;
|
|
59
|
+
clearResponseInterceptors(): void;
|
|
60
|
+
}
|
|
61
|
+
declare class FluidFetchRequest<T = any> implements PromiseLike<Response> {
|
|
62
|
+
private fluidFetch;
|
|
63
|
+
private request;
|
|
64
|
+
private promise;
|
|
65
|
+
constructor(fluidFetch: FluidFetch, request: Request);
|
|
66
|
+
headers(headers: Record<string, string>): FluidFetchRequest<T>;
|
|
67
|
+
params(params: Record<string, string | number | boolean>): FluidFetchRequest<T>;
|
|
68
|
+
body(data: any): FluidFetchRequest<T>;
|
|
69
|
+
cache(ttl: boolean | number): FluidFetchRequest<T>;
|
|
70
|
+
timeout(ms: number): FluidFetchRequest<T>;
|
|
71
|
+
cancel(): FluidFetchRequest<T>;
|
|
72
|
+
then<TResult1 = Response, TResult2 = never>(onFulfilled?: ((value: Response) => TResult1 | PromiseLike<TResult1>) | undefined | null, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;
|
|
73
|
+
catch<TResult = never>(onRejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): PromiseLike<Response | TResult>;
|
|
74
|
+
private _executeRequest;
|
|
75
|
+
}
|
|
76
|
+
export { TimeoutError, MiddlewareManager, RequestMiddleware, ResponseMiddleware };
|
|
77
|
+
export default FluidFetch;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import MiddlewareManager from './MiddlewareManager.js';
|
|
2
|
+
class TimeoutError extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = 'TimeoutError';
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
class FluidFetch {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.cache = new Map();
|
|
11
|
+
this.pendingRequests = new Map();
|
|
12
|
+
const requestManager = new MiddlewareManager();
|
|
13
|
+
const responseManager = new MiddlewareManager();
|
|
14
|
+
this.middlewares = {
|
|
15
|
+
request: requestManager,
|
|
16
|
+
response: responseManager
|
|
17
|
+
};
|
|
18
|
+
this.interceptors = {
|
|
19
|
+
request: requestManager,
|
|
20
|
+
response: responseManager
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(this.interceptors.request, 'push', {
|
|
23
|
+
value: (fn) => requestManager.use(fn)
|
|
24
|
+
});
|
|
25
|
+
Object.defineProperty(this.interceptors.response, 'push', {
|
|
26
|
+
value: (fn) => responseManager.use(fn)
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
get(url, config = {}) {
|
|
30
|
+
return this._createRequest('GET', url, null, config);
|
|
31
|
+
}
|
|
32
|
+
post(url, data = null, config = {}) {
|
|
33
|
+
return this._createRequest('POST', url, data, config);
|
|
34
|
+
}
|
|
35
|
+
put(url, data = null, config = {}) {
|
|
36
|
+
return this._createRequest('PUT', url, data, config);
|
|
37
|
+
}
|
|
38
|
+
delete(url, config = {}) {
|
|
39
|
+
return this._createRequest('DELETE', url, null, config);
|
|
40
|
+
}
|
|
41
|
+
_createRequest(method, url, data = null, config = {}) {
|
|
42
|
+
const request = {
|
|
43
|
+
method,
|
|
44
|
+
url,
|
|
45
|
+
data,
|
|
46
|
+
headers: Object.assign({}, (config.headers || {})),
|
|
47
|
+
params: Object.assign({}, (config.params || {})),
|
|
48
|
+
cache: config.cache,
|
|
49
|
+
timeout: config.timeout,
|
|
50
|
+
abortController: new AbortController()
|
|
51
|
+
};
|
|
52
|
+
return new FluidFetchRequest(this, request);
|
|
53
|
+
}
|
|
54
|
+
_getCacheKey(request) {
|
|
55
|
+
return `${request.method}:${request.url}:${JSON.stringify(request.params)}`;
|
|
56
|
+
}
|
|
57
|
+
_buildUrl(url, params) {
|
|
58
|
+
if (!params || Object.keys(params).length === 0)
|
|
59
|
+
return url;
|
|
60
|
+
const query = Object.entries(params)
|
|
61
|
+
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
|
|
62
|
+
.join('&');
|
|
63
|
+
return `${url}?${query}`;
|
|
64
|
+
}
|
|
65
|
+
getCachedResponse(cacheKey) {
|
|
66
|
+
const entry = this.cache.get(cacheKey);
|
|
67
|
+
if (entry && entry.expires > Date.now()) {
|
|
68
|
+
return entry.response;
|
|
69
|
+
}
|
|
70
|
+
if (entry) {
|
|
71
|
+
this.cache.delete(cacheKey);
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
getPendingRequest(cacheKey) {
|
|
76
|
+
return this.pendingRequests.get(cacheKey);
|
|
77
|
+
}
|
|
78
|
+
registerPendingRequest(cacheKey, controller) {
|
|
79
|
+
this.pendingRequests.set(cacheKey, controller);
|
|
80
|
+
}
|
|
81
|
+
removePendingRequest(cacheKey) {
|
|
82
|
+
this.pendingRequests.delete(cacheKey);
|
|
83
|
+
}
|
|
84
|
+
cacheResponse(cacheKey, response, ttl) {
|
|
85
|
+
const duration = typeof ttl === 'number' ? ttl : 3600000;
|
|
86
|
+
const entry = {
|
|
87
|
+
response: response,
|
|
88
|
+
expires: Date.now() + duration
|
|
89
|
+
};
|
|
90
|
+
this.cache.set(cacheKey, entry);
|
|
91
|
+
}
|
|
92
|
+
clearRequestMiddlewares() {
|
|
93
|
+
this.middlewares.request.clear();
|
|
94
|
+
}
|
|
95
|
+
clearResponseMiddlewares() {
|
|
96
|
+
this.middlewares.response.clear();
|
|
97
|
+
}
|
|
98
|
+
clearRequestInterceptors() {
|
|
99
|
+
this.clearRequestMiddlewares();
|
|
100
|
+
}
|
|
101
|
+
clearResponseInterceptors() {
|
|
102
|
+
this.clearResponseMiddlewares();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
class FluidFetchRequest {
|
|
106
|
+
constructor(fluidFetch, request) {
|
|
107
|
+
this.fluidFetch = fluidFetch;
|
|
108
|
+
this.request = request;
|
|
109
|
+
this.promise = null;
|
|
110
|
+
}
|
|
111
|
+
headers(headers) {
|
|
112
|
+
Object.assign(this.request.headers, headers);
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
params(params) {
|
|
116
|
+
Object.assign(this.request.params, params);
|
|
117
|
+
return this;
|
|
118
|
+
}
|
|
119
|
+
body(data) {
|
|
120
|
+
this.request.data = data;
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
cache(ttl) {
|
|
124
|
+
this.request.cache = typeof ttl === 'boolean' ?
|
|
125
|
+
3600000 :
|
|
126
|
+
ttl;
|
|
127
|
+
return this;
|
|
128
|
+
}
|
|
129
|
+
timeout(ms) {
|
|
130
|
+
this.request.timeout = ms;
|
|
131
|
+
return this;
|
|
132
|
+
}
|
|
133
|
+
cancel() {
|
|
134
|
+
this.request.abortController.abort();
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
then(onFulfilled, onRejected) {
|
|
138
|
+
if (!this.promise) {
|
|
139
|
+
this.promise = this._executeRequest();
|
|
140
|
+
}
|
|
141
|
+
return this.promise.then(onFulfilled, onRejected);
|
|
142
|
+
}
|
|
143
|
+
catch(onRejected) {
|
|
144
|
+
if (!this.promise) {
|
|
145
|
+
this.promise = this._executeRequest();
|
|
146
|
+
}
|
|
147
|
+
return this.promise.catch(onRejected);
|
|
148
|
+
}
|
|
149
|
+
async _executeRequest() {
|
|
150
|
+
let request = this.request;
|
|
151
|
+
request = await this.fluidFetch.middlewares.request.runMiddlewares(request);
|
|
152
|
+
const cacheKey = this.fluidFetch._getCacheKey(request);
|
|
153
|
+
if (request.cache) {
|
|
154
|
+
const cachedResponse = this.fluidFetch.getCachedResponse(cacheKey);
|
|
155
|
+
if (cachedResponse) {
|
|
156
|
+
return cachedResponse.clone();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const pendingController = this.fluidFetch.getPendingRequest(cacheKey);
|
|
160
|
+
if (pendingController) {
|
|
161
|
+
pendingController.abort();
|
|
162
|
+
}
|
|
163
|
+
this.fluidFetch.registerPendingRequest(cacheKey, request.abortController);
|
|
164
|
+
let timeoutId;
|
|
165
|
+
if (request.timeout && request.timeout > 0) {
|
|
166
|
+
timeoutId = setTimeout(() => {
|
|
167
|
+
const timeoutError = new TimeoutError(`Request timed out after ${request.timeout}ms`);
|
|
168
|
+
request.abortController.abort(timeoutError);
|
|
169
|
+
}, request.timeout);
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
const response = await fetch(this.fluidFetch._buildUrl(request.url, request.params), {
|
|
173
|
+
method: request.method,
|
|
174
|
+
headers: request.headers,
|
|
175
|
+
body: request.data ? JSON.stringify(request.data) : undefined,
|
|
176
|
+
signal: request.abortController.signal
|
|
177
|
+
});
|
|
178
|
+
let processedResponse = response;
|
|
179
|
+
processedResponse = await this.fluidFetch.middlewares.response.runMiddlewares(processedResponse);
|
|
180
|
+
if (request.cache) {
|
|
181
|
+
this.fluidFetch.cacheResponse(cacheKey, processedResponse.clone(), typeof request.cache === 'boolean' ? undefined : request.cache);
|
|
182
|
+
}
|
|
183
|
+
return processedResponse;
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
if (timeoutId) {
|
|
187
|
+
clearTimeout(timeoutId);
|
|
188
|
+
}
|
|
189
|
+
this.fluidFetch.removePendingRequest(cacheKey);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
export { TimeoutError, MiddlewareManager };
|
|
194
|
+
export default FluidFetch;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import Schema from "validno";
|
|
2
|
+
import Kodzero from "./Kodzero.js";
|
|
3
|
+
console.log('front-sdk started');
|
|
4
|
+
const kodzero = new Kodzero({
|
|
5
|
+
host: 'http://localhost:6969'
|
|
6
|
+
});
|
|
7
|
+
const carSchema = new Schema({
|
|
8
|
+
_id: { type: String },
|
|
9
|
+
mark: { type: String },
|
|
10
|
+
model: { type: String },
|
|
11
|
+
year: { type: Number }
|
|
12
|
+
});
|
|
13
|
+
const Car = kodzero.createModel({
|
|
14
|
+
collection: 'cars',
|
|
15
|
+
schema: carSchema
|
|
16
|
+
});
|
|
17
|
+
Car.registerMethod('greet', function () {
|
|
18
|
+
return `Hello, I am a ${this.modelData.mark} ${this.modelData.model} from ${this.modelData.year}`;
|
|
19
|
+
});
|
|
20
|
+
const carRecord = await Car.get('68aec23b4732a44b3f559250');
|
|
21
|
+
const data = carRecord.data();
|
|
22
|
+
console.log(carRecord.greet());
|
|
23
|
+
const signRes = await kodzero.auth.email.signin({ email: 'leshatour@gmail.com', password: 'qwerty123' });
|
|
24
|
+
const verifyRes = await kodzero.auth.email.verify();
|
|
25
|
+
console.log('verify1', verifyRes);
|
|
26
|
+
const refreshRes = await kodzero.auth.email.refresh();
|
|
27
|
+
console.log('refresh', refreshRes);
|
|
28
|
+
const logoutRes = await kodzero.auth.email.signout();
|
|
29
|
+
console.log('logout', logoutRes);
|
|
30
|
+
const verifyRes2 = await kodzero.auth.email.verify();
|
|
31
|
+
console.log('verify2', verifyRes2);
|
|
32
|
+
const signupRes = await kodzero.auth.email.signup({
|
|
33
|
+
"name": "leshatour2",
|
|
34
|
+
"email": `leshatour${Math.random()}@gmail.com`,
|
|
35
|
+
"password": "qwerty123"
|
|
36
|
+
});
|
|
37
|
+
console.log('signup', signupRes);
|
|
38
|
+
const URec = kodzero.createModel({
|
|
39
|
+
collection: 'scope-user',
|
|
40
|
+
schema: new Schema({
|
|
41
|
+
text: '134'
|
|
42
|
+
})
|
|
43
|
+
});
|
|
44
|
+
console.log(1);
|
|
45
|
+
const urec = new URec({ _id: '', text: 'User Scope Example' });
|
|
46
|
+
console.log(2);
|
|
47
|
+
await urec.save();
|
|
48
|
+
console.log(3);
|
|
49
|
+
console.log(urec.data()._id);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Schema from "validno";
|
|
2
|
+
import FluidFetch from "fluid-fetch";
|
|
3
|
+
export interface ModelOptions {
|
|
4
|
+
host: string;
|
|
5
|
+
collection: string;
|
|
6
|
+
schema?: typeof Schema;
|
|
7
|
+
}
|
|
8
|
+
declare class BaseModel<T extends {
|
|
9
|
+
_id?: string;
|
|
10
|
+
}> {
|
|
11
|
+
host: string;
|
|
12
|
+
collection: string;
|
|
13
|
+
modelData: T;
|
|
14
|
+
schema?: typeof Schema;
|
|
15
|
+
api: typeof FluidFetch;
|
|
16
|
+
id: string | null;
|
|
17
|
+
static url: string;
|
|
18
|
+
static collection: string;
|
|
19
|
+
static api: typeof FluidFetch;
|
|
20
|
+
constructor(options: ModelOptions, api: typeof FluidFetch);
|
|
21
|
+
_setId: (id: string | null) => void;
|
|
22
|
+
_setModelData: (data: T) => void;
|
|
23
|
+
_handleApiError(response: Response): Promise<void>;
|
|
24
|
+
data(): T;
|
|
25
|
+
_dataWithoutId(): Omit<T, "_id"> | {};
|
|
26
|
+
_setNested(key: string, value: any): T;
|
|
27
|
+
set(data: Record<string, any> | string, value?: any): T;
|
|
28
|
+
validate(): {
|
|
29
|
+
ok: boolean;
|
|
30
|
+
errors: string[];
|
|
31
|
+
joinErrors: () => string;
|
|
32
|
+
};
|
|
33
|
+
update(): Promise<T>;
|
|
34
|
+
delete(): Promise<boolean>;
|
|
35
|
+
create(): Promise<T>;
|
|
36
|
+
save(): Promise<T>;
|
|
37
|
+
}
|
|
38
|
+
export default BaseModel;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import constants from "./constants.js";
|
|
13
|
+
import validateApiResponse from "../utils/validateApiResponse.js";
|
|
14
|
+
import BaseModelSchema from "../schemas/baseModel.js";
|
|
15
|
+
import buildURL from "../utils/buildURL_rename.js";
|
|
16
|
+
class BaseModel {
|
|
17
|
+
constructor(options, api) {
|
|
18
|
+
this.modelData = {};
|
|
19
|
+
this._setId = (id) => {
|
|
20
|
+
this.id = id;
|
|
21
|
+
};
|
|
22
|
+
this._setModelData = (data) => {
|
|
23
|
+
this.modelData = data;
|
|
24
|
+
this._setId((data === null || data === void 0 ? void 0 : data._id) || null);
|
|
25
|
+
};
|
|
26
|
+
BaseModelSchema.validateOrThrow(options);
|
|
27
|
+
this.host = options.host;
|
|
28
|
+
this.collection = options.collection;
|
|
29
|
+
this.schema = options.schema;
|
|
30
|
+
this.api = api;
|
|
31
|
+
this.id = null;
|
|
32
|
+
}
|
|
33
|
+
_handleApiError(response) {
|
|
34
|
+
return validateApiResponse(response);
|
|
35
|
+
}
|
|
36
|
+
data() {
|
|
37
|
+
return this.modelData;
|
|
38
|
+
}
|
|
39
|
+
_dataWithoutId() {
|
|
40
|
+
if (typeof this.modelData === 'object' && this.modelData !== null && '_id' in this.modelData) {
|
|
41
|
+
const _a = this.modelData, { _id } = _a, dataWithoutId = __rest(_a, ["_id"]);
|
|
42
|
+
return dataWithoutId;
|
|
43
|
+
}
|
|
44
|
+
return this.modelData;
|
|
45
|
+
}
|
|
46
|
+
_setNested(key, value) {
|
|
47
|
+
const keys = key.split('.');
|
|
48
|
+
let obj = this.modelData;
|
|
49
|
+
while (keys.length > 1) {
|
|
50
|
+
const k = keys.shift();
|
|
51
|
+
if (!(k in obj))
|
|
52
|
+
obj[k] = {};
|
|
53
|
+
obj = obj[k];
|
|
54
|
+
}
|
|
55
|
+
obj[keys[0]] = value;
|
|
56
|
+
return this.modelData;
|
|
57
|
+
}
|
|
58
|
+
set(data, value) {
|
|
59
|
+
if (typeof data === 'string' && value !== undefined) {
|
|
60
|
+
this._setNested(data, value);
|
|
61
|
+
}
|
|
62
|
+
else if (typeof data === 'object') {
|
|
63
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
64
|
+
this._setNested(key, value);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return this.modelData;
|
|
68
|
+
}
|
|
69
|
+
validate() {
|
|
70
|
+
const schema = this.schema;
|
|
71
|
+
if (!schema) {
|
|
72
|
+
throw new Error(constants.NoSchema);
|
|
73
|
+
}
|
|
74
|
+
const keysToValidate = Object.keys(this.schema.definition).filter(k => k !== '_id');
|
|
75
|
+
const validationResult = schema.validate(this._dataWithoutId(), keysToValidate);
|
|
76
|
+
return validationResult;
|
|
77
|
+
}
|
|
78
|
+
async update() {
|
|
79
|
+
if (!this.id) {
|
|
80
|
+
throw new Error(constants.RequiresId);
|
|
81
|
+
}
|
|
82
|
+
const updateUrl = buildURL(this.host, this.collection, this.id);
|
|
83
|
+
const response = await this.api.patch(updateUrl, this._dataWithoutId())
|
|
84
|
+
.headers({ 'Content-Type': 'application/json' });
|
|
85
|
+
await this._handleApiError(response);
|
|
86
|
+
const json = await response.json();
|
|
87
|
+
this._setModelData(json.result);
|
|
88
|
+
return this.modelData;
|
|
89
|
+
}
|
|
90
|
+
async delete() {
|
|
91
|
+
if (!this.id) {
|
|
92
|
+
throw new Error(constants.RequiresId);
|
|
93
|
+
}
|
|
94
|
+
const deleteUrl = buildURL(this.host, this.collection, this.id);
|
|
95
|
+
const response = await this.api.delete(deleteUrl);
|
|
96
|
+
await this._handleApiError(response);
|
|
97
|
+
this._setId(null);
|
|
98
|
+
this.modelData = {};
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
async create() {
|
|
102
|
+
const createUrl = buildURL(this.host, this.collection);
|
|
103
|
+
const response = await this.api.post(createUrl, this._dataWithoutId())
|
|
104
|
+
.headers({ 'Content-Type': 'application/json' });
|
|
105
|
+
await this._handleApiError(response);
|
|
106
|
+
const json = await response.json();
|
|
107
|
+
this._setModelData(json.result);
|
|
108
|
+
return this.modelData;
|
|
109
|
+
}
|
|
110
|
+
async save() {
|
|
111
|
+
if (this.id) {
|
|
112
|
+
return this.update();
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
return this.create();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export default BaseModel;
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
NoSchema: 'No schema defined for validation',
|
|
3
|
+
RequiresId: 'Method requires model id',
|
|
4
|
+
DataTypeNotArray: 'Data must be a non-empty array',
|
|
5
|
+
RequiresIdsArray: 'Method requires array of ids',
|
|
6
|
+
DistinctRequiresFieldsArray: 'Distinct methods requires array of fields'
|
|
7
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import FluidFetch from 'fluid-fetch';
|
|
2
|
+
import BaseModel, { ModelOptions } from './BaseModel.js';
|
|
3
|
+
export interface FindManyOptions {
|
|
4
|
+
page: number;
|
|
5
|
+
perPage: number;
|
|
6
|
+
search?: string;
|
|
7
|
+
sort?: string;
|
|
8
|
+
fields?: string[];
|
|
9
|
+
}
|
|
10
|
+
declare const createModel: <T extends {
|
|
11
|
+
_id?: string;
|
|
12
|
+
}, M = {}>(options: ModelOptions, api: typeof FluidFetch) => {
|
|
13
|
+
new (data: T): BaseModel<T> & M;
|
|
14
|
+
get(id: string): Promise<BaseModel<T> & M>;
|
|
15
|
+
registerMethod<K extends keyof M>(name: K, fn: M[K]): void;
|
|
16
|
+
find(id: string): Promise<T>;
|
|
17
|
+
findMany(options?: FindManyOptions | {}): Promise<T[]>;
|
|
18
|
+
create(data: T): Promise<T>;
|
|
19
|
+
createMany(data: T[]): Promise<T[]>;
|
|
20
|
+
update(id: string, data: Partial<T>): Promise<T>;
|
|
21
|
+
updateMany(updates: Partial<T>[]): Promise<T[]>;
|
|
22
|
+
delete(id: string): Promise<boolean>;
|
|
23
|
+
deleteMany(ids: string[]): Promise<Record<string, boolean>>;
|
|
24
|
+
distinct(fields: string[], filter?: Record<string, any>): Promise<string[]>;
|
|
25
|
+
host: string;
|
|
26
|
+
collection: string;
|
|
27
|
+
};
|
|
28
|
+
export default createModel;
|