Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
common
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
npm
common
Commits
876ca5fc
Commit
876ca5fc
authored
Jan 24, 2019
by
Vladislav Lagunov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Исправления в импортах
parent
444c887c
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
9 additions
and
283 deletions
+9
-283
decoder/index.ts
+1
-1
fields/AutoComplete/state-machine.ts
+1
-1
fields/SelectField.tsx
+3
-3
jsonapi/resources.ts
+2
-2
utils/jsonapi/decoders.ts
+1
-271
utils/jsonapi/index.ts
+1
-5
utils/jsonapi/resources.ts
+0
-0
No files found.
decoder/index.ts
View file @
876ca5fc
...
@@ -403,8 +403,8 @@ export function optional(key: string|string[], dec: Decoder<any>, def: any): Dec
...
@@ -403,8 +403,8 @@ export function optional(key: string|string[], dec: Decoder<any>, def: any): Dec
/**
/**
* Создание декодера перечислением всех допустимых значений
* Создание декодера перечислением всех допустимых значений
*/
*/
export
function
variants
<
A
extends
Expr
[]
>
(...
array
:
A
):
Variants
<
A
[
number
]
>
;
export
function
variants
<
A
extends
Expr
[]
>
(
array
:
A
):
Variants
<
A
[
number
]
>
;
export
function
variants
<
A
extends
Expr
[]
>
(
array
:
A
):
Variants
<
A
[
number
]
>
;
export
function
variants
<
A
extends
Expr
[]
>
(...
array
:
A
):
Variants
<
A
[
number
]
>
;
export
function
variants
():
Variants
<
any
>
{
export
function
variants
():
Variants
<
any
>
{
return
new
Variants
(
Array
.
isArray
(
arguments
[
0
])
?
arguments
[
0
]
:
Array
.
prototype
.
slice
.
call
(
arguments
));
return
new
Variants
(
Array
.
isArray
(
arguments
[
0
])
?
arguments
[
0
]
:
Array
.
prototype
.
slice
.
call
(
arguments
));
}
}
...
...
fields/AutoComplete/state-machine.ts
View file @
876ca5fc
import
{
Err
,
AuthCtx
}
from
"~/context"
;
import
{
Err
,
AuthCtx
}
from
"~/context"
;
import
{
Cmd
,
noop
,
Eff
,
cmd
}
from
"
@bitmaster
/core"
;
import
{
Cmd
,
noop
,
Eff
,
cmd
}
from
"
../..
/core"
;
/**
/**
...
...
fields/SelectField.tsx
View file @
876ca5fc
...
@@ -9,7 +9,7 @@ import Select, { SelectProps } from '@material-ui/core/Select';
...
@@ -9,7 +9,7 @@ import Select, { SelectProps } from '@material-ui/core/Select';
import
{
AuthCtx
as
Ctx
}
from
'~/context'
;
import
{
AuthCtx
as
Ctx
}
from
'~/context'
;
import
{
Err
,
notifyError
}
from
'~/context'
;
import
{
Err
,
notifyError
}
from
'~/context'
;
import
*
as
Rx
from
'rxjs'
;
import
*
as
Rx
from
'rxjs'
;
import
{
Eff
}
from
'
@bitmaster
/core'
;
import
{
Eff
}
from
'
..
/core'
;
// Источник для опций
// Источник для опций
...
@@ -25,7 +25,7 @@ export type AsyncSource<A> = {
...
@@ -25,7 +25,7 @@ export type AsyncSource<A> = {
// Props
// Props
export
type
Props
<
A
=
any
>
=
StandardProps
<
React
.
HTMLProps
<
HTMLDivElement
>
,
ClassKey
>
&
FieldProps
<
A
>
&
{
export
type
Props
<
A
=
any
>
=
StandardProps
<
React
.
HTMLProps
<
HTMLDivElement
>
,
ClassKey
,
'disabled'
>
&
FieldProps
<
A
>
&
{
selectProps
?:
Partial
<
SelectProps
>
;
selectProps
?:
Partial
<
SelectProps
>
;
source
:
Source
<
A
>
;
source
:
Source
<
A
>
;
renderItem
?(
item
:
A
):
string
;
renderItem
?(
item
:
A
):
string
;
...
@@ -125,7 +125,7 @@ export default class SelectField<A = any> extends React.Component<Props<A>, Stat
...
@@ -125,7 +125,7 @@ export default class SelectField<A = any> extends React.Component<Props<A>, Stat
const
valueIdx
=
options
.
findIndex
(
x
=>
predicate
(
x
,
value
!
));
const
valueIdx
=
options
.
findIndex
(
x
=>
predicate
(
x
,
value
!
));
return
(
return
(
<
Select
value=
{
valueIdx
}
onChange=
{
this
.
handleChange
}
className=
{
rootClass
}
disabled=
{
disabled
}
open=
{
open
}
onOpen=
{
this
.
handleOpen
}
onClose=
{
this
.
handleClose
}
>
<
Select
value=
{
valueIdx
}
onChange=
{
this
.
handleChange
}
className=
{
rootClass
}
disabled=
{
Boolean
(
disabled
)
}
open=
{
open
}
onOpen=
{
this
.
handleOpen
}
onClose=
{
this
.
handleClose
}
>
{
nullCase
&&
<
MenuItem
key=
"@null"
value=
{
-
1
}
>
{
nullCase
}
</
MenuItem
>
}
{
nullCase
&&
<
MenuItem
key=
"@null"
value=
{
-
1
}
>
{
nullCase
}
</
MenuItem
>
}
{
options
.
map
((
item
,
idx
)
=>
<
MenuItem
key=
{
idx
}
value=
{
idx
}
>
{
(
renderItem
||
String
)(
item
)
}
</
MenuItem
>)
}
{
options
.
map
((
item
,
idx
)
=>
<
MenuItem
key=
{
idx
}
value=
{
idx
}
>
{
(
renderItem
||
String
)(
item
)
}
</
MenuItem
>)
}
</
Select
>
</
Select
>
...
...
jsonapi/resources.ts
View file @
876ca5fc
...
@@ -4,7 +4,7 @@ import { Expr } from '../types';
...
@@ -4,7 +4,7 @@ import { Expr } from '../types';
import
*
as
decoders
from
'./decoders'
;
import
*
as
decoders
from
'./decoders'
;
import
{
Decoder
,
Validation
}
from
'../decoder'
;
import
{
Decoder
,
Validation
}
from
'../decoder'
;
import
{
Left
,
Right
}
from
'../either'
;
import
{
Left
,
Right
}
from
'../either'
;
import
{
Params
}
from
'../http'
;
import
{
Params
}
from
'../
core/
http'
;
/** Ресурс jsonapi */
/** Ресурс jsonapi */
...
@@ -85,7 +85,7 @@ export class JsonApiBase<A> {
...
@@ -85,7 +85,7 @@ export class JsonApiBase<A> {
case
'RelatedMany'
:
{
case
'RelatedMany'
:
{
acc
.
fields
[
ty
]
=
acc
.
fields
[
ty
]
||
{};
acc
.
fields
[
ty
]
=
acc
.
fields
[
ty
]
||
{};
acc
.
fields
[
ty
][
key
]
=
true
;
acc
.
fields
[
ty
][
key
]
=
true
;
if
(
!
isEmpty
(
field
.
child
ren
.
desc
))
acc
.
include
[
path
.
concat
(
key
).
join
(
'.'
)]
=
true
;
if
(
!
isEmpty
(
field
.
child
.
desc
))
acc
.
include
[
path
.
concat
(
key
).
join
(
'.'
)]
=
true
;
for
(
let
k
in
field
.
child
.
desc
)
{
for
(
let
k
in
field
.
child
.
desc
)
{
if
(
!
field
.
child
.
desc
.
hasOwnProperty
(
k
))
continue
;
if
(
!
field
.
child
.
desc
.
hasOwnProperty
(
k
))
continue
;
go
(
acc
,
path
.
concat
(
key
),
field
.
child
.
type
,
k
,
field
.
child
.
desc
[
k
]);
go
(
acc
,
path
.
concat
(
key
),
field
.
child
.
type
,
k
,
field
.
child
.
desc
[
k
]);
...
...
utils/jsonapi/decoders.ts
View file @
876ca5fc
import
*
as
t
from
'../../decoder'
;
export
*
from
'../../jsonapi/decoders'
;
import
{
Decoder
,
decoder
,
required
,
optional
,
Validation
}
from
'../../decoder'
;
import
{
success
,
failure
}
from
'../../either'
;
/** tolarate numbers as strings */
export
const
stringOrNumber
:
Decoder
<
string
>
=
decoder
(
'stringOrNumber'
,
v
=>
typeof
(
v
)
===
'string'
||
typeof
(
v
)
===
'number'
?
success
(
String
(
v
))
:
failure
(
'not a string nor a number'
)
);
/** top level http://jsonapi.org/format/#document-top-level */
export
interface
Document
{
data
:
Resource
|
Resource
[]
|
null
|
undefined
;
meta
:
Record
<
string
,
JSON
>
|
null
;
included
:
Resource
[]
|
null
;
jsonapi
:
Jsonapi
|
null
;
links
:
{
[
key
:
string
]:
Link
}
|
null
;
}
/** a document, containing errors */
export
interface
Errors
{
errors
:
ErrorObject
[],
meta
:
Object
|
null
;
included
:
Resource
[]
|
null
;
jsonapi
:
Jsonapi
|
null
;
links
:
{
[
key
:
string
]:
Link
}
|
null
;
}
/** error obeject http://jsonapi.org/format/#error-objects */
export
interface
ErrorObject
{
id
:
string
|
null
;
links
:
{
[
s
:
string
]:
Link
}
|
null
;
status
:
string
|
null
;
code
:
string
|
null
;
title
:
string
|
null
;
detail
:
string
|
null
;
source
:
{
pointer
:
string
,
parameter
:
string
}
|
null
;
}
/** jsonapi resource http://jsonapi.org/format/#document-resource-objects */
export
interface
Resource
{
id
:
string
;
type
:
string
;
attributes
:
{
[
k
:
string
]:
any
}
|
null
;
relationships
:
{
[
k
:
string
]:
Relationship
}
|
null
;
meta
:
Object
|
null
;
}
/** link object http://jsonapi.org/format/#document-links */
export
type
Link
=
string
|
{
href
:
string
;
meta
:
Object
|
null
;
}
/** attributes http://jsonapi.org/format/#document-resource-object-attributes */
export
type
Attributes
=
Object
;
/** relationship http://jsonapi.org/format/#document-resource-object-relationships */
export
interface
Relationship
{
data
:
Linkage
;
meta
:
Object
|
null
;
links
:
{
[
k
:
string
]:
Link
}
|
null
;
}
/** linkage http://jsonapi.org/format/#document-resource-object-linkage */
export
type
Linkage
=
null
|
Identifier
|
Identifier
[]
/** resource identifier http://jsonapi.org/format/#document-resource-identifier-objects */
export
interface
Identifier
{
id
:
string
;
type
:
string
;
meta
:
object
|
null
;
}
/** jsonapi version http://jsonapi.org/format/#document-jsonapi-object */
export
interface
Jsonapi
{
version
:
string
;
}
/** identifier validation */
export
const
identifier
=
t
.
ap
(
required
(
'id'
,
stringOrNumber
),
required
(
'type'
,
t
.
string
),
optional
(
'meta'
,
tolerantDict
(
t
.
any
),
null
),
(
id
,
type
,
meta
)
=>
({
id
,
type
,
meta
})
);
/** linkage validation */
export
const
linkage
=
t
.
oneOf
(
t
.
null
,
identifier
,
t
.
array
(
identifier
));
/** link validation */
export
const
link
=
t
.
oneOf
(
t
.
string
,
t
.
ap
(
required
(
'href'
,
t
.
string
),
optional
(
'meta'
,
tolerantDict
(
t
.
any
),
null
),
(
href
,
meta
)
=>
({
href
,
meta
})
));
/** relationship validation */
export
const
relationship
=
t
.
ap
(
required
(
'data'
,
linkage
),
optional
(
'meta'
,
tolerantDict
(
t
.
any
),
null
),
optional
(
'links'
,
tolerantDict
(
link
),
null
),
(
data
,
meta
,
links
)
=>
({
data
,
meta
,
links
})
);
/** resource validation */
export
const
resource
:
Decoder
<
Resource
>
=
t
.
ap
(
required
(
'id'
,
stringOrNumber
),
required
(
'type'
,
t
.
string
),
optional
(
'attributes'
,
tolerantDict
(
t
.
any
),
null
),
optional
(
'relationships'
,
tolerantDict
(
relationship
),
null
),
optional
(
'meta'
,
tolerantDict
(
t
.
any
),
null
),
(
id
,
type
,
attributes
,
relationships
,
meta
)
=>
({
id
,
type
,
attributes
,
relationships
,
meta
})
);
/** jsonapi version validation */
export
const
jsonapi
=
required
(
'version'
,
t
.
string
).
map
(
version
=>
({
version
}));
/** document validation */
export
const
document
=
t
.
ap
(
optional
(
'data'
,
t
.
oneOf
(
resource
,
t
.
array
(
resource
),
t
.
null
),
undefined
),
optional
(
'meta'
,
tolerantDict
(
t
.
any
),
null
),
optional
(
'included'
,
t
.
array
(
resource
),
null
),
optional
(
'jsonapi'
,
jsonapi
,
null
),
optional
(
'links'
,
tolerantDict
(
link
),
null
),
(
data
,
meta
,
included
,
jsonapi
,
links
)
=>
({
data
,
meta
,
included
,
jsonapi
,
links
})
);
/** decode error object */
export
const
errorObject
=
t
.
ap
(
optional
(
'id'
,
t
.
string
,
null
),
optional
(
'links'
,
tolerantDict
(
link
),
null
),
optional
(
'status'
,
stringOrNumber
,
null
),
/* TODO: actualy can only be a string */
optional
(
'code'
,
t
.
string
,
null
),
optional
(
'title'
,
t
.
string
,
null
),
optional
(
'detail'
,
t
.
string
,
null
),
optional
(
'details'
,
t
.
string
,
null
),
/* HACK: due to TM quirks, this field doesn't appear in specification */
optional
(
'source'
,
t
.
record
({
pointer
:
t
.
string
,
parameter
:
t
.
string
}),
null
),
(
id
,
links
,
status
,
code
,
title
,
detail
,
details
,
source
)
=>
({
id
,
links
,
status
,
code
,
title
,
detail
:
detail
||
details
,
source
})
);
/** errors decoder */
export
const
errors
=
t
.
ap
(
required
(
'errors'
,
t
.
array
(
errorObject
)),
optional
(
'meta'
,
tolerantDict
(
t
.
any
),
null
),
optional
(
'jsonapi'
,
jsonapi
,
null
),
optional
(
'links'
,
tolerantDict
(
link
),
null
),
(
errors
,
meta
,
jsonapi
,
links
)
=>
({
errors
,
meta
,
jsonapi
,
links
})
);
/** validate attributes */
export
function
attributes
<
A
>
(
res
:
Resource
,
dec
:
Decoder
<
A
>
):
Validation
<
A
>
{
return
dec
.
validate
(
res
.
attributes
);
}
/** validate primary resource */
export
function
primary
(
doc
:
Document
):
Validation
<
Resource
>
{
return
Object
.
prototype
.
toString
.
call
(
doc
.
data
)
===
'[object Object]'
?
success
(
doc
.
data
as
Resource
)
:
failure
(
`jsonapi.primary: jsonapi document doesn't contain primary resorce`
);
}
/** validate resource collection */
export
function
collection
(
doc
:
Document
):
Validation
<
Resource
[]
>
{
return
Array
.
isArray
(
doc
.
data
)
?
success
(
doc
.
data
)
:
failure
(
'jsonapi.collection: jsonapi document doesn
\'
t contain collection of resorces'
);
}
/** meta */
export
function
meta
<
A
>
(
doc
:
Document
,
dec
:
Decoder
<
A
>
):
Validation
<
A
>
{
return
dec
.
validate
(
doc
.
meta
);
}
/** validate related resource */
export
function
related
(
doc
:
Document
,
res
:
Resource
,
name
:
string
):
Validation
<
Resource
>
{
if
(
doc
.
included
&&
res
.
relationships
&&
res
.
relationships
[
name
])
{
const
rel
:
Relationship
=
res
.
relationships
[
name
];
if
(
rel
.
data
!==
null
&&
!
Array
.
isArray
(
rel
.
data
))
{
const
{
id
,
type
}
=
rel
.
data
;
const
result
=
doc
.
included
.
find
(
a
=>
a
.
id
===
id
&&
a
.
type
===
type
);
return
result
?
success
(
result
)
:
failure
(
`jsonapi.related: cannot find related resource
${
name
}
-> '
${
type
}
', #
${
id
}
for '
${
res
.
type
}
', #
${
res
.
id
}
`
)
as
Validation
<
Resource
>
;
}
}
return
failure
(
`jsonapi.related: cannot find related resource
${
name
}
for '
${
res
.
type
}
', #
${
res
.
id
}
`
);
}
/** validate related resource (one-to-many) */
export
function
relatedCollection
(
doc
:
Document
,
res
:
Resource
,
name
:
string
):
Validation
<
Resource
[]
>
{
if
(
doc
.
included
&&
res
.
relationships
&&
res
.
relationships
[
name
])
{
const
rel
:
Relationship
=
res
.
relationships
[
name
];
if
(
Array
.
isArray
(
rel
.
data
))
{
const
acc
:
Resource
[]
=
[];
for
(
let
i
in
rel
.
data
)
{
const
{
id
,
type
}
=
rel
.
data
[
i
];
const
result
=
doc
.
included
.
find
(
a
=>
a
.
id
===
id
&&
a
.
type
===
type
);
if
(
result
)
{
acc
.
push
(
result
);
}
else
{
return
failure
(
`jsonapi.relatedCollection: cannot find related resource '
${
name
}
', id:
${
id
}
`
);
}
}
return
success
(
acc
);
}
}
return
failure
(
`jsonapi.relatedCollection: cannot find related resource '
${
name
}
' for '
${
res
.
type
}
', #
${
res
.
id
}
`
);
}
/** validate related resource (only identifier) */
export
function
relatedLinkage
(
res
:
Resource
,
name
:
string
):
Validation
<
Identifier
>
{
if
(
res
.
relationships
&&
res
.
relationships
[
name
])
{
const
rel
:
Relationship
=
res
.
relationships
[
name
];
return
rel
.
data
!==
null
&&
!
Array
.
isArray
(
rel
.
data
)
?
success
(
rel
.
data
)
:
failure
(
`jsonapi.relatedLinkage: cannot find relationship '
${
name
}
' for
${
res
.
type
}
#
${
res
.
id
}
`
);
}
return
failure
(
`relatedLinkage: trying to access relationship '
${
name
}
' on
${
res
.
type
}
#
${
res
.
id
}
: resource doesn't have relationships`
);
}
/** validate related resource collection (only identifiers) */
export
function
relatedLinkageCollection
(
res
:
Resource
,
name
:
string
):
Validation
<
Identifier
[]
>
{
if
(
res
.
relationships
&&
res
.
relationships
[
name
])
{
const
rel
:
Relationship
=
res
.
relationships
[
name
];
return
Array
.
isArray
(
rel
.
data
)
?
success
(
rel
.
data
)
:
failure
(
`relatedLinkageCollection: cannot find relationship '
${
name
}
' for
${
res
.
type
}
#
${
res
.
id
}
`
);
}
return
failure
(
`relatedLinkageCollection: trying to access relationship '
${
name
}
' on
${
res
.
type
}
#
${
res
.
id
}
: resource doesn't have relationships`
);
}
/** unlike `t.dict` this version ignores invalid values */
export
function
tolerantDict
<
A
>
(
d
:
Decoder
<
A
>
):
Decoder
<
Record
<
string
,
A
>>
{
return
decoder
(
'jsonapi.tolerantDict'
,
value
=>
{
if
(
Object
.
prototype
.
toString
.
call
(
value
)
!==
'[object Object]'
)
return
failure
(
'not an object'
);
const
output
=
{}
as
Record
<
string
,
A
>
;
for
(
let
key
in
value
)
{
if
(
!
value
.
hasOwnProperty
(
key
))
continue
;
const
ethr
=
d
.
validate
(
value
[
key
]);
switch
(
ethr
.
tag
)
{
case
'Left'
:
continue
;
case
'Right'
:
output
[
key
]
=
ethr
.
value
;
break
;
}
}
return
success
(
output
);
});
}
utils/jsonapi/index.ts
View file @
876ca5fc
import
*
as
decoders
from
'./decoders'
;
export
*
from
'../../jsonapi'
;
export
*
from
'./resources'
;
export
{
decoders
};
utils/jsonapi/resources.ts
View file @
876ca5fc
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment