@laboratoria/sdk-js 0.1.0 → 1.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/README.md +40 -3
- package/index.js +12 -20
- package/lib/core.js +67 -11
- package/lib/curriculum.js +59 -0
- package/lib/model.js +108 -36
- package/package.json +21 -11
- package/schemas/core.json +211 -11
- package/coverage/clover.xml +0 -140
- package/coverage/coverage-final.json +0 -9
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -79
- package/coverage/lcov-report/client.js.html +0 -152
- package/coverage/lcov-report/core.js.html +0 -281
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -126
- package/coverage/lcov-report/model.js.html +0 -557
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sdk-js/index.html +0 -111
- package/coverage/lcov-report/sdk-js/index.js.html +0 -293
- package/coverage/lcov-report/sdk-js/lib/campuses.js.html +0 -146
- package/coverage/lcov-report/sdk-js/lib/client.js.html +0 -152
- package/coverage/lcov-report/sdk-js/lib/core.js.html +0 -374
- package/coverage/lcov-report/sdk-js/lib/currencies.js.html +0 -89
- package/coverage/lcov-report/sdk-js/lib/index.html +0 -201
- package/coverage/lcov-report/sdk-js/lib/jobs.js.html +0 -143
- package/coverage/lcov-report/sdk-js/lib/model.js.html +0 -665
- package/coverage/lcov-report/sdk-js/lib/roles.js.html +0 -110
- package/coverage/lcov-report/sdk-js/lib/schemas.js.html +0 -434
- package/coverage/lcov-report/sdk-js/lib/team.js.html +0 -233
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -170
- package/coverage/lcov-report/team.js.html +0 -209
- package/coverage/lcov.info +0 -359
- package/index.spec.js +0 -112
- package/lib/client.spec.js +0 -77
- package/lib/currencies.js +0 -3
- package/lib/model.spec.js +0 -215
- package/lib/team.js +0 -52
- package/schemas/team.json +0 -146
package/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
## Laboratoria JavaScript (browser) SDK
|
2
2
|
|
3
|
+
[](https://github.com/Laboratoria/sdk-js/actions/workflows/node.js.yml)
|
4
|
+
|
3
5
|
:warning: This tool is still in draft stage and is likely to change without
|
4
6
|
notice.
|
5
7
|
|
@@ -25,7 +27,6 @@ const app = createApp({
|
|
25
27
|
firebaseApiKey: '',
|
26
28
|
firebaseProject: '',
|
27
29
|
coreApiUrl: '',
|
28
|
-
teamApiUrl: '',
|
29
30
|
jobsApiUrl: '',
|
30
31
|
});
|
31
32
|
```
|
@@ -79,7 +80,6 @@ app.user.create({
|
|
79
80
|
### Cohorts
|
80
81
|
|
81
82
|
```js
|
82
|
-
// Cohorts API
|
83
83
|
app.cohort.findMany({
|
84
84
|
where: {
|
85
85
|
end: { gt: new Date() },
|
@@ -96,13 +96,50 @@ app.cohort.findMany({
|
|
96
96
|
|
97
97
|
### Students
|
98
98
|
|
99
|
+
WIP
|
100
|
+
|
99
101
|
### Dropouts
|
100
102
|
|
103
|
+
WIP
|
101
104
|
|
102
105
|
### Projects
|
103
106
|
|
104
107
|
```js
|
105
108
|
app.project.findMany();
|
106
109
|
|
107
|
-
|
110
|
+
app.project.findMany({ tag: 'v3.0.0' });
|
111
|
+
|
112
|
+
app.project.findMany({
|
113
|
+
locale: 'es-ES',
|
114
|
+
track: 'js',
|
115
|
+
});
|
116
|
+
|
117
|
+
app.project.findById('cipher');
|
118
|
+
|
119
|
+
app.project.findById('cipher', { tag: 'v3.0.0' });
|
108
120
|
```
|
121
|
+
|
122
|
+
### Topics
|
123
|
+
|
124
|
+
```js
|
125
|
+
app.topic.findMany();
|
126
|
+
|
127
|
+
app.topic.findMany({ tag: 'v3.0.0' });
|
128
|
+
|
129
|
+
app.topic.findMany({
|
130
|
+
locale: 'es-ES',
|
131
|
+
track: 'js',
|
132
|
+
});
|
133
|
+
|
134
|
+
app.topic.findById('javascript');
|
135
|
+
|
136
|
+
app.topic.findById('javascript', { tag: 'v3.0.0' });
|
137
|
+
```
|
138
|
+
|
139
|
+
### Learning Objectives
|
140
|
+
|
141
|
+
```js
|
142
|
+
app.learningObjective.findMany();
|
143
|
+
|
144
|
+
app.learningObjective.findMany({ tag: 'v3.0.0' });
|
145
|
+
```
|
package/index.js
CHANGED
@@ -5,16 +5,14 @@ import {
|
|
5
5
|
signInWithEmailAndPassword,
|
6
6
|
signOut,
|
7
7
|
} from 'firebase/auth';
|
8
|
-
import { createClient } from './lib/client';
|
9
8
|
import { createAPI as createCoreAPI } from './lib/core';
|
9
|
+
import { createAPI as createCurriculumAPI } from './lib/curriculum';
|
10
10
|
import { createAPI as createJobsAPI } from './lib/jobs';
|
11
|
-
import { createAPI as createTeamAPI } from './lib/team';
|
12
11
|
|
13
12
|
export const createApp = ({
|
14
13
|
firebaseApiKey = 'AIzaSyAXbaEbpq8NOfn0r8mIrcoHvoGRkJThwdc',
|
15
14
|
firebaseProject = 'laboratoria-la',
|
16
15
|
coreApiUrl = 'https://us-central1-outpost-272720.cloudfunctions.net/core-api',
|
17
|
-
teamApiUrl = 'https://us-central1-outpost-272720.cloudfunctions.net/team-api',
|
18
16
|
jobsApiUrl = 'https://us-central1-outpost-272720.cloudfunctions.net/jobs-api',
|
19
17
|
} = {}) => {
|
20
18
|
const firebaseApp = initializeApp({
|
@@ -26,31 +24,25 @@ export const createApp = ({
|
|
26
24
|
|
27
25
|
const firebaseAuth = getAuth(firebaseApp);
|
28
26
|
const state = { authUser: undefined, user: undefined };
|
29
|
-
|
30
|
-
const
|
31
|
-
|
32
|
-
};
|
27
|
+
const coreAPI = createCoreAPI(coreApiUrl, state);
|
28
|
+
const jobsAPI = createJobsAPI(jobsApiUrl, state);
|
29
|
+
const curriculumAPI = createCurriculumAPI();
|
33
30
|
|
34
31
|
const authAPI = {
|
35
32
|
onChange: fn => onAuthStateChanged(firebaseAuth, (authUser) => {
|
36
33
|
if (!authUser) {
|
37
|
-
|
34
|
+
Object.assign(state, { authUser: null, user: null });
|
38
35
|
return fn(state);
|
39
36
|
}
|
40
|
-
|
37
|
+
Object.assign(state, { authUser });
|
38
|
+
coreAPI.user.findById(authUser.uid)
|
41
39
|
.then((user) => {
|
42
|
-
Object.assign(
|
43
|
-
isStaff: ['staff', 'manager', 'finance', 'admin'].includes(user.role),
|
44
|
-
isManager: ['manager', 'finance', 'admin'].includes(user.role),
|
45
|
-
isFinance: ['finance', 'admin'].includes(user.role),
|
46
|
-
isAdmin: user.role === 'admin',
|
47
|
-
});
|
48
|
-
setState(authUser, user);
|
40
|
+
Object.assign(state, { user });
|
49
41
|
fn(state);
|
50
42
|
})
|
51
43
|
.catch((err) => {
|
52
44
|
console.error(err);
|
53
|
-
|
45
|
+
Object.assign(state, { authUser: null, user: null });
|
54
46
|
fn(state);
|
55
47
|
});
|
56
48
|
}),
|
@@ -63,9 +55,9 @@ export const createApp = ({
|
|
63
55
|
};
|
64
56
|
|
65
57
|
return {
|
58
|
+
...jobsAPI,
|
59
|
+
...curriculumAPI,
|
60
|
+
...coreAPI,
|
66
61
|
auth: authAPI,
|
67
|
-
...createJobsAPI(jobsApiUrl, state),
|
68
|
-
...createTeamAPI(teamApiUrl, state),
|
69
|
-
...createCoreAPI(coreApiUrl, state),
|
70
62
|
};
|
71
63
|
};
|
package/lib/core.js
CHANGED
@@ -1,14 +1,18 @@
|
|
1
|
+
import md5 from 'blueimp-md5';
|
1
2
|
import { createModels, extendSchemaDefinitions } from './model';
|
2
3
|
import schema from '../schemas/core.json';
|
3
4
|
|
4
5
|
const extended = {
|
6
|
+
Country: {
|
7
|
+
plural: 'countries',
|
8
|
+
},
|
5
9
|
User: {
|
6
10
|
primaryKey: 'uid',
|
7
11
|
inputProps: [
|
8
12
|
'firstName',
|
9
13
|
'lastName',
|
10
14
|
'email',
|
11
|
-
'
|
15
|
+
'lang',
|
12
16
|
'github',
|
13
17
|
'linkedin',
|
14
18
|
'bio',
|
@@ -22,17 +26,24 @@ const extended = {
|
|
22
26
|
email: {
|
23
27
|
inputType: 'email',
|
24
28
|
},
|
25
|
-
locale: {
|
26
|
-
enum: ['es-ES', 'pt-BR'],
|
27
|
-
},
|
28
29
|
bio: {
|
29
30
|
inputType: 'textarea',
|
30
31
|
},
|
31
32
|
},
|
32
33
|
parse: (props) => {
|
34
|
+
const avatar = (
|
35
|
+
props.github
|
36
|
+
? `https://github.com/${props.github}.png?size=`
|
37
|
+
: `https://www.gravatar.com/avatar/${md5(props.email)}?s=`
|
38
|
+
)
|
33
39
|
return {
|
34
40
|
...props,
|
35
41
|
fullName: `${props.firstName} ${props.lastName}`,
|
42
|
+
avatar: size => `${avatar}${size}`,
|
43
|
+
isStaff: ['staff', 'manager', 'finance', 'admin'].includes(props.role),
|
44
|
+
isManager: ['manager', 'finance', 'admin'].includes(props.role),
|
45
|
+
isFinance: ['finance', 'admin'].includes(props.role),
|
46
|
+
isAdmin: props.role === 'admin',
|
36
47
|
};
|
37
48
|
},
|
38
49
|
},
|
@@ -59,6 +70,27 @@ const extended = {
|
|
59
70
|
`${name}${!stage ? '' : ` - ${stage.name}`} (id: ${id})`
|
60
71
|
),
|
61
72
|
properties: {},
|
73
|
+
parse: (props) => {
|
74
|
+
const now = Date.now();
|
75
|
+
// TODO: Handle case where start and/or end have not been selected in query
|
76
|
+
const status = (
|
77
|
+
props.start > now
|
78
|
+
? 'upcoming'
|
79
|
+
: props.end < now
|
80
|
+
? 'past'
|
81
|
+
: 'active'
|
82
|
+
);
|
83
|
+
const size = (
|
84
|
+
status === 'upcoming' && props.vacancies
|
85
|
+
? props.vacancies
|
86
|
+
: props._count?.students || props.students?.length || 0
|
87
|
+
);
|
88
|
+
return {
|
89
|
+
...props,
|
90
|
+
status,
|
91
|
+
size,
|
92
|
+
};
|
93
|
+
},
|
62
94
|
},
|
63
95
|
Student: {
|
64
96
|
inputProps: [],
|
@@ -71,8 +103,8 @@ const extended = {
|
|
71
103
|
'date',
|
72
104
|
'reason',
|
73
105
|
'reasonDetail',
|
74
|
-
'
|
75
|
-
'
|
106
|
+
'lastProject',
|
107
|
+
'completedProjects',
|
76
108
|
'notes',
|
77
109
|
'staffSad',
|
78
110
|
'covidRelated',
|
@@ -85,14 +117,38 @@ const extended = {
|
|
85
117
|
'cohort.name',
|
86
118
|
],
|
87
119
|
},
|
120
|
+
Contract: {
|
121
|
+
inputProps: [
|
122
|
+
'user',
|
123
|
+
'countryCode',
|
124
|
+
'currency',
|
125
|
+
'isEmployment',
|
126
|
+
'feeBasis',
|
127
|
+
'feeAmount',
|
128
|
+
'hoursPerWeek',
|
129
|
+
'start',
|
130
|
+
'end',
|
131
|
+
],
|
132
|
+
properties: {
|
133
|
+
countryCode: {
|
134
|
+
enum: ['BR', 'CL', 'CO', 'MX', 'PE'],
|
135
|
+
},
|
136
|
+
},
|
137
|
+
},
|
138
|
+
Gig: {
|
139
|
+
inputProps: [
|
140
|
+
// 'contract',
|
141
|
+
'cohort',
|
142
|
+
'user',
|
143
|
+
'role',
|
144
|
+
'hoursPerWeek',
|
145
|
+
'start',
|
146
|
+
'end',
|
147
|
+
],
|
148
|
+
},
|
88
149
|
};
|
89
150
|
|
90
151
|
export const createAPI = (url, state) => createModels(url, state, {
|
91
152
|
...schema,
|
92
153
|
definitions: extendSchemaDefinitions(schema, extended),
|
93
154
|
});
|
94
|
-
|
95
|
-
// const {
|
96
|
-
// delete: _,
|
97
|
-
// ...userAPI,
|
98
|
-
// } = createModel(coreApiUrl, state, 'users', schemas.user);
|
@@ -0,0 +1,59 @@
|
|
1
|
+
const releasesUrl = 'https://api.github.com/repos/Laboratoria/bootcamp/releases';
|
2
|
+
const rawUrl = 'https://raw.githubusercontent.com/Laboratoria/bootcamp';
|
3
|
+
|
4
|
+
const getLatestVersion = () => fetch(`${releasesUrl}/latest`)
|
5
|
+
.then(resp => resp.json())
|
6
|
+
.then(({ tag_name }) => tag_name);
|
7
|
+
|
8
|
+
const fetchProjects = async tag => (
|
9
|
+
fetch(`${rawUrl}/${tag || await getLatestVersion()}/dist/projects.json`)
|
10
|
+
.then(resp => resp.json())
|
11
|
+
);
|
12
|
+
|
13
|
+
const fetchProject = async (slug, tag) => (
|
14
|
+
fetch(`${rawUrl}/${tag || await getLatestVersion()}/dist/projects/${slug}.json`)
|
15
|
+
.then(resp => resp.json())
|
16
|
+
);
|
17
|
+
|
18
|
+
const fetchTopics = async tag => (
|
19
|
+
fetch(`${rawUrl}/${tag || await getLatestVersion()}/dist/topics.json`)
|
20
|
+
.then(resp => resp.json())
|
21
|
+
);
|
22
|
+
|
23
|
+
const fetchTopic = async (slug, tag) => (
|
24
|
+
fetch(`${rawUrl}/${tag || await getLatestVersion()}/dist/topics/${slug}.json`)
|
25
|
+
.then(resp => resp.json())
|
26
|
+
);
|
27
|
+
|
28
|
+
const fetchLearningObjectives = async tag => (
|
29
|
+
fetch(`${rawUrl}/${tag || await getLatestVersion()}/dist/learning-objectives.json`)
|
30
|
+
.then(resp => resp.json())
|
31
|
+
);
|
32
|
+
|
33
|
+
const filterByLocaleAndTrack = opts => arr => arr.filter((obj) => {
|
34
|
+
if (opts.locale && opts.locale !== obj.locale) {
|
35
|
+
return false;
|
36
|
+
}
|
37
|
+
if (opts.track && opts.track !== obj.track) {
|
38
|
+
return false;
|
39
|
+
}
|
40
|
+
return true;
|
41
|
+
});
|
42
|
+
|
43
|
+
export const createAPI = () => {
|
44
|
+
return {
|
45
|
+
projects: {
|
46
|
+
findMany: (opts = {}) => fetchProjects(opts.tag)
|
47
|
+
.then(filterByLocaleAndTrack(opts)),
|
48
|
+
findById: (slug, opts = {}) => fetchProject(slug, opts.tag),
|
49
|
+
},
|
50
|
+
topics: {
|
51
|
+
findMany: (opts = {}) => fetchTopics(opts.tag)
|
52
|
+
.then(filterByLocaleAndTrack(opts)),
|
53
|
+
findById: (slug, opts = {}) => fetchTopic(slug, opts.tag),
|
54
|
+
},
|
55
|
+
learningObjectives: {
|
56
|
+
findMany: (opts = {}) => fetchLearningObjectives(opts.tag),
|
57
|
+
},
|
58
|
+
};
|
59
|
+
};
|
package/lib/model.js
CHANGED
@@ -1,13 +1,53 @@
|
|
1
1
|
import { createClient } from './client.js';
|
2
2
|
|
3
|
+
|
4
|
+
const isRequiredOneToOneRelation = (schema, key) => (
|
5
|
+
!!schema.properties
|
6
|
+
&& !!schema.properties[key]
|
7
|
+
&& !!schema.properties[key].$ref
|
8
|
+
);
|
9
|
+
|
10
|
+
const isOptionalOneToOneRelation = (schema, key) => (
|
11
|
+
!!schema.properties
|
12
|
+
&& !!schema.properties[key]
|
13
|
+
&& Array.isArray(schema.properties[key].anyOf)
|
14
|
+
&& !!schema.properties[key].anyOf[0]?.$ref
|
15
|
+
&& schema.properties[key].anyOf[1]?.type === 'null'
|
16
|
+
);
|
17
|
+
|
18
|
+
const isOneToOneRelation = (schema, key) => (
|
19
|
+
isRequiredOneToOneRelation(schema, key)
|
20
|
+
|| isOptionalOneToOneRelation(schema, key)
|
21
|
+
);
|
22
|
+
|
23
|
+
const isOneToManyRelation = (schema, key) => (
|
24
|
+
schema.properties
|
25
|
+
&& schema.properties[key]
|
26
|
+
&& schema.properties[key].type === 'array'
|
27
|
+
&& !!schema.properties[key].items.$ref
|
28
|
+
);
|
29
|
+
|
30
|
+
// const isRelation = (schema, key) => (
|
31
|
+
// isOneToOneRelation(schema, key)
|
32
|
+
// || isOneToManyRelation(schema, key)
|
33
|
+
// );
|
34
|
+
|
35
|
+
|
3
36
|
const createValidator = (schema) => {
|
4
37
|
const properties = schema.properties || {};
|
5
38
|
const inputProps = schema.inputProps || Object.keys(properties);
|
6
39
|
|
7
40
|
const validateAttr = (key, value) => {
|
8
41
|
const attrSchema = properties[key] || {};
|
9
|
-
const type =
|
10
|
-
|
42
|
+
const type = (
|
43
|
+
Array.isArray(attrSchema.type)
|
44
|
+
? attrSchema.type[0]
|
45
|
+
: attrSchema.type
|
46
|
+
);
|
47
|
+
const isRequired = (
|
48
|
+
!Array.isArray(attrSchema.type)
|
49
|
+
|| !attrSchema.type.includes('null')
|
50
|
+
);
|
11
51
|
|
12
52
|
if (attrSchema.enum) {
|
13
53
|
if (!isRequired && !value) {
|
@@ -63,42 +103,47 @@ const createBuildURL = collectionName => (id, q) => {
|
|
63
103
|
};
|
64
104
|
|
65
105
|
|
66
|
-
const
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
{
|
85
|
-
|
106
|
+
const serializeData = (data, schema) => {
|
107
|
+
const hasInputProps = Array.isArray(schema.inputProps);
|
108
|
+
const payload = Object.keys(data).reduce(
|
109
|
+
(memo, key) => {
|
110
|
+
if (hasInputProps && !schema.inputProps.includes(key)) {
|
111
|
+
return memo;
|
112
|
+
}
|
113
|
+
if (isOptionalOneToOneRelation(schema, key) && data[key] === null) {
|
114
|
+
return memo;
|
115
|
+
}
|
116
|
+
return {
|
117
|
+
...memo,
|
118
|
+
[key]: data[key],
|
119
|
+
};
|
120
|
+
},
|
121
|
+
{},
|
122
|
+
);
|
123
|
+
|
124
|
+
// {
|
125
|
+
// signupCohort: {
|
126
|
+
// connect: { id: signupCohort.id },
|
127
|
+
// },
|
128
|
+
// }
|
129
|
+
|
130
|
+
return payload;
|
131
|
+
};
|
86
132
|
|
87
133
|
|
88
|
-
const createModel = (baseUrl, state, collectionName, schema = {}) => {
|
134
|
+
export const createModel = (baseUrl, state, collectionName, schema = {}) => {
|
135
|
+
const primaryKey = schema.primaryKey || 'id';
|
89
136
|
const validator = createValidator(schema);
|
90
137
|
const buildURL = createBuildURL(collectionName);
|
91
|
-
const defaultInclude = buildDefaultInclude(schema);
|
92
|
-
const buildQuery = createBuildQuery(defaultInclude);
|
93
138
|
const req = (...args) => createClient(baseUrl, state.authUser)(...args);
|
94
139
|
const create = q => req(buildURL(), {
|
95
140
|
method: 'POST',
|
96
|
-
body:
|
141
|
+
body: Object.assign(q, { data: serializeData(q.data, schema) }),
|
97
142
|
});
|
98
143
|
|
99
|
-
const put = q => req(buildURL(q.where
|
144
|
+
const put = q => req(buildURL(q.where[primaryKey]), {
|
100
145
|
method: 'PUT',
|
101
|
-
body:
|
146
|
+
body: Object.assign(q, { data: serializeData(q.data, schema) }),
|
102
147
|
});
|
103
148
|
|
104
149
|
const parse = data => {
|
@@ -123,23 +168,53 @@ const createModel = (baseUrl, state, collectionName, schema = {}) => {
|
|
123
168
|
);
|
124
169
|
};
|
125
170
|
|
171
|
+
const relations = Object.keys(schema.properties || {}).reduce(
|
172
|
+
(memo, key) => (
|
173
|
+
isRequiredOneToOneRelation(schema, key)
|
174
|
+
? Object.assign(memo, {
|
175
|
+
all: memo.all.concat(key),
|
176
|
+
oneToOne: memo.oneToOne.concat(key),
|
177
|
+
requiredOneToOne: memo.requiredOneToOne.concat(key),
|
178
|
+
})
|
179
|
+
: isOptionalOneToOneRelation(schema, key)
|
180
|
+
? Object.assign(memo, {
|
181
|
+
all: memo.all.concat(key),
|
182
|
+
oneToOne: memo.oneToOne.concat(key),
|
183
|
+
optionalOneToOne: memo.optionalOneToOne.concat(key),
|
184
|
+
})
|
185
|
+
: isOneToManyRelation(schema, key)
|
186
|
+
? Object.assign(memo, {
|
187
|
+
all: memo.all.concat(key),
|
188
|
+
oneToMany: memo.oneToMany.concat(key),
|
189
|
+
})
|
190
|
+
: memo
|
191
|
+
),
|
192
|
+
{
|
193
|
+
all: [],
|
194
|
+
oneToOne: [],
|
195
|
+
requiredOneToOne: [],
|
196
|
+
optionalOneToOne: [],
|
197
|
+
oneToMany: [],
|
198
|
+
},
|
199
|
+
);
|
200
|
+
|
126
201
|
return {
|
127
202
|
get schema() {
|
128
203
|
return schema;
|
129
204
|
},
|
130
|
-
get
|
131
|
-
return
|
205
|
+
get relations() {
|
206
|
+
return relations;
|
132
207
|
},
|
133
208
|
validateAttr: validator.validateAttr,
|
134
209
|
validate: validator.validate,
|
135
|
-
findMany: q => req(buildURL(null,
|
210
|
+
findMany: q => req(buildURL(null, q))
|
136
211
|
.then(results => results.map(parse)),
|
137
|
-
findById: (id, q) => req(buildURL(id,
|
212
|
+
findById: (id, q) => req(buildURL(id, q))
|
138
213
|
.then(raw => !!raw ? parse(raw) : raw),
|
139
214
|
create,
|
140
215
|
update: put,
|
141
216
|
upsert: opts => (
|
142
|
-
!opts.where
|
217
|
+
!opts.where[primaryKey]
|
143
218
|
? create({ data: opts.create })
|
144
219
|
: put({ where: opts.where, data: opts.update })
|
145
220
|
),
|
@@ -147,9 +222,6 @@ const createModel = (baseUrl, state, collectionName, schema = {}) => {
|
|
147
222
|
};
|
148
223
|
};
|
149
224
|
|
150
|
-
|
151
|
-
export default createModel;
|
152
|
-
|
153
225
|
export const createModels = (url, state, schema) => {
|
154
226
|
return Object.keys(schema.properties).reduce(
|
155
227
|
(prev, key) => {
|
package/package.json
CHANGED
@@ -1,23 +1,33 @@
|
|
1
1
|
{
|
2
2
|
"name": "@laboratoria/sdk-js",
|
3
|
-
"version": "
|
3
|
+
"version": "1.1.0",
|
4
4
|
"description": "Laboratoria JavaScript (browser) SDK",
|
5
5
|
"scripts": {
|
6
|
-
"test": "jest --verbose --coverage"
|
6
|
+
"test": "jest --verbose --coverage",
|
7
|
+
"changelog": "git log $(git describe --tags --abbrev=0)..HEAD --oneline --format=\"* %h %s (%an)\""
|
7
8
|
},
|
8
9
|
"license": "MIT",
|
9
10
|
"dependencies": {
|
10
|
-
"
|
11
|
+
"blueimp-md5": "^2.19.0",
|
12
|
+
"firebase": "^9.6.5"
|
11
13
|
},
|
12
14
|
"devDependencies": {
|
13
|
-
"@babel/core": "^7.16.
|
14
|
-
"@babel/plugin-transform-modules-commonjs": "^7.16.
|
15
|
-
"babel-jest": "^27.4.
|
16
|
-
"jest": "^27.4.
|
17
|
-
"webpack": "^5.
|
18
|
-
"webpack-cli": "^4.9.
|
15
|
+
"@babel/core": "^7.16.12",
|
16
|
+
"@babel/plugin-transform-modules-commonjs": "^7.16.8",
|
17
|
+
"babel-jest": "^27.4.6",
|
18
|
+
"jest": "^27.4.7",
|
19
|
+
"webpack": "^5.68.0",
|
20
|
+
"webpack-cli": "^4.9.2"
|
19
21
|
},
|
20
22
|
"jest": {
|
21
|
-
"testEnvironment": "jsdom"
|
23
|
+
"testEnvironment": "jsdom",
|
24
|
+
"coverageThreshold": {
|
25
|
+
"global": {
|
26
|
+
"statements": 97,
|
27
|
+
"branches": 92,
|
28
|
+
"functions": 98,
|
29
|
+
"lines": 97
|
30
|
+
}
|
31
|
+
}
|
22
32
|
}
|
23
|
-
}
|
33
|
+
}
|