loopbackio / loopbackio/loopback-next

Allow RegExp values for `jsonSchema.pattern` field in property definition

Abierto
#4,228 6 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

developer-experience feature good first issue Hacktoberfest Repository
Lenguaje dominante
TypeScript
Estrellas
5.1k
Forks
1.1k
Merge medio
2 d 21 h
PR fusionados (30 d)
27

Descripción

When creating a model, I'd like to specify pattern-based validation for my `phoneNum` property:

```ts
@property({
type: 'string',
jsonSchema: {
pattern: /\d{3}-\d{3}-\d{4}/,
},
})
phoneNum?: string;
```

At the moment, we require the pattern to be a string source:

```js
pattern: '\\d{3}-\\d{3}-\\d{4}'
```

I find these strings problematic:
- Editors/IDEs don't highlight RegExp keywords
- It's easy to forget to escape `\` characters. When they are not escaped, users end up with a different RegExp that expected - see #4218 for an example.

## Workaround

Use `RegExp.source` property to convert from a RegExp instance to a source string.

```ts
@property({
type: 'string',
jsonSchema: {
pattern: /\d{3}-\d{3}-\d{4}/.source,
},
})
phoneNum?: string;
```

## Acceptance criteria

### Models (the important and also easy part)

Allow LB4 app developers to use RegExp `pattern` values in their model definitions, scoped to `jsonSchema` only for now (i.e. to apply during REST API validation only, not as a database constraint). Example property definition:

```ts
@property({
jsonSchema: {
pattern: /\d{3}-\d{3}-\d{4}/,
},
})
phoneNum?: string;
```

- [ ] Implementation: The conversion from `RegExp` to `string` should probably happen inside [`metaToJsonProperty()`](https://github.com/strongloop/loopback-next/blob/b0a84b5adc30cac3614ea90e414b59cf76009ecf/packages/repository-json-schema/src/build-schema.ts#L296-L298) function. Use [`RegExp.prototype.source`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source) property to convert a `RegExp` instance to a string.

- [ ] Test coverage: Add tests to verify the new behavior, e.g. to [`packages/repository-json-schema/src/__tests__/unit/build-schema.unit.ts`](https://github.com/strongloop/loopback-next/blob/b0a84b5adc30cac3614ea90e414b59cf76009ecf/packages/repository-json-schema/src/__tests__/unit/build-schema.unit.ts)

- [ ] Docs: Update documentation to explain users how to use `jsonSchema` and `jsonSchema.pattern` in `@property()` decorators - see e.g. https://loopback.io/doc/en/lb4/Model.html#supported-json-keywords

### REST API layer (optional, could be difficult to implement)

Allow LB4 app developers to use RegExp values in OpenAPI spec metadata, e.g. provided via Controller decorators.

```ts
class MyController {
greet(
@param({
name: 'date',
in: 'path',
schema: {
type: 'string',
pattern: /^\d{4}-\d{2}-\d{2}$/,
}
})
today: string,
) {
return `Good morning, today is ${date}`;
}
}
```

Start by writing a group of (acceptance-level) tests to verify handling of RegExp patterns by our REST API layer:
- [ ] Define a controller with a method with a parameter using `pattern`-based validation and a RegExp pattern value.
- [ ] Send a request with a valid value expecting 200 response.
- [ ] Send a request with an invalid value expecting 4xx response.
- [ ] Verify that the OpenAPI spec document returned by the app includes the pattern converted to string via `.source` property. Quoting from https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#properties: _pattern (This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect)_
- [ ] Fix the implementation (and type definitions) as necessary to allow such test to pass.
- [ ] I think we will need to update `@param` definitions to allow `RegExp` values for `pattern` fields.
- [ ] Figure out how to pass `RegExp` patterns to AJV so that it can perform pattern-base validation. It's possible that AJV supports RegExp values out of the box, in which case no changes may be required

## Out of scope

`pattern` as a top-level model property:

```ts
@property({
pattern: /\d{3}-\d{3}-\d{4}/,
...
})
```

Quoting from https://github.com/strongloop/loopback-next/issues/4228#issuecomment-646700989:

> The catch is that once `pattern` is a regular property metadata, it must be enforced both at REST API level (`@loopback/rest` must translate that pattern to AJV JSON Schema field) and at data-access level (by loopback-datasource-juggler), so it's more work to make this happen 🤷 The upside is that with a new property-level metadata, connectors can translate the `pattern` constraint to a database constraint too ([a PostgreSQL example](https://stackoverflow.com/a/35822507/69868)). Related: Epic: Validation at Model/ORM level #1872.

---

## 🎆 Hacktoberfest 2020

Greetings :wave: to all Hacktoberfest 2020 participants!

Here are few tips 👀 to make your start easier:

- Before you start working on this issue, please leave a comment to let others know.
- Feel free to implement support for RegExp patterns in model property definitions only, it's ok to leave the rest for others to pick up.
- If you are new to GitHub pull requests, then you can learn about the process in [Submitting a pull request to LoopBack 4](https://loopback.io/doc/en/lb4/submitting_a_pr.html).
- If this is your first contribution to LoopBack, then please take a look at our [Developer guide](https://loopback.io/doc/en/lb4/code-contrib-lb4.html)
- Feel free to ask for help in `#loopback-contributors` channel, you can join our Slack workspace [here](https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw).

See also #6456.

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Para el trabajo acotado del modelo, empieza en packages/repository-json-schema/src/build-schema.ts, en metaToJsonProperty(), y después añade casos a packages/repository-json-schema/src/__tests__/unit/build-schema.unit.ts. Ejecuta las pruebas unitarias de repository-json-schema y verifica que los patrones RegExp se representen mediante sus cadenas de origen. La parte más amplia de REST requiere pruebas de aceptación para solicitudes válidas e inválidas, además del documento OpenAPI generado, mientras que la actualización de la documentación debería cubrir el uso de jsonSchema.pattern.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
openapi, typescript
Área
api, backend-api-design, documentation, testing
Tipo de issue
Nueva funcionalidad
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
45/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.