Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Pôle IS
Bundles Symfony 2
ng-model-generator-bundle
Commits
211a8948
Commit
211a8948
authored
Feb 26, 2019
by
Guillaume Perréal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Génération d'un APIClient au lieu d'utiliser une AbstractResourceCache.
parent
c8d285d6
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
65 additions
and
87 deletions
+65
-87
src/Metadata/OperationDef.php
src/Metadata/OperationDef.php
+13
-0
src/OperationMapper.php
src/OperationMapper.php
+27
-34
src/Resources/views/common.ts.twig
src/Resources/views/common.ts.twig
+22
-39
src/Resources/views/metadata.ts.twig
src/Resources/views/metadata.ts.twig
+3
-13
src/Resources/views/repositories.ts.twig
src/Resources/views/repositories.ts.twig
+0
-1
No files found.
src/Metadata/OperationDef.php
View file @
211a8948
...
...
@@ -179,6 +179,19 @@ final class OperationDef implements \JsonSerializable, HasName
return
$this
->
isCollection
;
}
/**
* @return string
*/
public
function
__toString
():
string
{
return
sprintf
(
'operation "%s" (method=%s, isCollection=%s, special=%s)'
,
$this
->
originalName
,
$this
->
method
,
$this
->
isCollection
?
"yes"
:
"no"
,
$this
->
special
);
}
/**
* {@inheritdoc}
*/
...
...
src/OperationMapper.php
View file @
211a8948
...
...
@@ -104,12 +104,9 @@ final class OperationMapper
}
$opParameters
=
$body
=
[];
$callParameters
=
[
TypescriptHelper
::
quoteString
(
$this
->
operation
->
getMethod
())];
$callPath
=
$path
=
$this
->
pathParser
->
parse
(
$this
->
operation
->
getPath
(),
$this
->
operation
->
getRequirements
());
$iriParameterName
=
null
;
if
(
$this
->
iri
)
{
$iriParameter
=
new
Parameter
(
'iri'
,
Placeholder
::
get
(
sprintf
(
'IRI<%s>'
,
$this
->
operation
->
getClassName
())));
...
...
@@ -118,14 +115,12 @@ final class OperationMapper
if
(
$callPath
===
$this
->
iri
)
{
$opParameters
[]
=
$iriParameter
;
$iriParameterName
=
$iriParameter
->
getName
();
$callParameters
[]
=
$iriParameterName
.
' as any'
;
$urlParameter
=
$iriParameter
->
getName
();
}
else
{
foreach
(
$callPath
->
getParameters
()
as
$parameter
)
{
$opParameters
[]
=
$parameter
;
}
$body
[]
=
'const path = '
.
$callPath
->
getUsage
()
.
';'
;
$callParameters
[]
=
'path'
;
$urlParameter
=
$callPath
->
getUsage
();
}
$denormalization
=
$this
->
operation
->
getDenormalization
();
...
...
@@ -137,7 +132,6 @@ final class OperationMapper
}
$opParameters
[]
=
new
Parameter
(
'body'
,
$requestBody
);
$body
[]
=
'options.body = body;'
;
}
$filterProperties
=
$this
->
getFilterProperties
();
...
...
@@ -148,11 +142,10 @@ final class OperationMapper
}
$opParameters
[]
=
new
Parameter
(
'options'
,
Placeholder
::
get
(
'RequestOptions'
),
false
,
'{}'
);
$callParameters
[]
=
'options'
;
$returnType
=
$responseBody
?:
Placeholder
::
get
(
'HttpResponseBase
'
);
$returnType
=
$responseBody
?:
BuiltinType
::
get
(
'void
'
);
$body
[]
=
sprintf
(
'return %s;'
,
$this
->
buildClientCall
(
$callParameters
,
$returnType
,
$iriParameterNam
e
));
$body
[]
=
sprintf
(
'return %s;'
,
$this
->
buildClientCall
(
TypescriptHelper
::
quoteString
(
$this
->
operation
->
getMethod
()),
$urlParameter
,
'body'
,
'options'
,
$returnTyp
e
));
return
new
Operation
(
$this
->
operation
->
getName
(),
...
...
@@ -186,41 +179,41 @@ final class OperationMapper
}
/**
* @param array $callParameters
* @param Type $returnType
* @param string|null $iriParameterName
* @param string $method
* @param string $path
* @param string $body
* @param string $options
* @param Type $returnType
*
* @return string
*/
private
function
buildClientCall
(
array
$callParameters
,
Type
$returnType
,
?
string
$
iriParameterNam
e
):
string
private
function
buildClientCall
(
string
$method
,
string
$path
,
string
$body
,
string
$
options
,
Type
$returnTyp
e
):
string
{
$clientCall
=
sprintf
(
'this.client.request<%s>(%s)'
,
$returnType
->
getUsage
(),
implode
(
', '
,
$callParameters
)
);
$opDef
=
$this
->
operation
->
getOpDef
();
if
(
$opDef
->
isDeleteItem
())
{
return
"this.client.deleteItem(
$path
,
$options
)"
;
}
$type
=
$returnType
->
getUsage
();
if
(
$opDef
->
isGetCollection
())
{
return
"this.c
ache.getAll(
$clientCall
)"
;
return
"this.c
lient.getCollection<
$type
>(
$path
,
$options
)"
;
}
if
(
$opDef
->
isCreateItem
())
{
return
"this.c
ache.post(
$clientCall
)"
;
return
"this.c
lient.postItem<
$type
>(
$path
,
$body
,
$options
)"
;
}
if
(
$iriParameterName
)
{
if
(
$opDef
->
isGetItem
())
{
return
"this.cache.get(
$iriParameterName
, () =>
$clientCall
)"
;
}
if
(
$opDef
->
isUpdateItem
())
{
return
"this.cache.put(
$iriParameterName
,
$clientCall
)"
;
}
if
(
$opDef
->
isDeleteItem
())
{
return
"this.cache.delete(
$iriParameterName
,
$clientCall
)"
;
}
if
(
$opDef
->
isUpdateItem
())
{
return
"this.client.putItem<
$type
>(
$path
,
$body
,
$options
)"
;
}
if
(
$opDef
->
isGetItem
())
{
return
"this.client.getItem<
$type
>(
$path
,
$options
)"
;
}
return
$clientCall
;
return
"this.client.request<
$type
>(
$method
,
$path
,
$options
)"
;
}
/**
...
...
src/Resources/views/common.ts.twig
View file @
211a8948
{%
extends
'@NgModelGenerator/_layout.ts.twig'
%}
{%
block
content
%}
import {HttpClient, HttpHeaders, HttpResponseBase} from '@angular/common/http';
import { forkJoin, Observable } from 'rxjs';
/**
...
...
@@ -46,7 +45,7 @@ export interface Resource {
readonly [IRI_PROPERTY]: IRI
<any>
;
readonly [TYPE_PROPERTY]: string;
[property: string]: any;
}
;
}
/**
* Collection représente une collection de respoucres JSON-LD pour un type T donné.
...
...
@@ -92,62 +91,48 @@ export type DateTime = string;
* Options supplémentaires pour les requêtes.
*/
export interface RequestOptions {
body?: any;
headers?: HttpHeaders | {
[header: string]: string | string[];
};
headers?: { [header: string]: string | string[]; };
params?: { [param: string]: string | string[]; };
}
/**
* AbstractResourceCache est une classe abstraite qui définit l'interface d'un cache de ressources.
*
* Elle doit être implémentée puis être fournie en provider d'un module core. Par exemple:
*
* final class ResourceCache
<T
extends
Resource
>
extends AbstractResourceCache
<T>
{
* // Implémentation
* }
*
* providers: [
* [ provider: AbstractResourceCache, useClass: ResourceCache ],
* ]
* Client d'API, à implémenter.
*/
export abstract class AbstractResourceCache {
/**
* Récupère une ressource par son IRI. N'exécute la requête requestFactory que si on ne dispose
* pas d'une version en cache.
export abstract class APIClient {
/**
* Récupère une ressource par son IRI.
*/
public abstract get
<R
extends
Resource
>
(
iri: IRI
<R>
,
requestFactory: () => Observable
<R>
): Observable
<R>
;
public abstract getItem
<R
extends
Resource
>
(iri: IRI
<R>
, options?: RequestOptions): Observable
<R>
;
/**
* Met à jour une ressource existante
, rafraîchit le cache local avec la réponse
.
* Met à jour une ressource existante.
*/
public abstract put
<R
extends
Resource
>
(iri: IRI
<R>
,
request: Observable
<R>
): Observable
<R>
;
public abstract put
Item
<R
extends
Resource
>
(iri: IRI
<R>
,
item: any, options?: RequestOptions
): Observable
<R>
;
/**
* Crée une nouvelle ressource et met la ressource créée dans le cache.
*/
public abstract post
<R
extends
Resource
>
(
request: Observable
<R>
): Observable
<R>
;
public abstract post
Item
<R
extends
Resource
>
(
iri: string, item: any, options?: RequestOptions
): Observable
<R>
;
/**
* Supprime une ressource en distant et dans le cache.
*/
public abstract delete
<R
extends
Resource
>
(iri: IRI
<R>
,
request: Observable
<HttpResponseBase>
): Observable
<HttpResponseBase
>
;
public abstract delete
Item
<R
extends
Resource
>
(iri: IRI
<R>
,
options?: RequestOptions): Observable
<void
>
;
/**
* Effectue une recherche et met en cache toutes les ressources récupérées.
*/
public abstract getAll
<R
extends
Resource
>
(
request: Observable
<Collection
<
R
>
>
): Observable
<Collection
<
R
>
>;
public abstract getCollection
<C
extends
Collection
<
Resource
>
>(iri: string, options?: RequestOptions): Observable
<C>
;
/**
* Invalide une ressource en cache.
*/
public abstract invalidate
<R
extends
Resource
>
(iri: IRI
<R>
): void;
public abstract invalidateItem
<R
extends
Resource
>
(iri: IRI
<R>
): void;
/**
* Effectue une requête arbitraire.
*/
public abstract request
<T>
(method: string, url: string, options?: RequestOptions): Observable
<T>
;
}
/**
...
...
@@ -249,8 +234,7 @@ export class ResourceMetadata<R extends Resource, T extends string, P extends IR
export abstract class AbstractRepository
<R
extends
Resource
,
T
extends
string
,
P
extends
IRIParameters
>
{
public constructor(
public readonly metadata: ResourceMetadata
<R
,
T
,
P
>
,
protected readonly client: HttpClient,
protected readonly cache: AbstractResourceCache
protected readonly client: APIClient
) {}
/**
...
...
@@ -379,8 +363,7 @@ export abstract class AbstractAPIService<
public constructor(
public readonly metadata: MR,
public readonly repositories: RR,
private readonly cache: AbstractResourceCache,
private readonly client: HttpClient
private readonly client: APIClient
) {}
public get
<R
extends
Resource
>
(iri: IRI
<R>
, options?: RequestOptions): Observable
<R>
;
...
...
@@ -398,7 +381,7 @@ export abstract class AbstractAPIService<
iri = typeOrIRI as IRI
<R>
;
options = parametersOrOptions as RequestOptions;
}
return
this.cache.get(iri, () =>
this.client.get
<R>
(iri
as any
, options)
)
;
return this.client.get
Item
<R>
(iri, options);
}
public getMany
<R
extends
Resource
>
(iris: IRI
<R>
[], options?: RequestOptions): Observable
<R
[]
>
{
...
...
@@ -410,7 +393,7 @@ export abstract class AbstractAPIService<
}
public invalidate
<R
extends
Resource
>
(iri: IRI
<R>
): void {
this.c
ache
.invalidate(iri);
this.c
lient
.invalidate
Item
(iri);
}
}
...
...
src/Resources/views/metadata.ts.twig
View file @
211a8948
...
...
@@ -5,11 +5,10 @@
{%
block
content
%}
{%
autoescape
false
%}
import { Injectable, Provider } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import {
AbstractAPIService,
A
bstractResourceCache
,
A
PIClient
,
APIMeta,
APIRepositoryRegistry,
IRIMetadata,
...
...
@@ -93,13 +92,12 @@ export class AppMetadata extends LazyMetadataRegistry<AppAPI> {
@Injectable()
export class AppRepositories implements APIRepositoryRegistry
<AppAPI>
{
{%
for
repo
in
repositories
%}
public readonly
{{
repo.resourceName
}}
= new
{{
repo.name
}}
(this.metadata.
{{
repo.resourceName
}}
, this.client
, this.cache
);
public readonly
{{
repo.resourceName
}}
= new
{{
repo.name
}}
(this.metadata.
{{
repo.resourceName
}}
, this.client);
{%
endfor
%}
public constructor(
public readonly metadata: AppMetadata,
private readonly cache: AbstractResourceCache,
private readonly client: HttpClient
private readonly client: APIClient
) {}
public get
<T
extends
keyof
AppAPI
>
(type: T): AppAPI[T]['repository'] {
...
...
@@ -112,14 +110,6 @@ export class AppRepositories implements APIRepositoryRegistry<AppAPI> {
*/
@Injectable()
export class AppAPIService extends AbstractAPIService
<AppAPI
,
AppMetadata
,
AppRepositories
>
{
public constructor(
metadata: AppMetadata,
repositories: AppRepositories,
cache: AbstractResourceCache,
client: HttpClient
) {
super(metadata, repositories, cache, client);
}
}
/* Provider factories */
...
...
src/Resources/views/repositories.ts.twig
View file @
211a8948
...
...
@@ -5,7 +5,6 @@
{%
block
content
%}
{%
autoescape
false
%}
import { Observable } from 'rxjs';
import { HttpResponseBase } from '@angular/common/http';
// @ts-ignore
import { AbstractRepository, Collection, IRI, RequestOptions, UUID } from './common';
...
...
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