@sneat/api 0.1.3 → 0.1.6
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/esm2022/index.js +6 -0
- package/esm2022/index.js.map +1 -0
- package/esm2022/lib/sneat-api-service-factory.js +60 -0
- package/esm2022/lib/sneat-api-service-factory.js.map +1 -0
- package/esm2022/lib/sneat-api-service.interface.js +2 -0
- package/esm2022/lib/sneat-api-service.interface.js.map +1 -0
- package/esm2022/lib/sneat-api-service.js +107 -0
- package/esm2022/lib/sneat-api-service.js.map +1 -0
- package/esm2022/lib/sneat-api.module.js +18 -0
- package/esm2022/lib/sneat-api.module.js.map +1 -0
- package/esm2022/lib/sneat-firestore.service.js +75 -0
- package/esm2022/lib/sneat-firestore.service.js.map +1 -0
- package/esm2022/sneat-api.js +5 -0
- package/esm2022/sneat-api.js.map +1 -0
- package/lib/sneat-api-service-factory.d.ts +9 -0
- package/lib/sneat-api-service.d.ts +29 -0
- package/lib/sneat-api-service.interface.d.ts +20 -0
- package/lib/sneat-api.module.d.ts +7 -0
- package/lib/sneat-firestore.service.d.ts +30 -0
- package/package.json +14 -2
- package/sneat-api.d.ts +5 -0
- package/tsconfig.lib.prod.tsbuildinfo +1 -0
- package/eslint.config.js +0 -7
- package/ng-package.json +0 -7
- package/project.json +0 -38
- package/src/lib/sneat-api-service-factory.spec.ts +0 -132
- package/src/lib/sneat-api-service-factory.ts +0 -59
- package/src/lib/sneat-api-service.interface.ts +0 -50
- package/src/lib/sneat-api-service.spec.ts +0 -298
- package/src/lib/sneat-api-service.ts +0 -138
- package/src/lib/sneat-api.module.spec.ts +0 -18
- package/src/lib/sneat-api.module.ts +0 -10
- package/src/lib/sneat-firestore.service.spec.ts +0 -465
- package/src/lib/sneat-firestore.service.ts +0 -157
- package/src/test-setup.ts +0 -3
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -19
- package/tsconfig.lib.prod.json +0 -7
- package/tsconfig.spec.json +0 -31
- package/vite.config.mts +0 -10
- /package/{src/index.ts → index.d.ts} +0 -0
package/esm2022/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './lib/sneat-api.module';
|
|
2
|
+
export * from './lib/sneat-api-service.interface';
|
|
3
|
+
export * from './lib/sneat-api-service-factory';
|
|
4
|
+
export * from './lib/sneat-api-service';
|
|
5
|
+
export * from './lib/sneat-firestore.service';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/api/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,mCAAmC,CAAC;AAClD,cAAc,iCAAiC,CAAC;AAChD,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC","sourcesContent":["export * from './lib/sneat-api.module';\nexport * from './lib/sneat-api-service.interface';\nexport * from './lib/sneat-api-service-factory';\nexport * from './lib/sneat-api-service';\nexport * from './lib/sneat-firestore.service';\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Injectable, inject } from '@angular/core';
|
|
2
|
+
import { parseStoreRef } from '@sneat/core';
|
|
3
|
+
import { SneatApiService } from './sneat-api-service';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export const getStoreUrl = (storeId) => {
|
|
6
|
+
if (storeId === 'firestore') {
|
|
7
|
+
const v = 'http://localhost:4300/v0'; //environment.agents.firestoreStoreAgent;
|
|
8
|
+
return v.endsWith('/') ? v.substring(0, v.length - 1) : v;
|
|
9
|
+
}
|
|
10
|
+
if (!storeId || storeId.match(/https?:\/\//)) {
|
|
11
|
+
return storeId;
|
|
12
|
+
}
|
|
13
|
+
if (storeId.startsWith('http-')) {
|
|
14
|
+
return storeId.replace('http-', 'http' + '://');
|
|
15
|
+
}
|
|
16
|
+
if (storeId.startsWith('https-')) {
|
|
17
|
+
return storeId.replace('https-', 'https://');
|
|
18
|
+
}
|
|
19
|
+
const a = storeId.split(':');
|
|
20
|
+
storeId = `//${a[0]}:${a[1]}`;
|
|
21
|
+
if (a[2]) {
|
|
22
|
+
storeId += ':' + a[2];
|
|
23
|
+
}
|
|
24
|
+
return storeId;
|
|
25
|
+
};
|
|
26
|
+
export class SneatApiServiceFactory {
|
|
27
|
+
constructor() {
|
|
28
|
+
this.services = {};
|
|
29
|
+
}
|
|
30
|
+
getSneatApiService(storeId) {
|
|
31
|
+
if (!storeId) {
|
|
32
|
+
throw new Error('storeRef is a required parameter, got empty: ' + typeof storeId);
|
|
33
|
+
}
|
|
34
|
+
const storeRef = parseStoreRef(storeId);
|
|
35
|
+
if (!storeRef.type) {
|
|
36
|
+
throw new Error('storeRef.type is a required parameter, got empty: ' +
|
|
37
|
+
typeof storeRef.type);
|
|
38
|
+
}
|
|
39
|
+
const id = `${storeRef.type}:${storeRef.url}`;
|
|
40
|
+
let service = this.services[id];
|
|
41
|
+
if (service) {
|
|
42
|
+
return service;
|
|
43
|
+
}
|
|
44
|
+
// const baseUrl = getStoreUrl(storeRefToId(storeRef));
|
|
45
|
+
switch (storeRef.type) {
|
|
46
|
+
case 'firestore':
|
|
47
|
+
this.services[id] = service = inject(SneatApiService);
|
|
48
|
+
return service;
|
|
49
|
+
default:
|
|
50
|
+
throw new Error('unknown store type: ' + storeRef.type);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SneatApiServiceFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
54
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SneatApiServiceFactory, providedIn: 'root' }); }
|
|
55
|
+
}
|
|
56
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SneatApiServiceFactory, decorators: [{
|
|
57
|
+
type: Injectable,
|
|
58
|
+
args: [{ providedIn: 'root' }]
|
|
59
|
+
}] });
|
|
60
|
+
//# sourceMappingURL=sneat-api-service-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sneat-api-service-factory.js","sourceRoot":"","sources":["../../../../../libs/api/src/lib/sneat-api-service-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;;AAEtD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAe,EAAU,EAAE;IACrD,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,0BAA0B,CAAC,CAAC,yCAAyC;QAC/E,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;QAC7C,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACT,OAAO,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAGF,MAAM,OAAO,sBAAsB;IADnC;QAEU,aAAQ,GAAqC,EAAE,CAAC;KA6BzD;IA3BQ,kBAAkB,CAAC,OAAe;QACvC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,+CAA+C,GAAG,OAAO,OAAO,CACjE,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,oDAAoD;gBAClD,OAAO,QAAQ,CAAC,IAAI,CACvB,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,GAAG,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC;QAC9C,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,uDAAuD;QACvD,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;YACtB,KAAK,WAAW;gBACd,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,OAAO,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;gBACtD,OAAO,OAAO,CAAC;YACjB;gBACE,MAAM,IAAI,KAAK,CAAC,sBAAsB,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;8GA7BU,sBAAsB;kHAAtB,sBAAsB,cADT,MAAM;;2FACnB,sBAAsB;kBADlC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE","sourcesContent":["import { Injectable, inject } from '@angular/core';\nimport { ISneatApiService } from './sneat-api-service.interface';\nimport { parseStoreRef } from '@sneat/core';\nimport { SneatApiService } from './sneat-api-service';\n\nexport const getStoreUrl = (storeId: string): string => {\n if (storeId === 'firestore') {\n const v = 'http://localhost:4300/v0'; //environment.agents.firestoreStoreAgent;\n return v.endsWith('/') ? v.substring(0, v.length - 1) : v;\n }\n if (!storeId || storeId.match(/https?:\\/\\//)) {\n return storeId;\n }\n if (storeId.startsWith('http-')) {\n return storeId.replace('http-', 'http' + '://');\n }\n if (storeId.startsWith('https-')) {\n return storeId.replace('https-', 'https://');\n }\n const a = storeId.split(':');\n storeId = `//${a[0]}:${a[1]}`;\n if (a[2]) {\n storeId += ':' + a[2];\n }\n return storeId;\n};\n\n@Injectable({ providedIn: 'root' })\nexport class SneatApiServiceFactory {\n private services: Record<string, ISneatApiService> = {};\n\n public getSneatApiService(storeId: string): ISneatApiService {\n if (!storeId) {\n throw new Error(\n 'storeRef is a required parameter, got empty: ' + typeof storeId,\n );\n }\n const storeRef = parseStoreRef(storeId);\n if (!storeRef.type) {\n throw new Error(\n 'storeRef.type is a required parameter, got empty: ' +\n typeof storeRef.type,\n );\n }\n const id = `${storeRef.type}:${storeRef.url}`;\n let service = this.services[id];\n if (service) {\n return service;\n }\n // const baseUrl = getStoreUrl(storeRefToId(storeRef));\n switch (storeRef.type) {\n case 'firestore':\n this.services[id] = service = inject(SneatApiService);\n return service;\n default:\n throw new Error('unknown store type: ' + storeRef.type);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sneat-api-service.interface.js","sourceRoot":"","sources":["../../../../../libs/api/src/lib/sneat-api-service.interface.ts"],"names":[],"mappings":"","sourcesContent":["import { Observable } from 'rxjs';\nimport { HttpHeaders, HttpParams } from '@angular/common/http';\n\nexport interface IHttpRequestOptions {\n headers?: HttpHeaders | Record<string, string | string[]>;\n observe?: 'body';\n params?: HttpParams | Record<string, string | string[]>;\n reportProgress?: boolean;\n responseType?: 'json';\n withCredentials?: boolean;\n}\n\n// const SneatApiService = new InjectionToken('ISneatApiService');\n\nexport interface ISneatApiResponse<T> {\n // TODO: Either use or delete\n data: T;\n}\n\nexport interface ISneatApiService {\n post<I, O>(\n endpoint: string,\n body: I,\n options?: IHttpRequestOptions,\n ): Observable<O>;\n\n put<I, O>(\n endpoint: string,\n body: I,\n options?: IHttpRequestOptions,\n ): Observable<O>;\n\n get<T>(\n endpoint: string,\n params?: HttpParams,\n options?: IHttpRequestOptions,\n ): Observable<T>;\n\n getAsAnonymous<T>(\n endpoint: string,\n params?: HttpParams,\n options?: IHttpRequestOptions,\n ): Observable<T>;\n\n delete<T>(\n endpoint: string,\n params?: HttpParams,\n body?: unknown,\n ): Observable<T>;\n}\n"]}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
|
2
|
+
import { Inject, Injectable, InjectionToken, Optional, } from '@angular/core';
|
|
3
|
+
import { Auth, onIdTokenChanged } from '@angular/fire/auth';
|
|
4
|
+
import { Subject, throwError } from 'rxjs';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
import * as i1 from "@angular/common/http";
|
|
7
|
+
import * as i2 from "@angular/fire/auth";
|
|
8
|
+
const userIsNotAuthenticatedNoFirebaseToken = 'User is not authenticated yet - no Firebase ID token';
|
|
9
|
+
export const SneatApiAuthTokenProvider = new InjectionToken('SneatApiAuthTokenProvider');
|
|
10
|
+
export const SneatApiBaseUrl = new InjectionToken('SneatApiBaseUrl');
|
|
11
|
+
export const DefaultSneatAppApiBaseUrl = 'https://api.sneat.ws/v0/';
|
|
12
|
+
export class SneatApiService {
|
|
13
|
+
constructor(httpClient, baseUrl, afAuth) {
|
|
14
|
+
this.httpClient = httpClient;
|
|
15
|
+
this.afAuth = afAuth;
|
|
16
|
+
this.destroyed = new Subject();
|
|
17
|
+
// TODO: It's made public because we use it in Login page, might be a bad idea consider making private and rely on afAuth.idToken event
|
|
18
|
+
this.setApiAuthToken = (token) => {
|
|
19
|
+
// console.log('setApiAuthToken()', token);
|
|
20
|
+
this.authToken = token;
|
|
21
|
+
};
|
|
22
|
+
this.baseUrl = baseUrl ?? DefaultSneatAppApiBaseUrl;
|
|
23
|
+
// console.log('SneatApiService.constructor()', this.baseUrl);
|
|
24
|
+
onIdTokenChanged(this.afAuth, {
|
|
25
|
+
next: (user) => {
|
|
26
|
+
user
|
|
27
|
+
?.getIdToken()
|
|
28
|
+
.then(this.setApiAuthToken)
|
|
29
|
+
.catch((err) => console.error('getIdToken() error:', err));
|
|
30
|
+
},
|
|
31
|
+
error: (error) => {
|
|
32
|
+
console.error('onIdTokenChanged() error:', error);
|
|
33
|
+
},
|
|
34
|
+
complete: () => void 0,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
ngOnDestroy() {
|
|
38
|
+
this.destroyed.next();
|
|
39
|
+
this.destroyed.complete();
|
|
40
|
+
}
|
|
41
|
+
post(endpoint, body) {
|
|
42
|
+
const url = this.baseUrl + endpoint;
|
|
43
|
+
// console.log('post()', endpoint, url, body);
|
|
44
|
+
return (this.errorIfNotAuthenticated() ||
|
|
45
|
+
this.httpClient.post(url, body, {
|
|
46
|
+
headers: this.headers(),
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
put(endpoint, body) {
|
|
50
|
+
return (this.errorIfNotAuthenticated() ||
|
|
51
|
+
this.httpClient.put(this.baseUrl + endpoint, body, {
|
|
52
|
+
headers: this.headers(),
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
get(endpoint, params) {
|
|
56
|
+
return (this.errorIfNotAuthenticated() ||
|
|
57
|
+
this.httpClient.get(this.baseUrl + endpoint, {
|
|
58
|
+
headers: this.headers(),
|
|
59
|
+
params,
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
getAsAnonymous(endpoint, params) {
|
|
63
|
+
return this.httpClient.get(this.baseUrl + endpoint, {
|
|
64
|
+
params,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
postAsAnonymous(endpoint, body) {
|
|
68
|
+
const url = this.baseUrl + endpoint;
|
|
69
|
+
// alert('postAsAnonymous(), url=' + url);
|
|
70
|
+
return this.httpClient.post(url, body);
|
|
71
|
+
}
|
|
72
|
+
delete(endpoint, params, body) {
|
|
73
|
+
// console.log('delete()', endpoint, params);
|
|
74
|
+
const url = this.baseUrl + endpoint;
|
|
75
|
+
return (this.errorIfNotAuthenticated() ||
|
|
76
|
+
this.httpClient.delete(url, {
|
|
77
|
+
params,
|
|
78
|
+
headers: this.headers(),
|
|
79
|
+
body,
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
errorIfNotAuthenticated() {
|
|
83
|
+
const result = (!this.authToken &&
|
|
84
|
+
throwError(() => userIsNotAuthenticatedNoFirebaseToken)) ||
|
|
85
|
+
undefined;
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
headers() {
|
|
89
|
+
let headers = new HttpHeaders();
|
|
90
|
+
if (this.authToken) {
|
|
91
|
+
headers = headers.append('Authorization', 'Bearer ' + this.authToken);
|
|
92
|
+
}
|
|
93
|
+
return headers;
|
|
94
|
+
}
|
|
95
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SneatApiService, deps: [{ token: i1.HttpClient }, { token: SneatApiBaseUrl, optional: true }, { token: i2.Auth }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
96
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SneatApiService, providedIn: 'root' }); }
|
|
97
|
+
}
|
|
98
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SneatApiService, decorators: [{
|
|
99
|
+
type: Injectable,
|
|
100
|
+
args: [{ providedIn: 'root' }]
|
|
101
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: undefined, decorators: [{
|
|
102
|
+
type: Inject,
|
|
103
|
+
args: [SneatApiBaseUrl]
|
|
104
|
+
}, {
|
|
105
|
+
type: Optional
|
|
106
|
+
}] }, { type: i2.Auth }] });
|
|
107
|
+
//# sourceMappingURL=sneat-api-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sneat-api-service.js","sourceRoot":"","sources":["../../../../../libs/api/src/lib/sneat-api-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';\nimport {\n Inject,\n Injectable,\n InjectionToken,\n OnDestroy,\n Optional,\n} from '@angular/core';\nimport { Auth, onIdTokenChanged } from '@angular/fire/auth';\nimport { Observable, Subject, throwError } from 'rxjs';\nimport { ISneatApiService } from './sneat-api-service.interface';\n\nconst userIsNotAuthenticatedNoFirebaseToken =\n 'User is not authenticated yet - no Firebase ID token';\n\nexport const SneatApiAuthTokenProvider = new InjectionToken(\n 'SneatApiAuthTokenProvider',\n);\nexport const SneatApiBaseUrl = new InjectionToken('SneatApiBaseUrl');\nexport const DefaultSneatAppApiBaseUrl = 'https://api.sneat.ws/v0/';\n\n@Injectable({ providedIn: 'root' }) // Should it be in root? Probably it is OK.\nexport class SneatApiService implements ISneatApiService, OnDestroy {\n private readonly baseUrl: string;\n\n private readonly destroyed = new Subject<void>();\n private authToken?: string;\n\n constructor(\n private readonly httpClient: HttpClient,\n @Inject(SneatApiBaseUrl) @Optional() baseUrl: string | null,\n private readonly afAuth: Auth,\n ) {\n this.baseUrl = baseUrl ?? DefaultSneatAppApiBaseUrl;\n // console.log('SneatApiService.constructor()', this.baseUrl);\n onIdTokenChanged(this.afAuth, {\n next: (user) => {\n user\n ?.getIdToken()\n .then(this.setApiAuthToken)\n .catch((err) => console.error('getIdToken() error:', err));\n },\n error: (error) => {\n console.error('onIdTokenChanged() error:', error);\n },\n complete: () => void 0,\n });\n }\n\n ngOnDestroy() {\n this.destroyed.next();\n this.destroyed.complete();\n }\n\n // TODO: It's made public because we use it in Login page, might be a bad idea consider making private and rely on afAuth.idToken event\n setApiAuthToken = (token?: string) => {\n // console.log('setApiAuthToken()', token);\n this.authToken = token;\n };\n\n public post<T>(endpoint: string, body: unknown): Observable<T> {\n const url = this.baseUrl + endpoint;\n // console.log('post()', endpoint, url, body);\n return (\n this.errorIfNotAuthenticated() ||\n this.httpClient.post<T>(url, body, {\n headers: this.headers(),\n })\n );\n }\n\n public put<T>(endpoint: string, body: unknown): Observable<T> {\n return (\n this.errorIfNotAuthenticated() ||\n this.httpClient.put<T>(this.baseUrl + endpoint, body, {\n headers: this.headers(),\n })\n );\n }\n\n public get<T>(endpoint: string, params?: HttpParams): Observable<T> {\n return (\n this.errorIfNotAuthenticated() ||\n this.httpClient.get<T>(this.baseUrl + endpoint, {\n headers: this.headers(),\n params,\n })\n );\n }\n\n public getAsAnonymous<T>(\n endpoint: string,\n params?: HttpParams,\n ): Observable<T> {\n return this.httpClient.get<T>(this.baseUrl + endpoint, {\n params,\n });\n }\n\n public postAsAnonymous<T>(endpoint: string, body: unknown): Observable<T> {\n const url = this.baseUrl + endpoint;\n // alert('postAsAnonymous(), url=' + url);\n return this.httpClient.post<T>(url, body);\n }\n\n public delete<T>(\n endpoint: string,\n params?: HttpParams,\n body?: unknown,\n ): Observable<T> {\n // console.log('delete()', endpoint, params);\n const url = this.baseUrl + endpoint;\n return (\n this.errorIfNotAuthenticated() ||\n this.httpClient.delete<T>(url, {\n params,\n headers: this.headers(),\n body,\n })\n );\n }\n\n private errorIfNotAuthenticated(): Observable<never> | undefined {\n const result: Observable<never> | undefined =\n (!this.authToken &&\n throwError(() => userIsNotAuthenticatedNoFirebaseToken)) ||\n undefined;\n return result;\n }\n\n private headers(): HttpHeaders {\n let headers = new HttpHeaders();\n if (this.authToken) {\n headers = headers.append('Authorization', 'Bearer ' + this.authToken);\n }\n return headers;\n }\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { HttpClientModule } from '@angular/common/http';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export class SneatApiModule {
|
|
5
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SneatApiModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
6
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: SneatApiModule, imports: [HttpClientModule] }); }
|
|
7
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SneatApiModule, imports: [HttpClientModule] }); }
|
|
8
|
+
}
|
|
9
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: SneatApiModule, decorators: [{
|
|
10
|
+
type: NgModule,
|
|
11
|
+
args: [{
|
|
12
|
+
imports: [HttpClientModule],
|
|
13
|
+
providers: [
|
|
14
|
+
// SneatTeamApiService,
|
|
15
|
+
],
|
|
16
|
+
}]
|
|
17
|
+
}] });
|
|
18
|
+
//# sourceMappingURL=sneat-api.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sneat-api.module.js","sourceRoot":"","sources":["../../../../../libs/api/src/lib/sneat-api.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;;AAQxD,MAAM,OAAO,cAAc;8GAAd,cAAc;+GAAd,cAAc,YALf,gBAAgB;+GAKf,cAAc,YALf,gBAAgB;;2FAKf,cAAc;kBAN1B,QAAQ;mBAAC;oBACR,OAAO,EAAE,CAAC,gBAAgB,CAAC;oBAC3B,SAAS,EAAE;oBACT,uBAAuB;qBACxB;iBACF","sourcesContent":["import { NgModule } from '@angular/core';\nimport { HttpClientModule } from '@angular/common/http';\n\n@NgModule({\n imports: [HttpClientModule],\n providers: [\n // SneatTeamApiService,\n ],\n})\nexport class SneatApiModule {}\n"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { runInInjectionContext } from '@angular/core';
|
|
2
|
+
import { doc, getDoc, query, where, onSnapshot, limit, } from '@angular/fire/firestore';
|
|
3
|
+
import { from, map, Subject } from 'rxjs';
|
|
4
|
+
export class SneatFirestoreService {
|
|
5
|
+
constructor(injector,
|
|
6
|
+
// private readonly afs: AngularFirestore,
|
|
7
|
+
dto2brief = (id, dto) => ({
|
|
8
|
+
...dto,
|
|
9
|
+
id,
|
|
10
|
+
})) {
|
|
11
|
+
this.injector = injector;
|
|
12
|
+
this.dto2brief = dto2brief;
|
|
13
|
+
if (!dto2brief) {
|
|
14
|
+
throw new Error('dto2brief is required');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
watchByID(collection, id) {
|
|
18
|
+
const docRef = runInInjectionContext(this.injector, () => doc(collection, id));
|
|
19
|
+
return this.watchByDocRef(docRef);
|
|
20
|
+
}
|
|
21
|
+
watchByDocRef(docRef) {
|
|
22
|
+
return runInInjectionContext(this.injector, () => {
|
|
23
|
+
const subj = new Subject();
|
|
24
|
+
// const snapshots = docSnapshots<Dbo2>(docRef);
|
|
25
|
+
onSnapshot(docRef, (snapshot) => subj.next(snapshot), (err) => subj.error(err), () => subj.complete());
|
|
26
|
+
// const snapshots = from(getDoc<Dbo2>(docRef));
|
|
27
|
+
return subj.asObservable().pipe(
|
|
28
|
+
// tap((snapshot) =>
|
|
29
|
+
// console.log(
|
|
30
|
+
// `SneatFirestoreService.watchByDocRef(${docRef.path}): snapshot:`,
|
|
31
|
+
// snapshot,
|
|
32
|
+
// ),
|
|
33
|
+
// ),
|
|
34
|
+
map((changes) => docSnapshotToDto(docRef.id, this.dto2brief, changes)));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
getByDocRef(docRef) {
|
|
38
|
+
return from(getDoc(docRef)).pipe(map((changes) => docSnapshotToDto(docRef.id, this.dto2brief, changes)));
|
|
39
|
+
}
|
|
40
|
+
watchSnapshotsByFilter(collectionRef, queryArgs) {
|
|
41
|
+
const operator = (f) => f.field.endsWith('IDs') ? 'array-contains' : f.operator;
|
|
42
|
+
const q = query(collectionRef, ...(queryArgs?.filter || []).map((f) => where(f.field, operator(f), f.value)), ...(queryArgs?.orderBy || []), ...(queryArgs?.limit ? [limit(queryArgs.limit)] : []));
|
|
43
|
+
const subj = new Subject();
|
|
44
|
+
onSnapshot(q, subj);
|
|
45
|
+
return subj;
|
|
46
|
+
}
|
|
47
|
+
watchByFilter(collectionRef, queryArgs) {
|
|
48
|
+
return this.watchSnapshotsByFilter(collectionRef, queryArgs).pipe(map((querySnapshot) => {
|
|
49
|
+
return querySnapshot.docs.map(this.docSnapshotToContext.bind(this));
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
docSnapshotsToContext(docSnapshots) {
|
|
53
|
+
return docSnapshots.map((doc) => {
|
|
54
|
+
return this.docSnapshotToContext(doc);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
docSnapshotToContext(doc) {
|
|
58
|
+
const { id } = doc;
|
|
59
|
+
const dto = doc.data();
|
|
60
|
+
const brief = dto && this.dto2brief(id, dto);
|
|
61
|
+
return {
|
|
62
|
+
id,
|
|
63
|
+
dto,
|
|
64
|
+
brief,
|
|
65
|
+
}; // TODO: try to remove this cast
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function docSnapshotToDto(id, dto2brief, docSnapshot) {
|
|
69
|
+
if (!docSnapshot.exists) {
|
|
70
|
+
return { id, brief: null, dbo: null };
|
|
71
|
+
}
|
|
72
|
+
const dto = docSnapshot.data();
|
|
73
|
+
return { id, dbo: dto, brief: dto ? dto2brief(id, dto) : undefined };
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=sneat-firestore.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sneat-firestore.service.js","sourceRoot":"","sources":["../../../../../libs/api/src/lib/sneat-firestore.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injector, runInInjectionContext } from '@angular/core';\nimport {\n doc,\n getDoc,\n CollectionReference,\n DocumentReference,\n DocumentSnapshot,\n query,\n where,\n onSnapshot,\n limit,\n} from '@angular/fire/firestore';\nimport { IIdAndOptionalBriefAndOptionalDbo } from '@sneat/core';\nimport { QuerySnapshot, QueryOrderByConstraint } from 'firebase/firestore';\nimport { WhereFilterOp } from '@firebase/firestore-types';\nimport { INavContext } from '@sneat/core';\nimport { from, map, Observable, Subject } from 'rxjs';\n\nexport interface IFilter {\n readonly field: string;\n readonly operator: WhereFilterOp;\n readonly value: unknown;\n}\n\nexport interface IQueryArgs {\n readonly limit?: number;\n readonly filter?: readonly IFilter[];\n readonly orderBy?: readonly QueryOrderByConstraint[];\n}\n\nexport class SneatFirestoreService<Brief, Dbo extends Brief> {\n constructor(\n private readonly injector: Injector,\n // private readonly afs: AngularFirestore,\n private readonly dto2brief: (id: string, dto: Dbo) => Brief = (\n id: string,\n dto: Dbo,\n ) => ({\n ...(dto as unknown as Brief),\n id,\n }),\n ) {\n if (!dto2brief) {\n throw new Error('dto2brief is required');\n }\n }\n\n watchByID<Dbo2 extends Dbo>(\n collection: CollectionReference<Dbo2>,\n id: string,\n ): Observable<IIdAndOptionalBriefAndOptionalDbo<Brief, Dbo2>> {\n const docRef = runInInjectionContext(this.injector, () =>\n doc(collection, id),\n );\n return this.watchByDocRef(docRef);\n }\n\n watchByDocRef<Dbo2 extends Dbo>(\n docRef: DocumentReference<Dbo2>,\n ): Observable<IIdAndOptionalBriefAndOptionalDbo<Brief, Dbo2>> {\n return runInInjectionContext(this.injector, () => {\n const subj = new Subject<DocumentSnapshot<Dbo2>>();\n // const snapshots = docSnapshots<Dbo2>(docRef);\n onSnapshot(\n docRef,\n (snapshot) => subj.next(snapshot),\n (err) => subj.error(err),\n () => subj.complete(),\n );\n // const snapshots = from(getDoc<Dbo2>(docRef));\n return subj.asObservable().pipe(\n // tap((snapshot) =>\n // \tconsole.log(\n // \t\t`SneatFirestoreService.watchByDocRef(${docRef.path}): snapshot:`,\n // \t\tsnapshot,\n // \t),\n // ),\n map((changes) =>\n docSnapshotToDto<Brief, Dbo2>(docRef.id, this.dto2brief, changes),\n ),\n );\n });\n }\n\n getByDocRef<Dbo2 extends Dbo>(\n docRef: DocumentReference<Dbo2>,\n ): Observable<INavContext<Brief, Dbo2>> {\n return from(getDoc(docRef)).pipe(\n map((changes) =>\n docSnapshotToDto<Brief, Dbo2>(docRef.id, this.dto2brief, changes),\n ),\n );\n }\n\n watchSnapshotsByFilter<Dbo2 extends Dbo>(\n collectionRef: CollectionReference<Dbo2>,\n queryArgs?: IQueryArgs,\n ): Observable<QuerySnapshot<Dbo2>> {\n const operator = (f: IFilter) =>\n f.field.endsWith('IDs') ? 'array-contains' : f.operator;\n const q = query(\n collectionRef,\n ...(queryArgs?.filter || []).map((f) =>\n where(f.field, operator(f), f.value),\n ),\n ...(queryArgs?.orderBy || []),\n ...(queryArgs?.limit ? [limit(queryArgs.limit)] : []),\n );\n const subj = new Subject<QuerySnapshot<Dbo2>>();\n onSnapshot(q, subj);\n return subj;\n }\n\n watchByFilter<Dbo2 extends Dbo>(\n collectionRef: CollectionReference<Dbo2>,\n queryArgs?: IQueryArgs,\n ): Observable<INavContext<Brief, Dbo2>[]> {\n return this.watchSnapshotsByFilter(collectionRef, queryArgs).pipe(\n map((querySnapshot) => {\n return querySnapshot.docs.map(this.docSnapshotToContext.bind(this));\n }),\n );\n }\n\n docSnapshotsToContext<Dbo2 extends Dbo>(\n docSnapshots: DocumentSnapshot<Dbo2>[],\n ): INavContext<Brief, Dbo2>[] {\n return docSnapshots.map((doc) => {\n return this.docSnapshotToContext(doc);\n });\n }\n\n docSnapshotToContext<Dbo2 extends Dbo>(\n doc: DocumentSnapshot<Dbo2>,\n ): INavContext<Brief, Dbo2> {\n const { id } = doc;\n const dto: Dbo2 | undefined = doc.data();\n const brief = dto && this.dto2brief(id, dto);\n return {\n id,\n dto,\n brief,\n } as unknown as INavContext<Brief, Dbo2>; // TODO: try to remove this cast\n }\n}\n\nexport function docSnapshotToDto<Brief, Dbo extends Brief>(\n id: string,\n dto2brief: (id: string, dto: Dbo) => Brief,\n docSnapshot: DocumentSnapshot<Dbo>,\n): INavContext<Brief, Dbo> {\n if (!docSnapshot.exists) {\n return { id, brief: null, dbo: null };\n }\n const dto: Dbo | undefined = docSnapshot.data();\n return { id, dbo: dto, brief: dto ? dto2brief(id, dto) : undefined };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sneat-api.js","sourceRoot":"","sources":["../../../../libs/api/src/sneat-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC","sourcesContent":["/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ISneatApiService } from './sneat-api-service.interface';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare const getStoreUrl: (storeId: string) => string;
|
|
4
|
+
export declare class SneatApiServiceFactory {
|
|
5
|
+
private services;
|
|
6
|
+
getSneatApiService(storeId: string): ISneatApiService;
|
|
7
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SneatApiServiceFactory, never>;
|
|
8
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<SneatApiServiceFactory>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { HttpClient, HttpParams } from '@angular/common/http';
|
|
2
|
+
import { InjectionToken, OnDestroy } from '@angular/core';
|
|
3
|
+
import { Auth } from '@angular/fire/auth';
|
|
4
|
+
import { Observable } from 'rxjs';
|
|
5
|
+
import { ISneatApiService } from './sneat-api-service.interface';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
export declare const SneatApiAuthTokenProvider: InjectionToken<unknown>;
|
|
8
|
+
export declare const SneatApiBaseUrl: InjectionToken<unknown>;
|
|
9
|
+
export declare const DefaultSneatAppApiBaseUrl = "https://api.sneat.ws/v0/";
|
|
10
|
+
export declare class SneatApiService implements ISneatApiService, OnDestroy {
|
|
11
|
+
private readonly httpClient;
|
|
12
|
+
private readonly afAuth;
|
|
13
|
+
private readonly baseUrl;
|
|
14
|
+
private readonly destroyed;
|
|
15
|
+
private authToken?;
|
|
16
|
+
constructor(httpClient: HttpClient, baseUrl: string | null, afAuth: Auth);
|
|
17
|
+
ngOnDestroy(): void;
|
|
18
|
+
setApiAuthToken: (token?: string) => void;
|
|
19
|
+
post<T>(endpoint: string, body: unknown): Observable<T>;
|
|
20
|
+
put<T>(endpoint: string, body: unknown): Observable<T>;
|
|
21
|
+
get<T>(endpoint: string, params?: HttpParams): Observable<T>;
|
|
22
|
+
getAsAnonymous<T>(endpoint: string, params?: HttpParams): Observable<T>;
|
|
23
|
+
postAsAnonymous<T>(endpoint: string, body: unknown): Observable<T>;
|
|
24
|
+
delete<T>(endpoint: string, params?: HttpParams, body?: unknown): Observable<T>;
|
|
25
|
+
private errorIfNotAuthenticated;
|
|
26
|
+
private headers;
|
|
27
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SneatApiService, [null, { optional: true; }, null]>;
|
|
28
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<SneatApiService>;
|
|
29
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { HttpHeaders, HttpParams } from '@angular/common/http';
|
|
3
|
+
export interface IHttpRequestOptions {
|
|
4
|
+
headers?: HttpHeaders | Record<string, string | string[]>;
|
|
5
|
+
observe?: 'body';
|
|
6
|
+
params?: HttpParams | Record<string, string | string[]>;
|
|
7
|
+
reportProgress?: boolean;
|
|
8
|
+
responseType?: 'json';
|
|
9
|
+
withCredentials?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface ISneatApiResponse<T> {
|
|
12
|
+
data: T;
|
|
13
|
+
}
|
|
14
|
+
export interface ISneatApiService {
|
|
15
|
+
post<I, O>(endpoint: string, body: I, options?: IHttpRequestOptions): Observable<O>;
|
|
16
|
+
put<I, O>(endpoint: string, body: I, options?: IHttpRequestOptions): Observable<O>;
|
|
17
|
+
get<T>(endpoint: string, params?: HttpParams, options?: IHttpRequestOptions): Observable<T>;
|
|
18
|
+
getAsAnonymous<T>(endpoint: string, params?: HttpParams, options?: IHttpRequestOptions): Observable<T>;
|
|
19
|
+
delete<T>(endpoint: string, params?: HttpParams, body?: unknown): Observable<T>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import * as i1 from "@angular/common/http";
|
|
3
|
+
export declare class SneatApiModule {
|
|
4
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SneatApiModule, never>;
|
|
5
|
+
static ɵmod: i0.ɵɵNgModuleDeclaration<SneatApiModule, never, [typeof i1.HttpClientModule], never>;
|
|
6
|
+
static ɵinj: i0.ɵɵInjectorDeclaration<SneatApiModule>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Injector } from '@angular/core';
|
|
2
|
+
import { CollectionReference, DocumentReference, DocumentSnapshot } from '@angular/fire/firestore';
|
|
3
|
+
import { IIdAndOptionalBriefAndOptionalDbo } from '@sneat/core';
|
|
4
|
+
import { QuerySnapshot, QueryOrderByConstraint } from 'firebase/firestore';
|
|
5
|
+
import { WhereFilterOp } from '@firebase/firestore-types';
|
|
6
|
+
import { INavContext } from '@sneat/core';
|
|
7
|
+
import { Observable } from 'rxjs';
|
|
8
|
+
export interface IFilter {
|
|
9
|
+
readonly field: string;
|
|
10
|
+
readonly operator: WhereFilterOp;
|
|
11
|
+
readonly value: unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface IQueryArgs {
|
|
14
|
+
readonly limit?: number;
|
|
15
|
+
readonly filter?: readonly IFilter[];
|
|
16
|
+
readonly orderBy?: readonly QueryOrderByConstraint[];
|
|
17
|
+
}
|
|
18
|
+
export declare class SneatFirestoreService<Brief, Dbo extends Brief> {
|
|
19
|
+
private readonly injector;
|
|
20
|
+
private readonly dto2brief;
|
|
21
|
+
constructor(injector: Injector, dto2brief?: (id: string, dto: Dbo) => Brief);
|
|
22
|
+
watchByID<Dbo2 extends Dbo>(collection: CollectionReference<Dbo2>, id: string): Observable<IIdAndOptionalBriefAndOptionalDbo<Brief, Dbo2>>;
|
|
23
|
+
watchByDocRef<Dbo2 extends Dbo>(docRef: DocumentReference<Dbo2>): Observable<IIdAndOptionalBriefAndOptionalDbo<Brief, Dbo2>>;
|
|
24
|
+
getByDocRef<Dbo2 extends Dbo>(docRef: DocumentReference<Dbo2>): Observable<INavContext<Brief, Dbo2>>;
|
|
25
|
+
watchSnapshotsByFilter<Dbo2 extends Dbo>(collectionRef: CollectionReference<Dbo2>, queryArgs?: IQueryArgs): Observable<QuerySnapshot<Dbo2>>;
|
|
26
|
+
watchByFilter<Dbo2 extends Dbo>(collectionRef: CollectionReference<Dbo2>, queryArgs?: IQueryArgs): Observable<INavContext<Brief, Dbo2>[]>;
|
|
27
|
+
docSnapshotsToContext<Dbo2 extends Dbo>(docSnapshots: DocumentSnapshot<Dbo2>[]): INavContext<Brief, Dbo2>[];
|
|
28
|
+
docSnapshotToContext<Dbo2 extends Dbo>(doc: DocumentSnapshot<Dbo2>): INavContext<Brief, Dbo2>;
|
|
29
|
+
}
|
|
30
|
+
export declare function docSnapshotToDto<Brief, Dbo extends Brief>(id: string, dto2brief: (id: string, dto: Dbo) => Brief, docSnapshot: DocumentSnapshot<Dbo>): INavContext<Brief, Dbo>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sneat/api",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -12,5 +12,17 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"tslib": "2.8.1"
|
|
15
|
-
}
|
|
15
|
+
},
|
|
16
|
+
"module": "esm2022/sneat-api.js",
|
|
17
|
+
"typings": "sneat-api.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
"./package.json": {
|
|
20
|
+
"default": "./package.json"
|
|
21
|
+
},
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./sneat-api.d.ts",
|
|
24
|
+
"default": "./esm2022/sneat-api.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"sideEffects": false
|
|
16
28
|
}
|