From 01bf5cfbe41cfdfee9df1713708e401c802d2f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20Herbaux?= Date: Tue, 23 Apr 2024 18:19:37 +0200 Subject: [PATCH] docs: update code formatting and minor text adjustments in type system documentation (#20186) --- .../05-type-system/02-concepts/01-schema.mdx | 19 ++-- .../05-type-system/02-concepts/02-uid.mdx | 18 ++-- .../02-concepts/03-public-registry.mdx | 87 ++++++++++--------- 3 files changed, 69 insertions(+), 55 deletions(-) diff --git a/docs/docs/guides/05-type-system/02-concepts/01-schema.mdx b/docs/docs/guides/05-type-system/02-concepts/01-schema.mdx index 115ad857ca..a5a76d78e8 100644 --- a/docs/docs/guides/05-type-system/02-concepts/01-schema.mdx +++ b/docs/docs/guides/05-type-system/02-concepts/01-schema.mdx @@ -67,8 +67,8 @@ For instance, a string attribute will resolve to a primitive string in an entity ### Usage -import Tabs from '@theme/Tabs' -import TabItem from '@theme/TabItem' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; @@ -89,22 +89,23 @@ declare const component: Schema.Component; declare function processAnySchema(schema: Schema.Schema): void; -processAnySchema(schema); // ✅ +processAnySchema(schema); // ✅ processAnySchema(contentType); // ✅ processAnySchema(component); // ✅ declare function processContentTypeSchema(schema: Schema.ContentType): void; -processContentTypeSchema(schema); // ✅ +processContentTypeSchema(schema); // ✅ processContentTypeSchema(contentType); // ✅ processContentTypeSchema(component); // ❌ Error, a component schema is not assignable to a content-type schema declare function processComponentSchema(schema: Schema.Component): void; -processComponentSchema(schema); // ✅ +processComponentSchema(schema); // ✅ processComponentSchema(contentType); // ❌ Error, a content-type schema is not assignable to a component schema processComponentSchema(component); // ✅ ``` + Schema definitions exported from the `Struct` namespace defines the low level type representation of Strapi schemas. @@ -112,6 +113,7 @@ Schema definitions exported from the `Struct` namespace defines the low level ty :::caution Those types can be useful when you want to validate other types against the base ones, but realistically, the public Schema types should almost always be preferred. ::: + ```typescript import type { Struct } from '@strapi/strapi'; @@ -121,21 +123,22 @@ declare const component: Struct.ComponentSchema; declare function processAnySchema(schema: Struct.Schema): void; -processAnySchema(schema); // ✅ +processAnySchema(schema); // ✅ processAnySchema(contentType); // ✅ processAnySchema(component); // ✅ declare function processContentTypeSchema(schema: Struct.ContentTypeSchema): void; -processContentTypeSchema(schema); // ✅ +processContentTypeSchema(schema); // ✅ processContentTypeSchema(contentType); // ✅ processContentTypeSchema(component); // ❌ Error, a component schema is not assignable to a content-type schema declare function processComponentSchema(schema: Struct.ComponentSchema): void; -processComponentSchema(schema); // ✅ +processComponentSchema(schema); // ✅ processComponentSchema(contentType); // ❌ Error, a content-type schema is not assignable to a component schema processComponentSchema(component); // ✅ ``` + diff --git a/docs/docs/guides/05-type-system/02-concepts/02-uid.mdx b/docs/docs/guides/05-type-system/02-concepts/02-uid.mdx index db2692423d..6d26d1c1ee 100644 --- a/docs/docs/guides/05-type-system/02-concepts/02-uid.mdx +++ b/docs/docs/guides/05-type-system/02-concepts/02-uid.mdx @@ -14,7 +14,6 @@ On this page, **a resource** is considered as **anything that can be identified This includes (but is not limited to) controllers, schema, services, policies, middlewares, etc... ::: - In the Type System, UIDs play a crucial role in referencing various resources (such as schema and entities) by attaching a unique identifier. To put it simply, a UID is a unique (string) literal key used to identify, locate, or access a particular resource within the system. @@ -26,6 +25,7 @@ This makes it the perfect tool to index type registries or to use as a type para ### Format A UID is composed of 3 different parts: + 1. A namespace ([link](#1-namespaces)) 2. A separator ([link](#2-separators)) 3. A name ([link](#3-names)) @@ -46,7 +46,7 @@ Scoped namespaces are defined by a base name, followed by a separator (`::`) and In Strapi there are two of them: | Name | Definition | Description | -|--------|:-----------------:|------------------------------------------------------| +| ------ | :---------------: | ---------------------------------------------------- | | API | `api::` | Represent a resource present in the `` API | | Plugin | `plugin::` | Represent a resource present in the `` plugin | @@ -57,7 +57,7 @@ These namespaces are used as a simple prefix and define the origin of a resource Strapi uses three of them to create UIDs | Name | Definition | Description | -|--------|:----------:|-------------------------------------------------------------------------------| +| ------ | :--------: | ----------------------------------------------------------------------------- | | Strapi | `strapi` | Represent a resource present in the core of strapi | | Admin | `admin` | Represent a resource present in Strapi admin | | Global | `global` | Rarely used (_e.g. policies or middlewares_), it represents a global resource | @@ -90,7 +90,7 @@ ContentType and Component are referring to both the related schema and entity. ::: | | ContentType | Component | Middleware | Policy | Controller | Service | -|--------------------------|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:| +| ------------------------ | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | | `api::.` | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | `plugin::.` | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | `.` | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | @@ -141,6 +141,7 @@ fetch('api::article.article'); fetch('admin::user'); // ^ this should return a Data.Entity<'admin::user'> ``` + To do that, we'll need the function to be able to provide us with the current `uid` type based on usage. ```typescript @@ -171,14 +172,15 @@ Let's add the possibility to select which fields we want to return for our entit ```typescript import type { UID, Data, Schema } from '@strapi/types'; -declare function fetch< - T extends UID.ContentType, - F extends Schema.AttributeNames ->(uid: T, fields: F[]): Data.ContentType; +declare function fetch>( + uid: T, + fields: F[] +): Data.ContentType; ``` :::tip You may have noticed that we're using the inferred UID type (`T`) to reference both: + - An entity (`Data.Entity`) - A schema (`Schema.AttributeNames`) diff --git a/docs/docs/guides/05-type-system/02-concepts/03-public-registry.mdx b/docs/docs/guides/05-type-system/02-concepts/03-public-registry.mdx index 3ee780a471..572eaaadf2 100644 --- a/docs/docs/guides/05-type-system/02-concepts/03-public-registry.mdx +++ b/docs/docs/guides/05-type-system/02-concepts/03-public-registry.mdx @@ -9,8 +9,8 @@ tags: toc_max_heading_level: 5 --- -import Tabs from '@theme/Tabs' -import TabItem from '@theme/TabItem' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; ### Context @@ -108,6 +108,7 @@ Creating a new registry is as simple as exporting an indexed interface from the Let's declare the content-type schema registry. It should accept: + - Content-type UIDs as keys - Content-type schemas as values @@ -130,7 +131,7 @@ We use low level types to define our index (`Internal`/`Struct`) to keep it as g To define `UID.ContentType`, we extract every key (`Internal.Registry.Keys`) from the public content-type registry (`Public.ContentTypeSchemas`) that matches with the base definition of a content-type UID (`Internal.UID.ContentType`). ```ts title="@strapi/types/uid.ts" -import type { Internal, Public } from '@strapi/types' +import type { Internal, Public } from '@strapi/types'; export type ContentType = Internal.Registry.Keys< Public.ContentTypeSchemas, @@ -151,7 +152,7 @@ Since `UID.ContentType` (`TUID`) is [dynamically built based on actual keys](#ui ::: ```ts title="@strapi/types/schema.ts" -import type { UID, Public } from '@strapi/types' +import type { UID, Public } from '@strapi/types'; export type ContentType = Public.ContentTypeSchemas[TUID]; ``` @@ -172,6 +173,7 @@ Remember to use dynamic type definitions (`UID`, `Data`, `Schema`) and not stati :::info[Reminder] Registries are **indexed**, which means that: + - **When augmented** (_e.g. in users' applications_), they'll return **strongly typed values** that correspond to the defined types. - **When empty** (_e.g. in Strapi codebase_), they'll return **generic low level types** based on their index definition. @@ -183,6 +185,7 @@ Registries are **indexed**, which means that: const uid: UID.ContentType; // ^ 'api::article.article' | 'admin::user' ``` + ```ts @@ -191,6 +194,7 @@ Registries are **indexed**, which means that: const uid: UID.ContentType; // ^ `admin::${string}` | `api::${string}.${string}` | `plugin::${string}.${string}` | `strapi::${string}` ``` + ::: @@ -215,7 +219,7 @@ declare module '@strapi/strapi' { } } } -```` +``` This will force every type that depends on the `Public.ContentTypeSchemas` registry to recognize `'api::article.article'` as the only valid UID and `ApiArticleArticle` the only valid schema. @@ -235,18 +239,20 @@ The process will generate type definitions based on the user application state ( Generate the types once. - ```shell title="my-app/" - yarn strapi ts:generate-types - ``` +```shell title="my-app/" +yarn strapi ts:generate-types +``` + Start the application in dev mode, and generate types on every server restart. Useful when working with the content-type builder. - ```shell title="my-app/" - yarn develop - ``` +```shell title="my-app/" +yarn develop +``` + @@ -277,40 +283,43 @@ declare module '@strapi/strapi' { When coupling everything together, the end result is a TypeScript developer experience automatically adjusted to the current context. + - - ```ts title="my-app/src/index.ts" - export default () => ({ - bootstrap() { - strapi.findOne('ap'); - // ^ TypeScript will autocomplete with "api::article.article" + +```ts title="my-app/src/index.ts" +export default () => ({ + bootstrap() { + strapi.findOne('ap'); + // ^ TypeScript will autocomplete with "api::article.article" - strapi.findOne('ad'); - // ^ TypeScript will autocomplete with "admin::user" + strapi.findOne('ad'); + // ^ TypeScript will autocomplete with "admin::user" - strapi.findOne('api::blog.blog'); - // ^ Error, TypeScript will complain - } - }) - ``` - - - ```ts title="@strapi/strapi/document-service.ts" - import type { UID } from '@strapi/types'; - - export const findOne(uid: TUID) { - // ... + strapi.findOne('api::blog.blog'); + // ^ Error, TypeScript will complain } +}) +``` + + +```ts title="@strapi/strapi/document-service.ts" +import type { UID } from '@strapi/types'; - findOne('admin::foo'); - // ^ Valid, matches 'admin::${string}' +export const findOne(uid: TUID) { + // ... +} - findOne('plugin::bar.bar'); - // ^ Valid, matches 'plugin::${string}.${string}' +findOne('admin::foo'); +// ^ Valid, matches 'admin::${string}' - findOne('baz'); - // ^ Error, does not correspond to any content-type UID format - ``` - +findOne('plugin::bar.bar'); +// ^ Valid, matches 'plugin::${string}.${string}' + +findOne('baz'); +// ^ Error, does not correspond to any content-type UID format +``` + + +