@websolutespa/bom-mixer-store 0.3.0 → 0.3.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.
@@ -0,0 +1,191 @@
1
+ import { FetchRequestOptions, httpFetch, IEntity, IEquatable, IQuerable, merge, Pagination, qsSerialize, QueryParams } from '@websolutespa/bom-core';
2
+ import { StoreStrategy, storeStrategy } from '../store/store';
3
+
4
+ const STORE_API_URL = process.env.STORE_URL;
5
+ const STORE_API_BASE = process.env.STORE_API || '/api';
6
+ const STORE_BEARER = process.env.STORE_BEARER;
7
+
8
+ const MOCK_API_URL = process.env.NEXT_PUBLIC_URL;
9
+ const MOCK_API_BASE = process.env.NEXT_PUBLIC_API || '/api';
10
+
11
+ export type ApiRequestOptions = FetchRequestOptions;
12
+
13
+ const defaultStoreOptions: ApiRequestOptions = {
14
+ // mode: 'cors',
15
+ headers: {
16
+ Authorization: `Bearer ${STORE_BEARER}`,
17
+ },
18
+ };
19
+
20
+ function getApiUrl(pathname: string): string {
21
+ let url: string;
22
+ if (storeStrategy === StoreStrategy.Api) {
23
+ url = `${STORE_API_URL}${STORE_API_BASE}${pathname}`;
24
+ } else {
25
+ url = `${MOCK_API_URL}${MOCK_API_BASE}/_mock${pathname}`;
26
+ }
27
+ return url;
28
+ }
29
+
30
+ export async function storeApiFetch(pathname: string, options: ApiRequestOptions = {}): Promise<any> {
31
+ const url = getApiUrl(pathname);
32
+ // console.log('ApiStore.apiFetch', url, options.method);
33
+ const apiOptions = merge({ ...defaultStoreOptions }, options);
34
+ const apiResponse = await httpFetch(url, apiOptions);
35
+ return apiResponse;
36
+ }
37
+
38
+ export async function storeApiGet(url: string, options: ApiRequestOptions = {}): Promise<any> {
39
+ return await storeApiFetch(url, { ...options, method: 'GET' });
40
+ }
41
+
42
+ export async function storeApiPost(url: string, payload: any, options: ApiRequestOptions = {}): Promise<any> {
43
+ return await storeApiFetch(url, { ...options, method: 'POST', body: JSON.stringify(payload) });
44
+ }
45
+
46
+ export async function storeApiPut(url: string, payload: any, options: ApiRequestOptions = {}): Promise<any> {
47
+ return await storeApiFetch(url, { ...options, method: 'PUT', body: JSON.stringify(payload) });
48
+ }
49
+
50
+ export async function storeApiPatch(url: string, payload: any, options: ApiRequestOptions = {}): Promise<any> {
51
+ return await storeApiFetch(url, { ...options, method: 'PATCH', body: JSON.stringify(payload) });
52
+ }
53
+
54
+ export async function storeApiDelete(url: string, options: ApiRequestOptions = {}): Promise<any> {
55
+ return await storeApiFetch(url, { ...options, method: 'DELETE' });
56
+ }
57
+
58
+ export class StoreApiService<T extends IEntity = IEntity> implements IQuerable<T> {
59
+ key: string;
60
+
61
+ constructor(key: string) {
62
+ if (!key) {
63
+ throw new Error('StoreApiService: key is required');
64
+ }
65
+ this.key = key;
66
+ }
67
+
68
+ /*
69
+ async findOne___<B extends T = T>(id: IEquatable, params: QueryParams = {}): Promise<B | undefined> {
70
+ params.pagination = params.pagination || false;
71
+ params.richText = params.richText || false;
72
+ const query = qsSerialize(params);
73
+ const search = query ? `?${query}` : '';
74
+ const url = `/${this.key}${search}`;
75
+ const response = await storeApiGet(url);
76
+ const items: B[] = Array.isArray(response.docs) ? response.docs : response;
77
+ const item = items.length ? items[0] : undefined;
78
+ if (item) {
79
+ return this.decorator_(item, params);
80
+ }
81
+ return;
82
+ }
83
+ */
84
+
85
+ async findOne<B extends T = T>(id: IEquatable, params: QueryParams = {}): Promise<B | undefined> {
86
+ params.richText = String(params.richText) === 'true' ? true : false;
87
+ const query = qsSerialize(params);
88
+ const search = query ? `?${query}` : '';
89
+ const url = `/${this.key}/${encodeURIComponent(id)}${search}`;
90
+ const item: B = await storeApiGet(url);
91
+ if (item) {
92
+ return this.decorator_(item, params);
93
+ }
94
+ return;
95
+ }
96
+
97
+ async findMany<B extends T = T>(params: QueryParams = {}): Promise<B[]> {
98
+ params.richText = String(params.richText) === 'true' ? true : false;
99
+ params.pagination = false;
100
+ const query = qsSerialize(params);
101
+ const search = query ? `?${query}` : '';
102
+ const url = `/${this.key}${search}`;
103
+ const response = await storeApiGet(url);
104
+ const items: B[] = Array.isArray(response.docs) ? response.docs : response;
105
+ // console.log('StoreApiService.findMany', url);
106
+ // console.log('StoreApiService.findMany', url, items);
107
+ // items = this.where_(items, params);
108
+ return items.map(x => this.decorator_(x, params));
109
+ }
110
+
111
+ async findPaged<B extends T = T>(params: QueryParams = {}): Promise<{ docs: B[]; } & Pagination> {
112
+ params.richText = String(params.richText) === 'true' ? true : false;
113
+ params.pagination = true;
114
+ const query = qsSerialize(params);
115
+ const search = query ? `?${query}` : '';
116
+ const url = `/${this.key}${search}`;
117
+ const response = await storeApiGet(url);
118
+ let items: B[] = response.docs;
119
+ items = items.map(x => this.decorator_(x, params));
120
+ return { ...response, docs: items };
121
+ }
122
+
123
+ async create<B extends T = T>(payload: Omit<B, 'id'>): Promise<B> {
124
+ const url = `/${this.key}`;
125
+ // console.log('StoreApiService', this.key, 'create', url);
126
+ const item = await storeApiPost(url, payload);
127
+ return this.decorator_(item);
128
+ }
129
+
130
+ async update<B extends T = T>(payload: Partial<B>): Promise<B> {
131
+ const url = `/${this.key}`;
132
+ // console.log('StoreApiService', this.key, 'update', url);
133
+ const item = await storeApiPut(url, payload);
134
+ return this.decorator_(item);
135
+ }
136
+
137
+ async delete<B extends T = T>(id: IEquatable): Promise<B | undefined> {
138
+ // const params = toFindParams(id);
139
+ const params = {
140
+ where: {
141
+ id: {
142
+ equals: id,
143
+ }
144
+ },
145
+ };
146
+ const query = qsSerialize(params);
147
+ const search = query ? `?${query}` : '';
148
+ // const search = this.search_(params);
149
+ const url = `/${this.key}${search}`;
150
+ // const url = `/${this.key}/${encodeURIComponent(id.toString())}`;
151
+ // console.log('StoreApiService', this.key, 'delete', url);
152
+ const item = await storeApiDelete(url);
153
+ return this.decorator_(item);
154
+ }
155
+
156
+ /*
157
+ protected where_(items: any[], params: FindParams): any[] {
158
+ const where = params.where;
159
+ if (where) {
160
+ const keys = Object.keys(where);
161
+ items = items.filter(x => {
162
+ return keys.reduce<boolean>((p, c) => {
163
+ return p && (x[c] === where[c]);
164
+ }, true);
165
+ });
166
+ }
167
+ return items;
168
+ }
169
+ */
170
+
171
+ protected decorator_<B extends T = T>(item: B, params: QueryParams = {}): B {
172
+ return item;
173
+ }
174
+
175
+ /*
176
+ protected search_(params: QueryParams): string {
177
+ const search: { [key: string]: string; } = {};
178
+ Object.entries(params).forEach(([key, value]) => {
179
+ if (typeof value !== 'object') {
180
+ search[key] = value.toString();
181
+ } else {
182
+ switch (key) {
183
+ case 'where':
184
+ search[key] = JSON.stringify(value);
185
+ }
186
+ }
187
+ });
188
+ return Object.keys(search).length ? '?' + new URLSearchParams(search).toString() : '';
189
+ }
190
+ */
191
+ }
@@ -0,0 +1,66 @@
1
+ import { IEntity, IQuerable, IStore, isDevelopment } from '@websolutespa/bom-core';
2
+ import { MockService } from '../mock/mock.service';
3
+ import { getMockStoreServer } from '../mock/mock.store';
4
+ import { MOCK_COLLECTIONS } from '../store/store.service';
5
+ import { StoreApiService, storeApiGet } from './storeApi.service';
6
+
7
+ export async function getApiStore<T extends IStore>(collections: string[]): Promise<T> {
8
+ // console.count('ApiStore.getApiStore');
9
+ // console.log('ApiStore.getApiStore', collections);
10
+ // console.log('NODE_ENV', process.env.NODE_ENV, 'NEXT_RUNTIME', process.env.NEXT_RUNTIME, 'NEXT_PHASE', process.env.NEXT_PHASE);
11
+ if (process.env.NEXT_PHASE === 'phase-production-build') {
12
+ return await getApiBuildStore();
13
+ } else {
14
+ return await getApiRuntimeStore(collections);
15
+ }
16
+ }
17
+
18
+ let RUNTIME_STORE_: IStore;
19
+ export async function getApiRuntimeStore<T extends IStore>(collections: string[]): Promise<T> {
20
+ if (RUNTIME_STORE_) {
21
+ return RUNTIME_STORE_ as T;
22
+ }
23
+ let mockStore: IStore = {};
24
+ if (MOCK_COLLECTIONS.length > 0) {
25
+ mockStore = await getMockStoreServer<T>();
26
+ }
27
+ const store: { [key: string]: IQuerable<IEntity> } = {};
28
+ collections.sort();
29
+ collections.forEach(key => {
30
+ if (MOCK_COLLECTIONS.includes(key)) {
31
+ store[key] = mockStore[key];
32
+ } else {
33
+ store[key] = new StoreApiService(key);
34
+ }
35
+ });
36
+ // console.count('ApiStore.getApiRuntimeStore');
37
+ // console.log('StoreApi.getApiRuntimeStore', Object.keys(store));
38
+ if (!isDevelopment) {
39
+ RUNTIME_STORE_ = store;
40
+ }
41
+ return store as T;
42
+ }
43
+
44
+ let BUILD_STORE_: IStore;
45
+ export async function getApiBuildStore<T extends IStore>(): Promise<T> {
46
+ if (BUILD_STORE_) {
47
+ return BUILD_STORE_ as T;
48
+ }
49
+ const store: IStore = {};
50
+ const url = '/store?pagination=true&richText=false';
51
+ const json = await storeApiGet(url);
52
+ // const json: { [key: string]: { items: any[] } } = {};
53
+ if (json != null) {
54
+ const collections = Object.keys(json);
55
+ collections.sort();
56
+ collections.forEach(key => {
57
+ if (json[key]) {
58
+ store[key] = new MockService(json[key], store);
59
+ }
60
+ });
61
+ }
62
+ // console.count('ApiStore.getApiBuildStore');
63
+ // console.log('StoreApi.getApiBuildStore', Object.keys(store));
64
+ BUILD_STORE_ = store;
65
+ return store as T;
66
+ }