loopbackio / loopbackio/loopback-next
Allow RegExp values for `jsonSchema.pattern` field in property definition
Nadie ha tomado este issue todavía.
- 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
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- 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