From 2cf4c5af4cd5420a654d6d7fd9d31c941076bfaf Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 28 Feb 2024 10:19:07 -0500 Subject: [PATCH] (chore, internal): move `docs-config` to use local typescript sdk gen (#3047) * docs-config -> local * lint fix * prettier * monorepo lint * prettier ignore * fix * fix compile --------- Co-authored-by: dsinghvi --- .eslintignore | 2 + .pnp.cjs | 45 ++- ...onfig-npm-0.0.76-8592dd5cfc-97fbaacd7a.zip | Bin 337594 -> 0 bytes fern/apis/docs-config/generators.yml | 10 - package.json | 3 +- .../docs-configuration/package.json | 2 +- .../src/ParsedDocsConfiguration.ts | 2 +- .../src/convertColorsConfiguration.ts | 2 +- .../src/parseDocsConfiguration.ts | 28 +- .../docs-configuration/tsconfig.json | 1 + packages/cli/docs-preview/package.json | 2 +- packages/cli/docs-preview/src/previewDocs.ts | 2 +- packages/cli/docs-preview/tsconfig.json | 1 + .../remote-workspace-runner/package.json | 2 +- .../src/publishDocs.ts | 10 +- .../remote-workspace-runner/tsconfig.json | 1 + packages/cli/init/package.json | 2 +- packages/cli/init/src/initializeDocs.ts | 2 +- packages/cli/init/tsconfig.json | 1 + packages/cli/workspace-loader/package.json | 2 +- .../workspace-loader/src/loadDocsWorkspace.ts | 5 +- .../workspace-loader/src/types/Workspace.ts | 2 +- packages/cli/workspace-loader/tsconfig.json | 1 + .../cli/yaml/yaml-migrations/package.json | 2 +- .../docs-config/convertLegacyDocsConfig.ts | 1 + .../docs-config/index.ts | 3 +- .../cli/yaml/yaml-migrations/tsconfig.json | 1 + packages/cli/yaml/yaml-schema/package.json | 2 +- .../src/docsAst/DocsConfigFileAstVisitor.ts | 2 +- .../src/docsAst/validateVersionConfig.ts | 5 +- .../src/docsAst/visitDocsConfigFileAst.ts | 4 +- packages/cli/yaml/yaml-schema/tsconfig.json | 1 + packages/docs-config-sdk/.depcheckrc.json | 1 + packages/docs-config-sdk/.mrlint.json | 11 + packages/docs-config-sdk/.prettierrc.cjs | 1 + .../docs-config-sdk/fern}/definition/api.yml | 0 .../docs-config-sdk/fern}/definition/docs.yml | 37 +- .../docs-config-sdk/fern/fern.config.json | 4 + packages/docs-config-sdk/fern/generators.yml | 13 + packages/docs-config-sdk/jest.config.ts | 1 + packages/docs-config-sdk/package.json | 40 +++ packages/docs-config-sdk/src/index.ts | 4 + packages/docs-config-sdk/src/sdk/api/index.ts | 1 + .../src/sdk/api/resources/docs/index.ts | 1 + .../docs/types/ApiSectionConfiguration.ts | 15 + .../resources/docs/types/AudiencesConfig.ts | 9 + .../api/resources/docs/types/ColorConfig.ts | 7 + .../resources/docs/types/ColorThemedConfig.ts | 8 + .../docs/types/ColorsConfiguration.ts | 10 + .../sdk/api/resources/docs/types/CssConfig.ts | 20 ++ .../resources/docs/types/DocsConfiguration.ts | 25 ++ .../api/resources/docs/types/DocsInstances.ts | 15 + .../docs/types/DocsTypographyConfig.ts | 11 + .../docs/types/EditThisPageConfig.ts | 9 + .../api/resources/docs/types/FontConfig.ts | 23 ++ .../resources/docs/types/FontConfigPath.ts | 7 + .../resources/docs/types/FontConfigVariant.ts | 13 + .../api/resources/docs/types/FontDisplay.ts | 13 + .../sdk/api/resources/docs/types/FontStyle.ts | 10 + .../docs/types/GithubEditThisPageConfig.ts | 12 + .../sdk/api/resources/docs/types/JsConfig.ts | 40 +++ .../resources/docs/types/JsConfigOptions.ts | 7 + .../api/resources/docs/types/JsFileConfig.ts | 7 + .../docs/types/JsFileConfigSettings.ts | 10 + .../resources/docs/types/JsRemoteConfig.ts | 10 + .../resources/docs/types/JsScriptStrategy.ts | 11 + .../api/resources/docs/types/LayoutConfig.ts | 59 ++++ .../resources/docs/types/LinkConfiguration.ts | 8 + .../resources/docs/types/LogoConfiguration.ts | 10 + .../api/resources/docs/types/NavbarLink.ts | 34 ++ .../docs/types/NavbarLinkConfiguration.ts | 9 + .../resources/docs/types/NavigationConfig.ts | 7 + .../resources/docs/types/NavigationItem.ts | 11 + .../resources/docs/types/PageConfiguration.ts | 9 + .../docs/types/SectionConfiguration.ts | 12 + .../docs/types/SidebarOrHeaderPlacement.ts | 10 + .../docs/types/SnippetsConfiguration.ts | 10 + .../sdk/api/resources/docs/types/TabConfig.ts | 9 + .../src/sdk/api/resources/docs/types/TabId.ts | 5 + .../docs/types/TabbedNavigationConfig.ts | 7 + .../docs/types/TabbedNavigationItem.ts | 10 + .../docs/types/UntabbedNavigationConifg.ts | 7 + .../docs/types/VersionAvailability.ts | 12 + .../api/resources/docs/types/VersionConfig.ts | 15 + .../resources/docs/types/VersionFileConfig.ts | 9 + .../src/sdk/api/resources/docs/types/index.ts | 41 +++ .../src/sdk/api/resources/index.ts | 2 + .../docs-config-sdk/src/sdk/core/index.ts | 1 + .../src/sdk/core/schemas/Schema.ts | 94 +++++ .../sdk/core/schemas/builders/date/date.ts | 65 ++++ .../sdk/core/schemas/builders/date/index.ts | 1 + .../sdk/core/schemas/builders/enum/enum.ts | 43 +++ .../sdk/core/schemas/builders/enum/index.ts | 1 + .../src/sdk/core/schemas/builders/index.ts | 13 + .../sdk/core/schemas/builders/lazy/index.ts | 3 + .../sdk/core/schemas/builders/lazy/lazy.ts | 34 ++ .../core/schemas/builders/lazy/lazyObject.ts | 20 ++ .../sdk/core/schemas/builders/list/index.ts | 1 + .../sdk/core/schemas/builders/list/list.ts | 74 ++++ .../builders/literals/booleanLiteral.ts | 29 ++ .../core/schemas/builders/literals/index.ts | 2 + .../builders/literals/stringLiteral.ts | 29 ++ .../object-like/getObjectLikeUtils.ts | 79 +++++ .../schemas/builders/object-like/index.ts | 2 + .../schemas/builders/object-like/types.ts | 11 + .../sdk/core/schemas/builders/object/index.ts | 22 ++ .../core/schemas/builders/object/object.ts | 333 ++++++++++++++++++ .../object/objectWithoutOptionalProperties.ts | 18 + .../core/schemas/builders/object/property.ts | 23 ++ .../sdk/core/schemas/builders/object/types.ts | 72 ++++ .../core/schemas/builders/primitives/any.ts | 4 + .../schemas/builders/primitives/boolean.ts | 25 ++ .../core/schemas/builders/primitives/index.ts | 5 + .../schemas/builders/primitives/number.ts | 25 ++ .../schemas/builders/primitives/string.ts | 25 ++ .../schemas/builders/primitives/unknown.ts | 4 + .../sdk/core/schemas/builders/record/index.ts | 2 + .../core/schemas/builders/record/record.ts | 131 +++++++ .../sdk/core/schemas/builders/record/types.ts | 17 + .../builders/schema-utils/JsonError.ts | 9 + .../builders/schema-utils/ParseError.ts | 9 + .../builders/schema-utils/getSchemaUtils.ts | 99 ++++++ .../schemas/builders/schema-utils/index.ts | 4 + .../schema-utils/stringifyValidationErrors.ts | 8 + .../sdk/core/schemas/builders/set/index.ts | 1 + .../src/sdk/core/schemas/builders/set/set.ts | 43 +++ .../builders/undiscriminated-union/index.ts | 6 + .../builders/undiscriminated-union/types.ts | 10 + .../undiscriminatedUnion.ts | 61 ++++ .../schemas/builders/union/discriminant.ts | 14 + .../sdk/core/schemas/builders/union/index.ts | 10 + .../sdk/core/schemas/builders/union/types.ts | 26 ++ .../sdk/core/schemas/builders/union/union.ts | 173 +++++++++ .../src/sdk/core/schemas/index.ts | 2 + .../sdk/core/schemas/utils/MaybePromise.ts | 1 + .../addQuestionMarksToNullableProperties.ts | 15 + .../utils/createIdentitySchemaCreator.ts | 21 ++ .../src/sdk/core/schemas/utils/entries.ts | 3 + .../sdk/core/schemas/utils/filterObject.ts | 10 + .../utils/getErrorMessageForIncorrectType.ts | 21 ++ .../sdk/core/schemas/utils/isPlainObject.ts | 17 + .../src/sdk/core/schemas/utils/keys.ts | 3 + .../core/schemas/utils/maybeSkipValidation.ts | 39 ++ .../src/sdk/core/schemas/utils/partition.ts | 12 + .../src/sdk/errors/FernDocsConfigError.ts | 45 +++ .../sdk/errors/FernDocsConfigTimeoutError.ts | 10 + .../docs-config-sdk/src/sdk/errors/index.ts | 2 + packages/docs-config-sdk/src/sdk/index.ts | 2 + .../src/sdk/serialization/index.ts | 1 + .../sdk/serialization/resources/docs/index.ts | 1 + .../docs/types/ApiSectionConfiguration.ts | 28 ++ .../resources/docs/types/AudiencesConfig.ts | 19 + .../resources/docs/types/ColorConfig.ts | 17 + .../resources/docs/types/ColorThemedConfig.ts | 22 ++ .../docs/types/ColorsConfiguration.ts | 22 ++ .../resources/docs/types/CssConfig.ts | 17 + .../resources/docs/types/DocsConfiguration.ts | 58 +++ .../resources/docs/types/DocsInstances.ts | 31 ++ .../docs/types/DocsTypographyConfig.ts | 24 ++ .../docs/types/EditThisPageConfig.ts | 20 ++ .../resources/docs/types/FontConfig.ts | 37 ++ .../resources/docs/types/FontConfigPath.ts | 17 + .../resources/docs/types/FontConfigVariant.ts | 24 ++ .../resources/docs/types/FontDisplay.ts | 14 + .../resources/docs/types/FontStyle.ts | 14 + .../docs/types/GithubEditThisPageConfig.ts | 26 ++ .../resources/docs/types/JsConfig.ts | 17 + .../resources/docs/types/JsConfigOptions.ts | 19 + .../resources/docs/types/JsFileConfig.ts | 17 + .../docs/types/JsFileConfigSettings.ts | 22 ++ .../resources/docs/types/JsRemoteConfig.ts | 22 ++ .../resources/docs/types/JsScriptStrategy.ts | 16 + .../resources/docs/types/LayoutConfig.ts | 34 ++ .../resources/docs/types/LinkConfiguration.ts | 22 ++ .../resources/docs/types/LogoConfiguration.ts | 26 ++ .../resources/docs/types/NavbarLink.ts | 45 +++ .../docs/types/NavbarLinkConfiguration.ts | 24 ++ .../resources/docs/types/NavigationConfig.ts | 19 + .../resources/docs/types/NavigationItem.ts | 23 ++ .../resources/docs/types/PageConfiguration.ts | 24 ++ .../docs/types/SectionConfiguration.ts | 26 ++ .../docs/types/SidebarOrHeaderPlacement.ts | 16 + .../docs/types/SnippetsConfiguration.ts | 26 ++ .../resources/docs/types/TabConfig.ts | 22 ++ .../resources/docs/types/TabId.ts | 14 + .../docs/types/TabbedNavigationConfig.ts | 16 + .../docs/types/TabbedNavigationItem.ts | 22 ++ .../docs/types/UntabbedNavigationConifg.ts | 16 + .../docs/types/VersionAvailability.ts | 16 + .../resources/docs/types/VersionConfig.ts | 26 ++ .../resources/docs/types/VersionFileConfig.ts | 20 ++ .../resources/docs/types/index.ts | 41 +++ .../src/sdk/serialization/resources/index.ts | 2 + packages/docs-config-sdk/tsconfig.json | 5 + shared/.prettierignore | 1 + yarn.lock | 36 +- 196 files changed, 3674 insertions(+), 88 deletions(-) delete mode 100644 .yarn/cache/@fern-fern-docs-config-npm-0.0.76-8592dd5cfc-97fbaacd7a.zip delete mode 100644 fern/apis/docs-config/generators.yml create mode 100644 packages/docs-config-sdk/.depcheckrc.json create mode 100644 packages/docs-config-sdk/.mrlint.json create mode 100644 packages/docs-config-sdk/.prettierrc.cjs rename {fern/apis/docs-config => packages/docs-config-sdk/fern}/definition/api.yml (100%) rename {fern/apis/docs-config => packages/docs-config-sdk/fern}/definition/docs.yml (92%) create mode 100644 packages/docs-config-sdk/fern/fern.config.json create mode 100644 packages/docs-config-sdk/fern/generators.yml create mode 100644 packages/docs-config-sdk/jest.config.ts create mode 100644 packages/docs-config-sdk/package.json create mode 100644 packages/docs-config-sdk/src/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/ApiSectionConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/AudiencesConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorThemedConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorsConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/CssConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsInstances.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsTypographyConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/EditThisPageConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfigPath.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfigVariant.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontDisplay.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontStyle.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/GithubEditThisPageConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsConfigOptions.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsFileConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsFileConfigSettings.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsRemoteConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsScriptStrategy.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/LayoutConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/LinkConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/LogoConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavbarLink.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavbarLinkConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavigationConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavigationItem.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/PageConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/SectionConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/SidebarOrHeaderPlacement.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/SnippetsConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabId.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabbedNavigationConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabbedNavigationItem.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/UntabbedNavigationConifg.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionAvailability.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionFileConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/docs/types/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/api/resources/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/Schema.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/date/date.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/date/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/enum/enum.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/enum/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/lazy.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/lazyObject.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/list/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/list/list.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/booleanLiteral.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/stringLiteral.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/getObjectLikeUtils.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/types.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/object/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/object/object.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/object/objectWithoutOptionalProperties.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/object/property.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/object/types.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/any.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/boolean.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/number.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/string.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/unknown.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/record/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/record/record.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/record/types.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/JsonError.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/ParseError.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/getSchemaUtils.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/stringifyValidationErrors.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/set/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/set/set.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/types.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/undiscriminatedUnion.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/union/discriminant.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/union/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/union/types.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/builders/union/union.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/utils/MaybePromise.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/utils/addQuestionMarksToNullableProperties.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/utils/createIdentitySchemaCreator.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/utils/entries.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/utils/filterObject.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/utils/getErrorMessageForIncorrectType.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/utils/isPlainObject.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/utils/keys.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/utils/maybeSkipValidation.ts create mode 100644 packages/docs-config-sdk/src/sdk/core/schemas/utils/partition.ts create mode 100644 packages/docs-config-sdk/src/sdk/errors/FernDocsConfigError.ts create mode 100644 packages/docs-config-sdk/src/sdk/errors/FernDocsConfigTimeoutError.ts create mode 100644 packages/docs-config-sdk/src/sdk/errors/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ApiSectionConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/AudiencesConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorThemedConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorsConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/CssConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsInstances.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsTypographyConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/EditThisPageConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfigPath.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfigVariant.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontDisplay.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontStyle.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/GithubEditThisPageConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsConfigOptions.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsFileConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsFileConfigSettings.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsRemoteConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsScriptStrategy.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LayoutConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LinkConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LogoConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavbarLink.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavbarLinkConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavigationConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavigationItem.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/PageConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SectionConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SidebarOrHeaderPlacement.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SnippetsConfiguration.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabId.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabbedNavigationConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabbedNavigationItem.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/UntabbedNavigationConifg.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionAvailability.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionFileConfig.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/index.ts create mode 100644 packages/docs-config-sdk/src/sdk/serialization/resources/index.ts create mode 100644 packages/docs-config-sdk/tsconfig.json diff --git a/.eslintignore b/.eslintignore index 384d29af16f..8cedbfe4b0d 100644 --- a/.eslintignore +++ b/.eslintignore @@ -7,7 +7,9 @@ generated bundle.c?js .pnp* packages/ir-sdk/** +packages/docs-config/** packages/cli/openapi-ir-sdk/** +packages/docs-config-sdk/** packages/seed/** generators/typescript/utils/core-utilities/** seed/** diff --git a/.pnp.cjs b/.pnp.cjs index 531b3091dda..254a24a75d3 100644 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -375,6 +375,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "name": "@fern-api/core",\ "reference": "workspace:packages/core"\ },\ + {\ + "name": "@fern-api/docs-config-sdk",\ + "reference": "workspace:packages/docs-config-sdk"\ + },\ {\ "name": "@fern-api/generator-commons",\ "reference": "workspace:packages/generators/commons"\ @@ -405,6 +409,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fern-api/csharp-generator-cli", ["workspace:generators/csharp/cli"]],\ ["@fern-api/dependencies-configuration", ["workspace:packages/cli/config-management/dependencies-configuration"]],\ ["@fern-api/docker-utils", ["workspace:packages/cli/generation/local-generation/docker-utils"]],\ + ["@fern-api/docs-config-sdk", ["workspace:packages/docs-config-sdk"]],\ ["@fern-api/docs-configuration", ["workspace:packages/cli/config-management/docs-configuration"]],\ ["@fern-api/docs-preview", ["workspace:packages/cli/docs-preview"]],\ ["@fern-api/docs-validator", ["workspace:packages/cli/yaml/docs-validator"]],\ @@ -4693,6 +4698,23 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "SOFT"\ }]\ ]],\ + ["@fern-api/docs-config-sdk", [\ + ["workspace:packages/docs-config-sdk", {\ + "packageLocation": "./packages/docs-config-sdk/",\ + "packageDependencies": [\ + ["@fern-api/docs-config-sdk", "workspace:packages/docs-config-sdk"],\ + ["@types/jest", "npm:29.0.3"],\ + ["@types/node", "npm:18.7.18"],\ + ["depcheck", "npm:1.4.6"],\ + ["eslint", "npm:8.56.0"],\ + ["jest", "virtual:f8e21c9fa0a798b21a87ac455600e39198fef65848556a3a2cd5c956b0460181f9e618173dcff6d9d4fb96fb870055dfe1a3ec3db5db0700e71c0184e4711659#npm:29.7.0"],\ + ["organize-imports-cli", "npm:0.10.0"],\ + ["prettier", "npm:2.7.1"],\ + ["typescript", "patch:typescript@npm%3A4.6.4#~builtin::version=4.6.4&hash=5d3a66"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ ["@fern-api/docs-configuration", [\ ["workspace:packages/cli/config-management/docs-configuration", {\ "packageLocation": "./packages/cli/config-management/docs-configuration/",\ @@ -4700,10 +4722,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fern-api/docs-configuration", "workspace:packages/cli/config-management/docs-configuration"],\ ["@fern-api/config-management-commons", "workspace:packages/cli/config-management/commons"],\ ["@fern-api/core-utils", "workspace:packages/commons/core-utils"],\ + ["@fern-api/docs-config-sdk", "workspace:packages/docs-config-sdk"],\ ["@fern-api/fdr-sdk", "npm:0.50.8-1-gace1ff5"],\ ["@fern-api/fs-utils", "workspace:packages/commons/fs-utils"],\ ["@fern-api/task-context", "workspace:packages/cli/task-context"],\ - ["@fern-fern/docs-config", "npm:0.0.76"],\ ["@types/jest", "npm:29.0.3"],\ ["@types/js-yaml", "npm:4.0.8"],\ ["@types/node", "npm:18.7.18"],\ @@ -4726,6 +4748,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [\ ["@fern-api/docs-preview", "workspace:packages/cli/docs-preview"],\ ["@fern-api/core-utils", "workspace:packages/commons/core-utils"],\ + ["@fern-api/docs-config-sdk", "workspace:packages/docs-config-sdk"],\ ["@fern-api/docs-configuration", "workspace:packages/cli/config-management/docs-configuration"],\ ["@fern-api/fdr-sdk", "npm:0.50.8-1-gace1ff5"],\ ["@fern-api/fs-utils", "workspace:packages/commons/fs-utils"],\ @@ -4733,7 +4756,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fern-api/register", "workspace:packages/cli/register"],\ ["@fern-api/task-context", "workspace:packages/cli/task-context"],\ ["@fern-api/workspace-loader", "workspace:packages/cli/workspace-loader"],\ - ["@fern-fern/docs-config", "npm:0.0.76"],\ ["@types/cors", "npm:2.8.17"],\ ["@types/express", "npm:4.17.20"],\ ["@types/jest", "npm:29.0.3"],\ @@ -5006,6 +5028,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fern-api/init", "workspace:packages/cli/init"],\ ["@fern-api/auth", "workspace:packages/cli/auth"],\ ["@fern-api/core", "workspace:packages/core"],\ + ["@fern-api/docs-config-sdk", "workspace:packages/docs-config-sdk"],\ ["@fern-api/fs-utils", "workspace:packages/commons/fs-utils"],\ ["@fern-api/generators-configuration", "workspace:packages/cli/config-management/generators-configuration"],\ ["@fern-api/login", "workspace:packages/cli/login"],\ @@ -5013,7 +5036,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fern-api/task-context", "workspace:packages/cli/task-context"],\ ["@fern-api/yaml-formatter", "workspace:packages/cli/yaml/formatter"],\ ["@fern-api/yaml-schema", "workspace:packages/cli/yaml/yaml-schema"],\ - ["@fern-fern/docs-config", "npm:0.0.76"],\ ["@types/fs-extra", "npm:11.0.1"],\ ["@types/jest", "npm:29.0.3"],\ ["@types/js-yaml", "npm:4.0.8"],\ @@ -5580,6 +5602,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fern-api/config-management-commons", "workspace:packages/cli/config-management/commons"],\ ["@fern-api/core", "workspace:packages/core"],\ ["@fern-api/core-utils", "workspace:packages/commons/core-utils"],\ + ["@fern-api/docs-config-sdk", "workspace:packages/docs-config-sdk"],\ ["@fern-api/docs-configuration", "workspace:packages/cli/config-management/docs-configuration"],\ ["@fern-api/fdr-sdk", "npm:0.50.8-1-gace1ff5"],\ ["@fern-api/fs-utils", "workspace:packages/commons/fs-utils"],\ @@ -5591,7 +5614,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fern-api/register", "workspace:packages/cli/register"],\ ["@fern-api/task-context", "workspace:packages/cli/task-context"],\ ["@fern-api/workspace-loader", "workspace:packages/cli/workspace-loader"],\ - ["@fern-fern/docs-config", "npm:0.0.76"],\ ["@fern-fern/fiddle-sdk", "npm:0.0.411"],\ ["@types/decompress", "npm:4.2.7"],\ ["@types/jest", "npm:29.0.3"],\ @@ -5837,6 +5859,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fern-api/core", "workspace:packages/core"],\ ["@fern-api/core-utils", "workspace:packages/commons/core-utils"],\ ["@fern-api/dependencies-configuration", "workspace:packages/cli/config-management/dependencies-configuration"],\ + ["@fern-api/docs-config-sdk", "workspace:packages/docs-config-sdk"],\ ["@fern-api/fs-utils", "workspace:packages/commons/fs-utils"],\ ["@fern-api/generators-configuration", "workspace:packages/cli/config-management/generators-configuration"],\ ["@fern-api/openapi-ir-sdk", "workspace:packages/cli/openapi-ir-sdk"],\ @@ -5846,7 +5869,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fern-api/semver-utils", "workspace:packages/cli/semver-utils"],\ ["@fern-api/task-context", "workspace:packages/cli/task-context"],\ ["@fern-api/yaml-schema", "workspace:packages/cli/yaml/yaml-schema"],\ - ["@fern-fern/docs-config", "npm:0.0.76"],\ ["@fern-fern/fiddle-sdk", "npm:0.0.411"],\ ["@types/jest", "npm:29.0.3"],\ ["@types/js-yaml", "npm:4.0.8"],\ @@ -5902,10 +5924,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@fern-api/yaml-migrations", "workspace:packages/cli/yaml/yaml-migrations"],\ ["@fern-api/config-management-commons", "workspace:packages/cli/config-management/commons"],\ ["@fern-api/core-utils", "workspace:packages/commons/core-utils"],\ + ["@fern-api/docs-config-sdk", "workspace:packages/docs-config-sdk"],\ ["@fern-api/fs-utils", "workspace:packages/commons/fs-utils"],\ ["@fern-api/semver-utils", "workspace:packages/cli/semver-utils"],\ ["@fern-api/task-context", "workspace:packages/cli/task-context"],\ - ["@fern-fern/docs-config", "npm:0.0.76"],\ ["@fern-fern/legacy-docs-config", "npm:0.0.58"],\ ["@types/inquirer", "npm:9.0.3"],\ ["@types/jest", "npm:29.0.3"],\ @@ -5936,9 +5958,9 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [\ ["@fern-api/yaml-schema", "workspace:packages/cli/yaml/yaml-schema"],\ ["@fern-api/core-utils", "workspace:packages/commons/core-utils"],\ + ["@fern-api/docs-config-sdk", "workspace:packages/docs-config-sdk"],\ ["@fern-api/fs-utils", "workspace:packages/commons/fs-utils"],\ ["@fern-api/ir-sdk", "workspace:packages/ir-sdk"],\ - ["@fern-fern/docs-config", "npm:0.0.76"],\ ["@types/jest", "npm:29.0.3"],\ ["@types/js-yaml", "npm:4.0.8"],\ ["@types/node", "npm:18.7.18"],\ @@ -5954,15 +5976,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "SOFT"\ }]\ ]],\ - ["@fern-fern/docs-config", [\ - ["npm:0.0.76", {\ - "packageLocation": "./.yarn/cache/@fern-fern-docs-config-npm-0.0.76-8592dd5cfc-97fbaacd7a.zip/node_modules/@fern-fern/docs-config/",\ - "packageDependencies": [\ - ["@fern-fern/docs-config", "npm:0.0.76"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@fern-fern/fiddle-sdk", [\ ["npm:0.0.411", {\ "packageLocation": "./.yarn/cache/@fern-fern-fiddle-sdk-npm-0.0.411-58ecea0710-8c4243eaa7.zip/node_modules/@fern-fern/fiddle-sdk/",\ diff --git a/.yarn/cache/@fern-fern-docs-config-npm-0.0.76-8592dd5cfc-97fbaacd7a.zip b/.yarn/cache/@fern-fern-docs-config-npm-0.0.76-8592dd5cfc-97fbaacd7a.zip deleted file mode 100644 index 2f4b7731d30407acaa232b0c6c625f7794764034..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 337594 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 = { [K in keyof Required]: undefined extends T[K] ? T[K] | undefined : T[K]; diff --git a/packages/cli/config-management/docs-configuration/src/convertColorsConfiguration.ts b/packages/cli/config-management/docs-configuration/src/convertColorsConfiguration.ts index 03fb6520b0b..492de6a52f4 100644 --- a/packages/cli/config-management/docs-configuration/src/convertColorsConfiguration.ts +++ b/packages/cli/config-management/docs-configuration/src/convertColorsConfiguration.ts @@ -1,7 +1,7 @@ import { assertNever } from "@fern-api/core-utils"; +import { FernDocsConfig as RawDocs } from "@fern-api/docs-config-sdk"; import { DocsV1Write } from "@fern-api/fdr-sdk"; import { TaskContext } from "@fern-api/task-context"; -import { FernDocsConfig as RawDocs } from "@fern-fern/docs-config"; import tinycolor from "tinycolor2"; export function convertColorsConfiguration( diff --git a/packages/cli/config-management/docs-configuration/src/parseDocsConfiguration.ts b/packages/cli/config-management/docs-configuration/src/parseDocsConfiguration.ts index 9c6be12a8f4..d9cce6674aa 100644 --- a/packages/cli/config-management/docs-configuration/src/parseDocsConfiguration.ts +++ b/packages/cli/config-management/docs-configuration/src/parseDocsConfiguration.ts @@ -1,10 +1,8 @@ import { assertNever } from "@fern-api/core-utils"; +import { FernDocsConfig as RawDocs, NavigationConfig, Serializer, VersionConfig } from "@fern-api/docs-config-sdk"; import { DocsV1Write } from "@fern-api/fdr-sdk"; import { AbsoluteFilePath, dirname, resolve } from "@fern-api/fs-utils"; import { TaskContext } from "@fern-api/task-context"; -import { FernDocsConfig as RawDocs } from "@fern-fern/docs-config"; -import { NavigationConfig, VersionConfig } from "@fern-fern/docs-config/api"; -import { VersionFileConfig as RawVersionFileConfigSerializer } from "@fern-fern/docs-config/serialization"; import { readFile } from "fs/promises"; import yaml from "js-yaml"; import { convertColorsConfiguration } from "./convertColorsConfiguration"; @@ -130,8 +128,18 @@ export async function parseDocsConfiguration({ logo, favicon, backgroundImage, - colors: convertColorsConfiguration(colors ?? {}, context), - navbarLinks, + colors: convertColorsConfiguration( + colors ?? { + accentPrimary: undefined, + background: undefined + }, + context + ), + navbarLinks: navbarLinks?.map((navbarLink) => ({ + type: navbarLink.type, + text: navbarLink.text, + url: navbarLink.href ?? navbarLink.url ?? "/" + })), typography, layout: convertLayoutConfig(layout), css, @@ -164,7 +172,7 @@ async function convertCssConfig( function isRemoteJsConfig( config: RawDocs.JsRemoteConfig | RawDocs.JsFileConfigSettings -): config is DocsV1Write.JsRemoteConfig { +): config is RawDocs.JsRemoteConfig { return Object.hasOwn(config, "url"); } @@ -284,7 +292,7 @@ async function getNavigationConfiguration({ for (const version of versions) { const absoluteFilepathToVersionFile = resolve(absolutePathToFernFolder, version.path); const content = yaml.load((await readFile(absoluteFilepathToVersionFile)).toString()); - const result = await RawVersionFileConfigSerializer.parseOrThrow(content); + const result = await Serializer.VersionFileConfig.parseOrThrow(content); const navigation = await convertNavigationConfiguration({ rawNavigationConfig: result.navigation, absolutePathToFernFolder, @@ -506,8 +514,8 @@ async function convertNavigationItem({ if (isRawLinkConfig(rawConfig)) { return { type: "link", - text: rawConfig.text, - url: rawConfig.url + text: rawConfig.link, + url: rawConfig.href }; } assertNever(rawConfig); @@ -543,7 +551,7 @@ function isRawApiSectionConfig(item: RawDocs.NavigationItem): item is RawDocs.Ap function isRawLinkConfig(item: RawDocs.NavigationItem): item is RawDocs.LinkConfiguration { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - return (item as RawDocs.LinkConfiguration).url != null; + return (item as RawDocs.LinkConfiguration).link != null; } async function convertImageReference({ diff --git a/packages/cli/config-management/docs-configuration/tsconfig.json b/packages/cli/config-management/docs-configuration/tsconfig.json index 058bd0b0e6d..6f6bd4eaa05 100644 --- a/packages/cli/config-management/docs-configuration/tsconfig.json +++ b/packages/cli/config-management/docs-configuration/tsconfig.json @@ -5,6 +5,7 @@ "references": [ { "path": "../../../commons/core-utils" }, { "path": "../../../commons/fs-utils" }, + { "path": "../../../docs-config-sdk" }, { "path": "../../task-context" }, { "path": "../commons" } ] diff --git a/packages/cli/docs-preview/package.json b/packages/cli/docs-preview/package.json index c5cb0685972..e3670508462 100644 --- a/packages/cli/docs-preview/package.json +++ b/packages/cli/docs-preview/package.json @@ -28,6 +28,7 @@ }, "dependencies": { "@fern-api/core-utils": "workspace:*", + "@fern-api/docs-config-sdk": "workspace:*", "@fern-api/docs-configuration": "workspace:*", "@fern-api/fdr-sdk": "0.50.8-1-gace1ff5", "@fern-api/fs-utils": "workspace:*", @@ -35,7 +36,6 @@ "@fern-api/register": "workspace:*", "@fern-api/task-context": "workspace:*", "@fern-api/workspace-loader": "workspace:*", - "@fern-fern/docs-config": "0.0.76", "cors": "^2.8.5", "express": "^4.18.2", "uuid": "^9.0.1" diff --git a/packages/cli/docs-preview/src/previewDocs.ts b/packages/cli/docs-preview/src/previewDocs.ts index 3d4656fb66a..37faf3737d2 100644 --- a/packages/cli/docs-preview/src/previewDocs.ts +++ b/packages/cli/docs-preview/src/previewDocs.ts @@ -1,4 +1,5 @@ import { assertNever, entries } from "@fern-api/core-utils"; +import { TabConfig, VersionAvailability } from "@fern-api/docs-config-sdk"; import { DocsNavigationConfiguration, DocsNavigationItem, @@ -22,7 +23,6 @@ import { generateIntermediateRepresentation } from "@fern-api/ir-generator"; import { convertIrToFdrApi } from "@fern-api/register"; import { TaskContext } from "@fern-api/task-context"; import { APIWorkspace, convertOpenApiWorkspaceToFernWorkspace, DocsWorkspace } from "@fern-api/workspace-loader"; -import { TabConfig, VersionAvailability } from "@fern-fern/docs-config/api"; import { v4 as uuidv4 } from "uuid"; export async function getPreviewDocsDefinition({ diff --git a/packages/cli/docs-preview/tsconfig.json b/packages/cli/docs-preview/tsconfig.json index 6e239a9e54a..e681d616908 100644 --- a/packages/cli/docs-preview/tsconfig.json +++ b/packages/cli/docs-preview/tsconfig.json @@ -5,6 +5,7 @@ "references": [ { "path": "../../commons/core-utils" }, { "path": "../../commons/fs-utils" }, + { "path": "../../docs-config-sdk" }, { "path": "../config-management/docs-configuration" }, { "path": "../generation/ir-generator" }, { "path": "../register" }, diff --git a/packages/cli/generation/remote-generation/remote-workspace-runner/package.json b/packages/cli/generation/remote-generation/remote-workspace-runner/package.json index 93991be4a07..82e772626e4 100644 --- a/packages/cli/generation/remote-generation/remote-workspace-runner/package.json +++ b/packages/cli/generation/remote-generation/remote-workspace-runner/package.json @@ -31,6 +31,7 @@ "@fern-api/config-management-commons": "workspace:*", "@fern-api/core": "workspace:*", "@fern-api/core-utils": "workspace:*", + "@fern-api/docs-config-sdk": "workspace:*", "@fern-api/docs-configuration": "workspace:*", "@fern-api/fdr-sdk": "0.50.8-1-gace1ff5", "@fern-api/fs-utils": "workspace:*", @@ -42,7 +43,6 @@ "@fern-api/register": "workspace:*", "@fern-api/task-context": "workspace:*", "@fern-api/workspace-loader": "workspace:*", - "@fern-fern/docs-config": "0.0.76", "@fern-fern/fiddle-sdk": "^0.0.411", "axios": "^0.28.0", "chalk": "^5.0.1", diff --git a/packages/cli/generation/remote-generation/remote-workspace-runner/src/publishDocs.ts b/packages/cli/generation/remote-generation/remote-workspace-runner/src/publishDocs.ts index af5ab667c0f..a64093e49c0 100644 --- a/packages/cli/generation/remote-generation/remote-workspace-runner/src/publishDocs.ts +++ b/packages/cli/generation/remote-generation/remote-workspace-runner/src/publishDocs.ts @@ -1,6 +1,7 @@ import { FernToken } from "@fern-api/auth"; import { createFdrService } from "@fern-api/core"; import { assertNever, entries, isNonNullish } from "@fern-api/core-utils"; +import { FernDocsConfig, SnippetsConfiguration, TabConfig, VersionAvailability } from "@fern-api/docs-config-sdk"; import { DocsNavigationConfiguration, DocsNavigationItem, @@ -18,8 +19,6 @@ import { AbsoluteFilePath, dirname, relative } from "@fern-api/fs-utils"; import { registerApi } from "@fern-api/register"; import { TaskContext } from "@fern-api/task-context"; import { DocsWorkspace, FernWorkspace } from "@fern-api/workspace-loader"; -import { FernDocsConfig } from "@fern-fern/docs-config"; -import { SnippetsConfiguration, TabConfig, VersionAvailability } from "@fern-fern/docs-config/api"; import axios from "axios"; import chalk from "chalk"; import { readFile } from "fs/promises"; @@ -693,7 +692,12 @@ async function convertNavigationItem({ token, audiences: item.audiences, snippetsConfig: convertDocsSnippetsConfigurationToFdr({ - snippetsConfiguration: item.snippetsConfiguration ?? {} + snippetsConfiguration: item.snippetsConfiguration ?? { + python: undefined, + typescript: undefined, + go: undefined, + java: undefined + } }) }); return { diff --git a/packages/cli/generation/remote-generation/remote-workspace-runner/tsconfig.json b/packages/cli/generation/remote-generation/remote-workspace-runner/tsconfig.json index 7fcba19c56b..828cfa40832 100644 --- a/packages/cli/generation/remote-generation/remote-workspace-runner/tsconfig.json +++ b/packages/cli/generation/remote-generation/remote-workspace-runner/tsconfig.json @@ -6,6 +6,7 @@ { "path": "../../../../commons/core-utils" }, { "path": "../../../../commons/fs-utils" }, { "path": "../../../../core" }, + { "path": "../../../../docs-config-sdk" }, { "path": "../../../../ir-sdk" }, { "path": "../../../auth" }, { "path": "../../../config-management/commons" }, diff --git a/packages/cli/init/package.json b/packages/cli/init/package.json index 26d900fac90..7f926f85864 100644 --- a/packages/cli/init/package.json +++ b/packages/cli/init/package.json @@ -29,6 +29,7 @@ "dependencies": { "@fern-api/auth": "workspace:*", "@fern-api/core": "workspace:*", + "@fern-api/docs-config-sdk": "workspace:*", "@fern-api/fs-utils": "workspace:*", "@fern-api/generators-configuration": "workspace:*", "@fern-api/login": "workspace:*", @@ -36,7 +37,6 @@ "@fern-api/task-context": "workspace:*", "@fern-api/yaml-formatter": "workspace:*", "@fern-api/yaml-schema": "workspace:*", - "@fern-fern/docs-config": "0.0.76", "axios": "^0.28.0", "chalk": "^5.0.1", "fs-extra": "^11.1.1", diff --git a/packages/cli/init/src/initializeDocs.ts b/packages/cli/init/src/initializeDocs.ts index b357d1f4bfd..fe4f6fb12ec 100644 --- a/packages/cli/init/src/initializeDocs.ts +++ b/packages/cli/init/src/initializeDocs.ts @@ -1,7 +1,7 @@ +import { FernDocsConfig as RawDocs } from "@fern-api/docs-config-sdk"; import { join, RelativeFilePath } from "@fern-api/fs-utils"; import { DOCS_CONFIGURATION_FILENAME } from "@fern-api/project-configuration"; import { TaskContext } from "@fern-api/task-context"; -import { FernDocsConfig as RawDocs } from "@fern-fern/docs-config"; import { writeFile } from "fs/promises"; import yaml from "js-yaml"; import { createFernDirectoryAndWorkspace } from "./createFernDirectoryAndOrganization"; diff --git a/packages/cli/init/tsconfig.json b/packages/cli/init/tsconfig.json index db82e7bf0de..417c56bfe07 100644 --- a/packages/cli/init/tsconfig.json +++ b/packages/cli/init/tsconfig.json @@ -5,6 +5,7 @@ "references": [ { "path": "../../commons/fs-utils" }, { "path": "../../core" }, + { "path": "../../docs-config-sdk" }, { "path": "../auth" }, { "path": "../config-management/generators-configuration" }, { "path": "../config-management/project-configuration" }, diff --git a/packages/cli/workspace-loader/package.json b/packages/cli/workspace-loader/package.json index 58567f2939f..d86f6aa3a8e 100644 --- a/packages/cli/workspace-loader/package.json +++ b/packages/cli/workspace-loader/package.json @@ -30,6 +30,7 @@ "@fern-api/core": "workspace:*", "@fern-api/core-utils": "workspace:*", "@fern-api/dependencies-configuration": "workspace:*", + "@fern-api/docs-config-sdk": "workspace:*", "@fern-api/fs-utils": "workspace:*", "@fern-api/generators-configuration": "workspace:*", "@fern-api/openapi-ir-sdk": "workspace:*", @@ -39,7 +40,6 @@ "@fern-api/semver-utils": "workspace:*", "@fern-api/task-context": "workspace:*", "@fern-api/yaml-schema": "workspace:*", - "@fern-fern/docs-config": "0.0.76", "@fern-fern/fiddle-sdk": "^0.0.411", "axios": "^0.28.0", "glob": "^8.0.3", diff --git a/packages/cli/workspace-loader/src/loadDocsWorkspace.ts b/packages/cli/workspace-loader/src/loadDocsWorkspace.ts index d161b32e896..208e6d84996 100644 --- a/packages/cli/workspace-loader/src/loadDocsWorkspace.ts +++ b/packages/cli/workspace-loader/src/loadDocsWorkspace.ts @@ -1,9 +1,8 @@ import { addPrefixToString } from "@fern-api/core-utils"; +import { DocsConfiguration, DocsConfiguration as RawDocsConfiguration, Serializer } from "@fern-api/docs-config-sdk"; import { AbsoluteFilePath, doesPathExist, join, RelativeFilePath } from "@fern-api/fs-utils"; import { DOCS_CONFIGURATION_FILENAME } from "@fern-api/project-configuration"; import { TaskContext } from "@fern-api/task-context"; -import { DocsConfiguration, DocsConfiguration as RawDocsConfiguration } from "@fern-fern/docs-config/api"; -import { DocsConfiguration as RawDocsConfigurationSerializer } from "@fern-fern/docs-config/serialization"; import { readFile } from "fs/promises"; import yaml from "js-yaml"; import path from "path"; @@ -82,7 +81,7 @@ export async function validateSchema({ context: TaskContext; filepathBeingParsed: string; }): Promise { - const result = await RawDocsConfigurationSerializer.parse(value); + const result = await Serializer.DocsConfiguration.parse(value); if (result.ok) { return result.value; } diff --git a/packages/cli/workspace-loader/src/types/Workspace.ts b/packages/cli/workspace-loader/src/types/Workspace.ts index c61a393c057..c3a98844826 100644 --- a/packages/cli/workspace-loader/src/types/Workspace.ts +++ b/packages/cli/workspace-loader/src/types/Workspace.ts @@ -1,8 +1,8 @@ import { DependenciesConfiguration } from "@fern-api/dependencies-configuration"; +import { DocsConfiguration } from "@fern-api/docs-config-sdk"; import { AbsoluteFilePath, RelativeFilePath } from "@fern-api/fs-utils"; import { GeneratorsConfiguration } from "@fern-api/generators-configuration"; import { DefinitionFileSchema, PackageMarkerFileSchema, RootApiFileSchema } from "@fern-api/yaml-schema"; -import { DocsConfiguration } from "@fern-fern/docs-config/api"; import { ParsedFernFile } from "./FernFile"; export type Workspace = DocsWorkspace | APIWorkspace; diff --git a/packages/cli/workspace-loader/tsconfig.json b/packages/cli/workspace-loader/tsconfig.json index d594b47bd43..1c7451b0149 100644 --- a/packages/cli/workspace-loader/tsconfig.json +++ b/packages/cli/workspace-loader/tsconfig.json @@ -6,6 +6,7 @@ { "path": "../../commons/core-utils" }, { "path": "../../commons/fs-utils" }, { "path": "../../core" }, + { "path": "../../docs-config-sdk" }, { "path": "../config-management/dependencies-configuration" }, { "path": "../config-management/generators-configuration" }, { "path": "../config-management/project-configuration" }, diff --git a/packages/cli/yaml/yaml-migrations/package.json b/packages/cli/yaml/yaml-migrations/package.json index 80cd6a195ed..14da1acaf9a 100644 --- a/packages/cli/yaml/yaml-migrations/package.json +++ b/packages/cli/yaml/yaml-migrations/package.json @@ -29,10 +29,10 @@ "dependencies": { "@fern-api/config-management-commons": "workspace:*", "@fern-api/core-utils": "workspace:*", + "@fern-api/docs-config-sdk": "workspace:*", "@fern-api/fs-utils": "workspace:*", "@fern-api/semver-utils": "workspace:*", "@fern-api/task-context": "workspace:*", - "@fern-fern/docs-config": "0.0.76", "@fern-fern/legacy-docs-config": "0.0.58", "chalk": "^5.0.1", "find-up": "^6.3.0", diff --git a/packages/cli/yaml/yaml-migrations/src/migrations/0.15.0-rc0/update-directory-structure/docs-config/convertLegacyDocsConfig.ts b/packages/cli/yaml/yaml-migrations/src/migrations/0.15.0-rc0/update-directory-structure/docs-config/convertLegacyDocsConfig.ts index 81e0a1e07a8..c84201d11c3 100644 --- a/packages/cli/yaml/yaml-migrations/src/migrations/0.15.0-rc0/update-directory-structure/docs-config/convertLegacyDocsConfig.ts +++ b/packages/cli/yaml/yaml-migrations/src/migrations/0.15.0-rc0/update-directory-structure/docs-config/convertLegacyDocsConfig.ts @@ -11,6 +11,7 @@ export function convertLegacyDocsConfig({ }): MigratedDocs.DocsConfiguration { return { ...docsConfiguration, + navbarLinks: docsConfiguration.navbarLinks?.map((link) => ({ ...link, href: link.url })), instances: docsURLs, logo: typeof docsConfiguration.logo === "string" ? { dark: docsConfiguration.logo } : docsConfiguration.logo, navigation: diff --git a/packages/cli/yaml/yaml-migrations/src/migrations/0.15.0-rc0/update-directory-structure/docs-config/index.ts b/packages/cli/yaml/yaml-migrations/src/migrations/0.15.0-rc0/update-directory-structure/docs-config/index.ts index 6974e3fa9fd..e704554d954 100644 --- a/packages/cli/yaml/yaml-migrations/src/migrations/0.15.0-rc0/update-directory-structure/docs-config/index.ts +++ b/packages/cli/yaml/yaml-migrations/src/migrations/0.15.0-rc0/update-directory-structure/docs-config/index.ts @@ -1,5 +1,4 @@ -export { FernDocsConfig as MigratedDocs } from "@fern-fern/docs-config"; -export { type DocsInstances as DocsURL } from "@fern-fern/docs-config/api"; +export { FernDocsConfig as MigratedDocs, type DocsInstances as DocsURL } from "@fern-api/docs-config-sdk"; export { FernDocsConfig as LegacyDocs } from "@fern-fern/legacy-docs-config"; export * as LegacyDocsSerializers from "@fern-fern/legacy-docs-config/serialization"; export { diff --git a/packages/cli/yaml/yaml-migrations/tsconfig.json b/packages/cli/yaml/yaml-migrations/tsconfig.json index 484e56d9d3d..6b0e3547c40 100644 --- a/packages/cli/yaml/yaml-migrations/tsconfig.json +++ b/packages/cli/yaml/yaml-migrations/tsconfig.json @@ -5,6 +5,7 @@ "references": [ { "path": "../../../commons/core-utils" }, { "path": "../../../commons/fs-utils" }, + { "path": "../../../docs-config-sdk" }, { "path": "../../config-management/commons" }, { "path": "../../semver-utils" }, { "path": "../../task-context" } diff --git a/packages/cli/yaml/yaml-schema/package.json b/packages/cli/yaml/yaml-schema/package.json index a6d3d6d1b76..1eb08f7d64f 100644 --- a/packages/cli/yaml/yaml-schema/package.json +++ b/packages/cli/yaml/yaml-schema/package.json @@ -28,9 +28,9 @@ }, "dependencies": { "@fern-api/core-utils": "workspace:*", + "@fern-api/docs-config-sdk": "workspace:*", "@fern-api/fs-utils": "workspace:*", "@fern-api/ir-sdk": "workspace:*", - "@fern-fern/docs-config": "0.0.76", "js-yaml": "^4.1.0", "zod": "^3.22.3" }, diff --git a/packages/cli/yaml/yaml-schema/src/docsAst/DocsConfigFileAstVisitor.ts b/packages/cli/yaml/yaml-schema/src/docsAst/DocsConfigFileAstVisitor.ts index c77e149a02d..187621ab770 100644 --- a/packages/cli/yaml/yaml-schema/src/docsAst/DocsConfigFileAstVisitor.ts +++ b/packages/cli/yaml/yaml-schema/src/docsAst/DocsConfigFileAstVisitor.ts @@ -1,5 +1,5 @@ +import { DocsConfiguration } from "@fern-api/docs-config-sdk"; import { AbsoluteFilePath } from "@fern-api/fs-utils"; -import { DocsConfiguration } from "@fern-fern/docs-config/api"; import { NodePath } from "../NodePath"; export type DocsConfigFileAstVisitor> = { diff --git a/packages/cli/yaml/yaml-schema/src/docsAst/validateVersionConfig.ts b/packages/cli/yaml/yaml-schema/src/docsAst/validateVersionConfig.ts index 5d0a0e98c54..9ebcb8b5c48 100644 --- a/packages/cli/yaml/yaml-schema/src/docsAst/validateVersionConfig.ts +++ b/packages/cli/yaml/yaml-schema/src/docsAst/validateVersionConfig.ts @@ -1,6 +1,5 @@ import { addPrefixToString } from "@fern-api/core-utils"; -import { VersionFileConfig } from "@fern-fern/docs-config/api"; -import { VersionFileConfig as RawVersionFileConfigSerializer } from "@fern-fern/docs-config/serialization"; +import { Serializer, VersionFileConfig } from "@fern-api/docs-config-sdk"; export type VersionParseResult = VersionFileSuccessParseResult | VersionFileFailureParseResult; @@ -15,7 +14,7 @@ interface VersionFileFailureParseResult { } export async function validateVersionConfigFileSchema({ value }: { value: unknown }): Promise { - const result = await RawVersionFileConfigSerializer.parse(value); + const result = await Serializer.VersionFileConfig.parse(value); if (result.ok) { return { type: "success", diff --git a/packages/cli/yaml/yaml-schema/src/docsAst/visitDocsConfigFileAst.ts b/packages/cli/yaml/yaml-schema/src/docsAst/visitDocsConfigFileAst.ts index c0d57aac845..56446771732 100644 --- a/packages/cli/yaml/yaml-schema/src/docsAst/visitDocsConfigFileAst.ts +++ b/packages/cli/yaml/yaml-schema/src/docsAst/visitDocsConfigFileAst.ts @@ -1,4 +1,3 @@ -import { AbsoluteFilePath, dirname, doesPathExist, resolve } from "@fern-api/fs-utils"; import { DocsConfiguration, NavigationConfig, @@ -6,7 +5,8 @@ import { PageConfiguration, SectionConfiguration, TabbedNavigationConfig -} from "@fern-fern/docs-config/api"; +} from "@fern-api/docs-config-sdk"; +import { AbsoluteFilePath, dirname, doesPathExist, resolve } from "@fern-api/fs-utils"; import { readFile } from "fs/promises"; import yaml from "js-yaml"; import { NodePath } from "../NodePath"; diff --git a/packages/cli/yaml/yaml-schema/tsconfig.json b/packages/cli/yaml/yaml-schema/tsconfig.json index efe0bc84e82..f5e116f01b0 100644 --- a/packages/cli/yaml/yaml-schema/tsconfig.json +++ b/packages/cli/yaml/yaml-schema/tsconfig.json @@ -5,6 +5,7 @@ "references": [ { "path": "../../../commons/core-utils" }, { "path": "../../../commons/fs-utils" }, + { "path": "../../../docs-config-sdk" }, { "path": "../../../ir-sdk" } ] } diff --git a/packages/docs-config-sdk/.depcheckrc.json b/packages/docs-config-sdk/.depcheckrc.json new file mode 100644 index 00000000000..57573daed03 --- /dev/null +++ b/packages/docs-config-sdk/.depcheckrc.json @@ -0,0 +1 @@ +{ "ignores": ["@types/jest", "@types/node"], "ignore-patterns": ["lib"] } diff --git a/packages/docs-config-sdk/.mrlint.json b/packages/docs-config-sdk/.mrlint.json new file mode 100644 index 00000000000..352ed84a2db --- /dev/null +++ b/packages/docs-config-sdk/.mrlint.json @@ -0,0 +1,11 @@ +{ + "type": "library", + "private": true, + "rules": { + "package-json": { + "scripts": { + "generate": "fern generate --local" + } + } + } +} diff --git a/packages/docs-config-sdk/.prettierrc.cjs b/packages/docs-config-sdk/.prettierrc.cjs new file mode 100644 index 00000000000..2b5cf5b0c04 --- /dev/null +++ b/packages/docs-config-sdk/.prettierrc.cjs @@ -0,0 +1 @@ +module.exports = require("../../.prettierrc.json"); diff --git a/fern/apis/docs-config/definition/api.yml b/packages/docs-config-sdk/fern/definition/api.yml similarity index 100% rename from fern/apis/docs-config/definition/api.yml rename to packages/docs-config-sdk/fern/definition/api.yml diff --git a/fern/apis/docs-config/definition/docs.yml b/packages/docs-config-sdk/fern/definition/docs.yml similarity index 92% rename from fern/apis/docs-config/definition/docs.yml rename to packages/docs-config-sdk/fern/definition/docs.yml index 1ccb97a666e..3e374cf6adf 100644 --- a/fern/apis/docs-config/definition/docs.yml +++ b/packages/docs-config-sdk/fern/definition/docs.yml @@ -99,13 +99,20 @@ types: VersionConfig: properties: display-name: string - path: string - slug: optional - availability: optional + path: + type: string + docs: The relative path to the version's docs.yml file. + slug: + type: optional + docs: The "slug" is this version's basePath. If not set, the slug will be generated from the display-name. + availability: + type: optional + docs: | + If `availability` is set to `deprecated`, Fern will display a warning banner on the docs site. VersionAvailability: enum: - - deprecated + - deprecated # TODO: should we support `legacy`? - ga - stable - beta @@ -305,6 +312,11 @@ types: docs: Defaults to false snippets: optional + LinkConfiguration: + properties: + link: string + href: string + SnippetsConfiguration: properties: python: optional @@ -330,17 +342,20 @@ types: NavbarLink: union: - filled: LinkConfiguration - outlined: LinkConfiguration - minimal: LinkConfiguration + filled: NavbarLinkConfiguration + outlined: NavbarLinkConfiguration + minimal: NavbarLinkConfiguration # deprecated - primary: LinkConfiguration # use `outlined` instead - secondary: LinkConfiguration # use `minimal` instead + primary: NavbarLinkConfiguration # use `outlined` instead + secondary: NavbarLinkConfiguration # use `minimal` instead - LinkConfiguration: + NavbarLinkConfiguration: properties: - url: string + href: optional + url: + type: optional + availability: deprecated text: string CssConfig: diff --git a/packages/docs-config-sdk/fern/fern.config.json b/packages/docs-config-sdk/fern/fern.config.json new file mode 100644 index 00000000000..e77f653f42c --- /dev/null +++ b/packages/docs-config-sdk/fern/fern.config.json @@ -0,0 +1,4 @@ +{ + "organization": "fern", + "version": "0.17.7" +} \ No newline at end of file diff --git a/packages/docs-config-sdk/fern/generators.yml b/packages/docs-config-sdk/fern/generators.yml new file mode 100644 index 00000000000..135f668dcb1 --- /dev/null +++ b/packages/docs-config-sdk/fern/generators.yml @@ -0,0 +1,13 @@ +default-group: local +groups: + local: + generators: + - name: fernapi/fern-typescript-node-sdk + version: 0.8.13 + output: + location: local-file-system + path: ../src/sdk + config: + outputSourceFiles: true + includeUtilsOnUnionMembers: false + noOptionalProperties: false diff --git a/packages/docs-config-sdk/jest.config.ts b/packages/docs-config-sdk/jest.config.ts new file mode 100644 index 00000000000..867f2c1f738 --- /dev/null +++ b/packages/docs-config-sdk/jest.config.ts @@ -0,0 +1 @@ +export { default } from "../../shared/jest.config.shared"; diff --git a/packages/docs-config-sdk/package.json b/packages/docs-config-sdk/package.json new file mode 100644 index 00000000000..9755cf3e15d --- /dev/null +++ b/packages/docs-config-sdk/package.json @@ -0,0 +1,40 @@ +{ + "name": "@fern-api/docs-config-sdk", + "version": "0.0.0", + "repository": { + "type": "git", + "url": "https://github.com/fern-api/fern.git", + "directory": "packages/docs-config-sdk" + }, + "private": true, + "files": [ + "lib" + ], + "type": "module", + "source": "src/index.ts", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "sideEffects": false, + "scripts": { + "clean": "rm -rf ./lib && tsc --build --clean", + "compile": "tsc --build", + "test": "yarn compile && jest --passWithNoTests", + "lint:eslint": "eslint --max-warnings 0 . --ignore-path=../../.eslintignore --report-unused-disable-directives", + "lint:eslint:fix": "yarn lint:eslint --fix", + "format": "prettier --write --ignore-unknown --ignore-path ../../shared/.prettierignore \"**\"", + "format:check": "prettier --check --ignore-unknown --ignore-path ../../shared/.prettierignore \"**\"", + "organize-imports": "organize-imports-cli tsconfig.json", + "depcheck": "depcheck", + "generate": "fern generate --local" + }, + "devDependencies": { + "@types/jest": "^29.0.3", + "@types/node": "^18.7.18", + "depcheck": "^1.4.6", + "eslint": "^8.56.0", + "jest": "^29.7.0", + "organize-imports-cli": "^0.10.0", + "prettier": "^2.7.1", + "typescript": "4.6.4" + } +} diff --git a/packages/docs-config-sdk/src/index.ts b/packages/docs-config-sdk/src/index.ts new file mode 100644 index 00000000000..4a9adbce060 --- /dev/null +++ b/packages/docs-config-sdk/src/index.ts @@ -0,0 +1,4 @@ +export * from "./sdk"; +export * from "./sdk/api"; +export * from "./sdk/core"; +export * as Serializer from "./sdk/serialization"; diff --git a/packages/docs-config-sdk/src/sdk/api/index.ts b/packages/docs-config-sdk/src/sdk/api/index.ts new file mode 100644 index 00000000000..3e5335fe421 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/index.ts @@ -0,0 +1 @@ +export * from "./resources"; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/index.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/index.ts new file mode 100644 index 00000000000..eea524d6557 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/index.ts @@ -0,0 +1 @@ +export * from "./types"; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ApiSectionConfiguration.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ApiSectionConfiguration.ts new file mode 100644 index 00000000000..5a74f0220e0 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ApiSectionConfiguration.ts @@ -0,0 +1,15 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface ApiSectionConfiguration { + api: string; + /** Name of API that we are referencing */ + apiName?: string; + audiences?: string[]; + /** Defaults to false */ + displayErrors?: boolean; + snippets?: FernDocsConfig.SnippetsConfiguration; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/AudiencesConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/AudiencesConfig.ts new file mode 100644 index 00000000000..9cffd18bf97 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/AudiencesConfig.ts @@ -0,0 +1,9 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +/** + * Restricts the API endpoints and webhooks that are included in the docs site. + * If `audiences` is not set, only entities marked as "external" will be included. + */ +export type AudiencesConfig = string | string[]; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorConfig.ts new file mode 100644 index 00000000000..55d85cca7ab --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorConfig.ts @@ -0,0 +1,7 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export type ColorConfig = string | FernDocsConfig.ColorThemedConfig; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorThemedConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorThemedConfig.ts new file mode 100644 index 00000000000..068d6a6681a --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorThemedConfig.ts @@ -0,0 +1,8 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export interface ColorThemedConfig { + dark?: string; + light?: string; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorsConfiguration.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorsConfiguration.ts new file mode 100644 index 00000000000..90f78f47f2b --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/ColorsConfiguration.ts @@ -0,0 +1,10 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface ColorsConfiguration { + accentPrimary?: FernDocsConfig.ColorConfig; + background?: FernDocsConfig.ColorConfig; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/CssConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/CssConfig.ts new file mode 100644 index 00000000000..aacf55ecf69 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/CssConfig.ts @@ -0,0 +1,20 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +/** + * The `css` object allows you to customize the appearance of your docs site by injecting custom CSS, i.e. + * + * ```yaml + * css: "path/to/css/file.css" + * ``` + * + * or, multiple files: + * + * ```yaml + * css: + * - "path/to/css/file.css" + * - "path/to/another/css/file.css" + * ``` + */ +export type CssConfig = string | string[]; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsConfiguration.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsConfiguration.ts new file mode 100644 index 00000000000..7f1332483df --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsConfiguration.ts @@ -0,0 +1,25 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface DocsConfiguration { + instances: FernDocsConfig.DocsInstances[]; + /** The navigation config is skipped when multiple versions are present. */ + navigation?: FernDocsConfig.NavigationConfig; + tabs?: Record; + versions?: FernDocsConfig.VersionConfig[]; + /** used as tab bar title, and in the navbar if no logo is defined */ + title?: string; + logo?: FernDocsConfig.LogoConfiguration; + favicon?: string; + /** This background image is used to customize the appearance of your docs site. */ + backgroundImage?: string; + colors?: FernDocsConfig.ColorsConfiguration; + navbarLinks?: FernDocsConfig.NavbarLink[]; + typography?: FernDocsConfig.DocsTypographyConfig; + layout?: FernDocsConfig.LayoutConfig; + css?: FernDocsConfig.CssConfig; + js?: FernDocsConfig.JsConfig; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsInstances.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsInstances.ts new file mode 100644 index 00000000000..1d5fe3e305b --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsInstances.ts @@ -0,0 +1,15 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface DocsInstances { + url: string; + customDomain?: string; + audiences?: FernDocsConfig.AudiencesConfig; + /** If `private` is set to true, Fern will protect the docs site with SSO. */ + private?: boolean; + /** If `edit-this-page` is set, Fern will add an "Edit this page" link to the bottom of each page that links to the given GitHub repository. */ + editThisPage?: FernDocsConfig.EditThisPageConfig; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsTypographyConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsTypographyConfig.ts new file mode 100644 index 00000000000..03cdb85b6f5 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/DocsTypographyConfig.ts @@ -0,0 +1,11 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface DocsTypographyConfig { + headingsFont?: FernDocsConfig.FontConfig; + bodyFont?: FernDocsConfig.FontConfig; + codeFont?: FernDocsConfig.FontConfig; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/EditThisPageConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/EditThisPageConfig.ts new file mode 100644 index 00000000000..425235e2552 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/EditThisPageConfig.ts @@ -0,0 +1,9 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface EditThisPageConfig { + github?: FernDocsConfig.GithubEditThisPageConfig; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfig.ts new file mode 100644 index 00000000000..54b4ec902c6 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfig.ts @@ -0,0 +1,23 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface FontConfig { + /** If the `name` is not supplied, Fern will default it to a generated name that will be used to reference your custom font in the eventually injected CSS in the docs. */ + name?: string; + /** The relative path of the font file. To define multiple weight and style varations of the same font, use `paths` instead. */ + path?: string; + /** @default: `100 900`. */ + weight?: string; + /** @default: `normal`. */ + style?: FernDocsConfig.FontStyle; + /** Use this instead of `path` if you want to specify multiple font files for different font weights and styles. */ + paths?: FernDocsConfig.FontConfigPath[]; + /** @default: `swap`. */ + display?: FernDocsConfig.FontDisplay; + /** Define fallback fonts in case the custom font fails to load. */ + fallback?: string[]; + fontVariationSettings?: string; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfigPath.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfigPath.ts new file mode 100644 index 00000000000..cd1a3cea2d1 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfigPath.ts @@ -0,0 +1,7 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export type FontConfigPath = string | FernDocsConfig.FontConfigVariant; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfigVariant.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfigVariant.ts new file mode 100644 index 00000000000..98838f53ef5 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontConfigVariant.ts @@ -0,0 +1,13 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface FontConfigVariant { + path: string; + /** @default: `100 900`. */ + weight?: string; + /** @default: `normal`. */ + style?: FernDocsConfig.FontStyle; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontDisplay.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontDisplay.ts new file mode 100644 index 00000000000..fec3aa2dd04 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontDisplay.ts @@ -0,0 +1,13 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export type FontDisplay = "auto" | "block" | "swap" | "fallback" | "optional"; + +export const FontDisplay = { + Auto: "auto", + Block: "block", + Swap: "swap", + Fallback: "fallback", + Optional: "optional", +} as const; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontStyle.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontStyle.ts new file mode 100644 index 00000000000..7f83ec7e7c3 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/FontStyle.ts @@ -0,0 +1,10 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export type FontStyle = "normal" | "italic"; + +export const FontStyle = { + Normal: "normal", + Italic: "italic", +} as const; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/GithubEditThisPageConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/GithubEditThisPageConfig.ts new file mode 100644 index 00000000000..39db01443df --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/GithubEditThisPageConfig.ts @@ -0,0 +1,12 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export interface GithubEditThisPageConfig { + /** @default: `github.com` */ + host?: string; + owner: string; + repo: string; + /** @default: `main` */ + branch?: string; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsConfig.ts new file mode 100644 index 00000000000..32698d3e1c1 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsConfig.ts @@ -0,0 +1,40 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +/** + * The `js` object allows you to customize the behavior of your docs site by injecting custom JavaScript, i.e. + * + * ```yaml + * js: "path/to/js/file.js" + * ``` + * + * or, multiple files: + * + * ```yaml + * js: + * - "path/to/js/file.js" + * - "path/to/another/js/file.js" + * ``` + * + * or remote js: + * + * ```yaml + * js: + * url: "https://example.com/path/to/js/file.js" + * strategy: "afterInteractive" + * ``` + * + * or, mixed: + * + * ```yaml + * js: + * - "path/to/js/file.js" + * - path: "path/to/another/js/file.js" + * strategy: "beforeInteractive" + * - url: "https://example.com/path/to/js/file.js" + * ``` + */ +export type JsConfig = FernDocsConfig.JsConfigOptions | FernDocsConfig.JsConfigOptions[]; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsConfigOptions.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsConfigOptions.ts new file mode 100644 index 00000000000..7d830d6172e --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsConfigOptions.ts @@ -0,0 +1,7 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export type JsConfigOptions = FernDocsConfig.JsRemoteConfig | FernDocsConfig.JsFileConfig; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsFileConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsFileConfig.ts new file mode 100644 index 00000000000..87217702314 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsFileConfig.ts @@ -0,0 +1,7 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export type JsFileConfig = string | FernDocsConfig.JsFileConfigSettings; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsFileConfigSettings.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsFileConfigSettings.ts new file mode 100644 index 00000000000..4775ceef7ac --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsFileConfigSettings.ts @@ -0,0 +1,10 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface JsFileConfigSettings { + path: string; + strategy?: FernDocsConfig.JsScriptStrategy; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsRemoteConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsRemoteConfig.ts new file mode 100644 index 00000000000..c18b15883f6 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsRemoteConfig.ts @@ -0,0 +1,10 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface JsRemoteConfig { + url: string; + strategy?: FernDocsConfig.JsScriptStrategy; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsScriptStrategy.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsScriptStrategy.ts new file mode 100644 index 00000000000..1cdb6bc01f0 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/JsScriptStrategy.ts @@ -0,0 +1,11 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export type JsScriptStrategy = "beforeInteractive" | "afterInteractive" | "lazyOnload"; + +export const JsScriptStrategy = { + BeforeInteractive: "beforeInteractive", + AfterInteractive: "afterInteractive", + LazyOnload: "lazyOnload", +} as const; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/LayoutConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/LayoutConfig.ts new file mode 100644 index 00000000000..a99c017a46d --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/LayoutConfig.ts @@ -0,0 +1,59 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface LayoutConfig { + /** + * Sets the maximum width of the docs layout, including the sidebar and content. + * If `page-width` is not set, the default value is 88rem (1408px). + * + * Valid options are: + * + * - `{number}rem` + * - `{number}px` + * - `full` (100% of the viewport width) + */ + pageWidth?: string; + /** + * Sets the maximum width of the markdown article content. + * If `content-width` is not set, the default value is 44rem (704px). + * + * Valid options are: + * + * - `{number}rem` + * - `{number}px` + */ + contentWidth?: string; + /** + * Sets the width of the sidebar in desktop mode. + * If `sidebar-width` is not set, the default value is 18rem (288px). + * + * Valid options are: + * + * - `{number}rem` + * - `{number}px` + */ + sidebarWidth?: string; + /** + * Sets the height of the header. + * If `header-height` is not set, the default value is 4rem (64px). + * + * Valid options are: + * + * - `{number}rem` + * - `{number}px` + */ + headerHeight?: string; + /** + * Sets the placement of the searchbar. + * If `searchbar-position` is not set, the default value is `sidebar`. + */ + searchbarPlacement?: FernDocsConfig.SidebarOrHeaderPlacement; + /** + * Set the placement of the tabs. + * If `tabs-position` is not set, the default value is `sidebar`. + */ + tabsPlacement?: FernDocsConfig.SidebarOrHeaderPlacement; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/LinkConfiguration.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/LinkConfiguration.ts new file mode 100644 index 00000000000..78d0561c288 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/LinkConfiguration.ts @@ -0,0 +1,8 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export interface LinkConfiguration { + link: string; + href: string; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/LogoConfiguration.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/LogoConfiguration.ts new file mode 100644 index 00000000000..2f77d30b784 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/LogoConfiguration.ts @@ -0,0 +1,10 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export interface LogoConfiguration { + dark?: string; + light?: string; + height?: number; + href?: string; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavbarLink.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavbarLink.ts new file mode 100644 index 00000000000..031783b03ee --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavbarLink.ts @@ -0,0 +1,34 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export type NavbarLink = + | FernDocsConfig.NavbarLink.Filled + | FernDocsConfig.NavbarLink.Outlined + | FernDocsConfig.NavbarLink.Minimal + | FernDocsConfig.NavbarLink.Primary + | FernDocsConfig.NavbarLink.Secondary; + +export declare namespace NavbarLink { + interface Filled extends FernDocsConfig.NavbarLinkConfiguration { + type: "filled"; + } + + interface Outlined extends FernDocsConfig.NavbarLinkConfiguration { + type: "outlined"; + } + + interface Minimal extends FernDocsConfig.NavbarLinkConfiguration { + type: "minimal"; + } + + interface Primary extends FernDocsConfig.NavbarLinkConfiguration { + type: "primary"; + } + + interface Secondary extends FernDocsConfig.NavbarLinkConfiguration { + type: "secondary"; + } +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavbarLinkConfiguration.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavbarLinkConfiguration.ts new file mode 100644 index 00000000000..c2eac049c8b --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavbarLinkConfiguration.ts @@ -0,0 +1,9 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export interface NavbarLinkConfiguration { + href?: string; + url?: string; + text: string; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavigationConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavigationConfig.ts new file mode 100644 index 00000000000..0c29172c8eb --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavigationConfig.ts @@ -0,0 +1,7 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export type NavigationConfig = FernDocsConfig.UntabbedNavigationConifg | FernDocsConfig.TabbedNavigationConfig; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavigationItem.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavigationItem.ts new file mode 100644 index 00000000000..f0d627dbb63 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/NavigationItem.ts @@ -0,0 +1,11 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export type NavigationItem = + | FernDocsConfig.PageConfiguration + | FernDocsConfig.SectionConfiguration + | FernDocsConfig.ApiSectionConfiguration + | FernDocsConfig.LinkConfiguration; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/PageConfiguration.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/PageConfiguration.ts new file mode 100644 index 00000000000..766e6c2a913 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/PageConfiguration.ts @@ -0,0 +1,9 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export interface PageConfiguration { + page: string; + path: string; + slug?: string; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/SectionConfiguration.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/SectionConfiguration.ts new file mode 100644 index 00000000000..f25073b328a --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/SectionConfiguration.ts @@ -0,0 +1,12 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface SectionConfiguration { + section: string; + contents: FernDocsConfig.NavigationItem[]; + collapsed?: boolean; + slug?: string; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/SidebarOrHeaderPlacement.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/SidebarOrHeaderPlacement.ts new file mode 100644 index 00000000000..b87ee1abf01 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/SidebarOrHeaderPlacement.ts @@ -0,0 +1,10 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export type SidebarOrHeaderPlacement = "header" | "sidebar"; + +export const SidebarOrHeaderPlacement = { + Header: "header", + Sidebar: "sidebar", +} as const; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/SnippetsConfiguration.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/SnippetsConfiguration.ts new file mode 100644 index 00000000000..e78c6dd98eb --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/SnippetsConfiguration.ts @@ -0,0 +1,10 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export interface SnippetsConfiguration { + python?: string; + typescript?: string; + go?: string; + java?: string; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabConfig.ts new file mode 100644 index 00000000000..68d86aa68b1 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabConfig.ts @@ -0,0 +1,9 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export interface TabConfig { + displayName: string; + icon: string; + slug?: string; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabId.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabId.ts new file mode 100644 index 00000000000..06246f9b086 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabId.ts @@ -0,0 +1,5 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export type TabId = string; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabbedNavigationConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabbedNavigationConfig.ts new file mode 100644 index 00000000000..3e261f3cd30 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabbedNavigationConfig.ts @@ -0,0 +1,7 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export type TabbedNavigationConfig = FernDocsConfig.TabbedNavigationItem[]; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabbedNavigationItem.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabbedNavigationItem.ts new file mode 100644 index 00000000000..edc3f34c41d --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/TabbedNavigationItem.ts @@ -0,0 +1,10 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface TabbedNavigationItem { + tab: FernDocsConfig.TabId; + layout: FernDocsConfig.NavigationItem[]; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/UntabbedNavigationConifg.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/UntabbedNavigationConifg.ts new file mode 100644 index 00000000000..4970b0f5570 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/UntabbedNavigationConifg.ts @@ -0,0 +1,7 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export type UntabbedNavigationConifg = FernDocsConfig.NavigationItem[]; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionAvailability.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionAvailability.ts new file mode 100644 index 00000000000..e2d46b1b982 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionAvailability.ts @@ -0,0 +1,12 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export type VersionAvailability = "deprecated" | "ga" | "stable" | "beta"; + +export const VersionAvailability = { + Deprecated: "deprecated", + Ga: "ga", + Stable: "stable", + Beta: "beta", +} as const; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionConfig.ts new file mode 100644 index 00000000000..04d6845bcef --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionConfig.ts @@ -0,0 +1,15 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface VersionConfig { + displayName: string; + /** The relative path to the version's docs.yml file. */ + path: string; + /** The "slug" is this version's basePath. If not set, the slug will be generated from the display-name. */ + slug?: string; + /** If `availability` is set to `deprecated`, Fern will display a warning banner on the docs site. */ + availability?: FernDocsConfig.VersionAvailability; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionFileConfig.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionFileConfig.ts new file mode 100644 index 00000000000..7c15c4f10d3 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/VersionFileConfig.ts @@ -0,0 +1,9 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as FernDocsConfig from "../../.."; + +export interface VersionFileConfig { + navigation: FernDocsConfig.NavigationConfig; +} diff --git a/packages/docs-config-sdk/src/sdk/api/resources/docs/types/index.ts b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/index.ts new file mode 100644 index 00000000000..0f292b9d80e --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/docs/types/index.ts @@ -0,0 +1,41 @@ +export * from "./DocsConfiguration"; +export * from "./TabId"; +export * from "./TabConfig"; +export * from "./DocsInstances"; +export * from "./EditThisPageConfig"; +export * from "./GithubEditThisPageConfig"; +export * from "./AudiencesConfig"; +export * from "./VersionConfig"; +export * from "./VersionAvailability"; +export * from "./VersionFileConfig"; +export * from "./NavigationConfig"; +export * from "./UntabbedNavigationConifg"; +export * from "./TabbedNavigationConfig"; +export * from "./TabbedNavigationItem"; +export * from "./NavigationItem"; +export * from "./LogoConfiguration"; +export * from "./DocsTypographyConfig"; +export * from "./LayoutConfig"; +export * from "./SidebarOrHeaderPlacement"; +export * from "./FontConfig"; +export * from "./FontStyle"; +export * from "./FontDisplay"; +export * from "./FontConfigPath"; +export * from "./FontConfigVariant"; +export * from "./PageConfiguration"; +export * from "./SectionConfiguration"; +export * from "./ApiSectionConfiguration"; +export * from "./LinkConfiguration"; +export * from "./SnippetsConfiguration"; +export * from "./ColorsConfiguration"; +export * from "./ColorConfig"; +export * from "./ColorThemedConfig"; +export * from "./NavbarLink"; +export * from "./NavbarLinkConfiguration"; +export * from "./CssConfig"; +export * from "./JsConfig"; +export * from "./JsConfigOptions"; +export * from "./JsRemoteConfig"; +export * from "./JsFileConfig"; +export * from "./JsFileConfigSettings"; +export * from "./JsScriptStrategy"; diff --git a/packages/docs-config-sdk/src/sdk/api/resources/index.ts b/packages/docs-config-sdk/src/sdk/api/resources/index.ts new file mode 100644 index 00000000000..e6bc80c6a88 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/api/resources/index.ts @@ -0,0 +1,2 @@ +export * as docs from "./docs"; +export * from "./docs/types"; diff --git a/packages/docs-config-sdk/src/sdk/core/index.ts b/packages/docs-config-sdk/src/sdk/core/index.ts new file mode 100644 index 00000000000..3ae53c06d38 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/index.ts @@ -0,0 +1 @@ +export * as serialization from "./schemas"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/Schema.ts b/packages/docs-config-sdk/src/sdk/core/schemas/Schema.ts new file mode 100644 index 00000000000..870f373ba87 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/Schema.ts @@ -0,0 +1,94 @@ +import { SchemaUtils } from "./builders"; +import { MaybePromise } from "./utils/MaybePromise"; + +export type Schema = BaseSchema & SchemaUtils; + +export type inferRaw = S extends Schema ? Raw : never; +export type inferParsed = S extends Schema ? Parsed : never; + +export interface BaseSchema { + parse: (raw: unknown, opts?: SchemaOptions) => MaybePromise>; + json: (parsed: unknown, opts?: SchemaOptions) => MaybePromise>; + getType: () => SchemaType | Promise; +} + +export const SchemaType = { + DATE: "date", + ENUM: "enum", + LIST: "list", + STRING_LITERAL: "stringLiteral", + BOOLEAN_LITERAL: "booleanLiteral", + OBJECT: "object", + ANY: "any", + BOOLEAN: "boolean", + NUMBER: "number", + STRING: "string", + UNKNOWN: "unknown", + RECORD: "record", + SET: "set", + UNION: "union", + UNDISCRIMINATED_UNION: "undiscriminatedUnion", + OPTIONAL: "optional", +} as const; +export type SchemaType = typeof SchemaType[keyof typeof SchemaType]; + +export type MaybeValid = Valid | Invalid; + +export interface Valid { + ok: true; + value: T; +} + +export interface Invalid { + ok: false; + errors: ValidationError[]; +} + +export interface ValidationError { + path: string[]; + message: string; +} + +export interface SchemaOptions { + /** + * how to handle unrecognized keys in objects + * + * @default "fail" + */ + unrecognizedObjectKeys?: "fail" | "passthrough" | "strip"; + + /** + * whether to fail when an unrecognized discriminant value is + * encountered in a union + * + * @default false + */ + allowUnrecognizedUnionMembers?: boolean; + + /** + * whether to fail when an unrecognized enum value is encountered + * + * @default false + */ + allowUnrecognizedEnumValues?: boolean; + + /** + * whether to allow data that doesn't conform to the schema. + * invalid data is passed through without transformation. + * + * when this is enabled, .parse() and .json() will always + * return `ok: true`. `.parseOrThrow()` and `.jsonOrThrow()` + * will never fail. + * + * @default false + */ + skipValidation?: boolean; + + /** + * each validation failure contains a "path" property, which is + * the breadcrumbs to the offending node in the JSON. you can supply + * a prefix that is prepended to all the errors' paths. this can be + * helpful for zurg's internal debug logging. + */ + breadcrumbsPrefix?: string[]; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/date/date.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/date/date.ts new file mode 100644 index 00000000000..b70f24b045a --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/date/date.ts @@ -0,0 +1,65 @@ +import { BaseSchema, Schema, SchemaType } from "../../Schema"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; +import { maybeSkipValidation } from "../../utils/maybeSkipValidation"; +import { getSchemaUtils } from "../schema-utils"; + +// https://stackoverflow.com/questions/12756159/regex-and-iso8601-formatted-datetime +const ISO_8601_REGEX = + /^([+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([.,]\d+(?!:))?)?(\17[0-5]\d([.,]\d+)?)?([zZ]|([+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/; + +export function date(): Schema { + const baseSchema: BaseSchema = { + parse: (raw, { breadcrumbsPrefix = [] } = {}) => { + if (typeof raw !== "string") { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(raw, "string"), + }, + ], + }; + } + if (!ISO_8601_REGEX.test(raw)) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(raw, "ISO 8601 date string"), + }, + ], + }; + } + return { + ok: true, + value: new Date(raw), + }; + }, + json: (date, { breadcrumbsPrefix = [] } = {}) => { + if (date instanceof Date) { + return { + ok: true, + value: date.toISOString(), + }; + } else { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(date, "Date object"), + }, + ], + }; + } + }, + getType: () => SchemaType.DATE, + }; + + return { + ...maybeSkipValidation(baseSchema), + ...getSchemaUtils(baseSchema), + }; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/date/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/date/index.ts new file mode 100644 index 00000000000..187b29040f6 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/date/index.ts @@ -0,0 +1 @@ +export { date } from "./date"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/enum/enum.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/enum/enum.ts new file mode 100644 index 00000000000..c1e24d69dec --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/enum/enum.ts @@ -0,0 +1,43 @@ +import { Schema, SchemaType } from "../../Schema"; +import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; + +export function enum_(values: E): Schema { + const validValues = new Set(values); + + const schemaCreator = createIdentitySchemaCreator( + SchemaType.ENUM, + (value, { allowUnrecognizedEnumValues, breadcrumbsPrefix = [] } = {}) => { + if (typeof value !== "string") { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(value, "string"), + }, + ], + }; + } + + if (!validValues.has(value) && !allowUnrecognizedEnumValues) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(value, "enum"), + }, + ], + }; + } + + return { + ok: true, + value: value as U, + }; + } + ); + + return schemaCreator(); +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/enum/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/enum/index.ts new file mode 100644 index 00000000000..fe6faed93e3 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/enum/index.ts @@ -0,0 +1 @@ +export { enum_ } from "./enum"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/index.ts new file mode 100644 index 00000000000..050cd2c4efb --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/index.ts @@ -0,0 +1,13 @@ +export * from "./date"; +export * from "./enum"; +export * from "./lazy"; +export * from "./list"; +export * from "./literals"; +export * from "./object"; +export * from "./object-like"; +export * from "./primitives"; +export * from "./record"; +export * from "./schema-utils"; +export * from "./set"; +export * from "./undiscriminated-union"; +export * from "./union"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/index.ts new file mode 100644 index 00000000000..77420fb031c --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/index.ts @@ -0,0 +1,3 @@ +export { lazy } from "./lazy"; +export type { SchemaGetter } from "./lazy"; +export { lazyObject } from "./lazyObject"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/lazy.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/lazy.ts new file mode 100644 index 00000000000..a665472d22c --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/lazy.ts @@ -0,0 +1,34 @@ +import { BaseSchema, Schema } from "../../Schema"; +import { getSchemaUtils } from "../schema-utils"; + +export type SchemaGetter> = () => SchemaType | Promise; + +export function lazy(getter: SchemaGetter>): Schema { + const baseSchema = constructLazyBaseSchema(getter); + return { + ...baseSchema, + ...getSchemaUtils(baseSchema), + }; +} + +export function constructLazyBaseSchema( + getter: SchemaGetter> +): BaseSchema { + return { + parse: async (raw, opts) => (await getMemoizedSchema(getter)).parse(raw, opts), + json: async (parsed, opts) => (await getMemoizedSchema(getter)).json(parsed, opts), + getType: async () => (await getMemoizedSchema(getter)).getType(), + }; +} + +type MemoizedGetter> = SchemaGetter & { __zurg_memoized?: SchemaType }; + +export async function getMemoizedSchema>( + getter: SchemaGetter +): Promise { + const castedGetter = getter as MemoizedGetter; + if (castedGetter.__zurg_memoized == null) { + castedGetter.__zurg_memoized = await getter(); + } + return castedGetter.__zurg_memoized; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/lazyObject.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/lazyObject.ts new file mode 100644 index 00000000000..e48c0166677 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/lazy/lazyObject.ts @@ -0,0 +1,20 @@ +import { getObjectUtils } from "../object"; +import { getObjectLikeUtils } from "../object-like"; +import { BaseObjectSchema, ObjectSchema } from "../object/types"; +import { getSchemaUtils } from "../schema-utils"; +import { constructLazyBaseSchema, getMemoizedSchema, SchemaGetter } from "./lazy"; + +export function lazyObject(getter: SchemaGetter>): ObjectSchema { + const baseSchema: BaseObjectSchema = { + ...constructLazyBaseSchema(getter), + _getRawProperties: async () => (await getMemoizedSchema(getter))._getRawProperties(), + _getParsedProperties: async () => (await getMemoizedSchema(getter))._getParsedProperties(), + }; + + return { + ...baseSchema, + ...getSchemaUtils(baseSchema), + ...getObjectLikeUtils(baseSchema), + ...getObjectUtils(baseSchema), + }; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/list/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/list/index.ts new file mode 100644 index 00000000000..25f4bcc1737 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/list/index.ts @@ -0,0 +1 @@ +export { list } from "./list"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/list/list.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/list/list.ts new file mode 100644 index 00000000000..b333321b507 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/list/list.ts @@ -0,0 +1,74 @@ +import { BaseSchema, MaybeValid, Schema, SchemaType, ValidationError } from "../../Schema"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; +import { MaybePromise } from "../../utils/MaybePromise"; +import { maybeSkipValidation } from "../../utils/maybeSkipValidation"; +import { getSchemaUtils } from "../schema-utils"; + +export function list(schema: Schema): Schema { + const baseSchema: BaseSchema = { + parse: async (raw, opts) => + validateAndTransformArray(raw, (item, index) => + schema.parse(item, { + ...opts, + breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `[${index}]`], + }) + ), + json: (parsed, opts) => + validateAndTransformArray(parsed, (item, index) => + schema.json(item, { + ...opts, + breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `[${index}]`], + }) + ), + getType: () => SchemaType.LIST, + }; + + return { + ...maybeSkipValidation(baseSchema), + ...getSchemaUtils(baseSchema), + }; +} + +async function validateAndTransformArray( + value: unknown, + transformItem: (item: Raw, index: number) => MaybePromise> +): Promise> { + if (!Array.isArray(value)) { + return { + ok: false, + errors: [ + { + message: getErrorMessageForIncorrectType(value, "list"), + path: [], + }, + ], + }; + } + + const maybeValidItems = await Promise.all(value.map((item, index) => transformItem(item, index))); + + return maybeValidItems.reduce>( + (acc, item) => { + if (acc.ok && item.ok) { + return { + ok: true, + value: [...acc.value, item.value], + }; + } + + const errors: ValidationError[] = []; + if (!acc.ok) { + errors.push(...acc.errors); + } + if (!item.ok) { + errors.push(...item.errors); + } + + return { + ok: false, + errors, + }; + }, + { ok: true, value: [] } + ); +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/booleanLiteral.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/booleanLiteral.ts new file mode 100644 index 00000000000..a83d22cd48a --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/booleanLiteral.ts @@ -0,0 +1,29 @@ +import { Schema, SchemaType } from "../../Schema"; +import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; + +export function booleanLiteral(literal: V): Schema { + const schemaCreator = createIdentitySchemaCreator( + SchemaType.BOOLEAN_LITERAL, + (value, { breadcrumbsPrefix = [] } = {}) => { + if (value === literal) { + return { + ok: true, + value: literal, + }; + } else { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(value, `${literal.toString()}`), + }, + ], + }; + } + } + ); + + return schemaCreator(); +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/index.ts new file mode 100644 index 00000000000..d2bf08fc6ca --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/index.ts @@ -0,0 +1,2 @@ +export { stringLiteral } from "./stringLiteral"; +export { booleanLiteral } from "./booleanLiteral"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/stringLiteral.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/stringLiteral.ts new file mode 100644 index 00000000000..3939b76b48d --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/literals/stringLiteral.ts @@ -0,0 +1,29 @@ +import { Schema, SchemaType } from "../../Schema"; +import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; + +export function stringLiteral(literal: V): Schema { + const schemaCreator = createIdentitySchemaCreator( + SchemaType.STRING_LITERAL, + (value, { breadcrumbsPrefix = [] } = {}) => { + if (value === literal) { + return { + ok: true, + value: literal, + }; + } else { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(value, `"${literal}"`), + }, + ], + }; + } + } + ); + + return schemaCreator(); +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/getObjectLikeUtils.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/getObjectLikeUtils.ts new file mode 100644 index 00000000000..270ea170c85 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/getObjectLikeUtils.ts @@ -0,0 +1,79 @@ +import { BaseSchema } from "../../Schema"; +import { filterObject } from "../../utils/filterObject"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; +import { isPlainObject } from "../../utils/isPlainObject"; +import { getSchemaUtils } from "../schema-utils"; +import { ObjectLikeSchema, ObjectLikeUtils } from "./types"; + +export function getObjectLikeUtils(schema: BaseSchema): ObjectLikeUtils { + return { + withParsedProperties: (properties) => withParsedProperties(schema, properties), + }; +} + +/** + * object-like utils are defined in one file to resolve issues with circular imports + */ + +export function withParsedProperties( + objectLike: BaseSchema, + properties: { [K in keyof Properties]: Properties[K] | ((parsed: ParsedObjectShape) => Properties[K]) } +): ObjectLikeSchema { + const objectSchema: BaseSchema = { + parse: async (raw, opts) => { + const parsedObject = await objectLike.parse(raw, opts); + if (!parsedObject.ok) { + return parsedObject; + } + + const additionalProperties = Object.entries(properties).reduce>( + (processed, [key, value]) => { + return { + ...processed, + [key]: typeof value === "function" ? value(parsedObject.value) : value, + }; + }, + {} + ); + + return { + ok: true, + value: { + ...parsedObject.value, + ...(additionalProperties as Properties), + }, + }; + }, + + json: (parsed, opts) => { + if (!isPlainObject(parsed)) { + return { + ok: false, + errors: [ + { + path: opts?.breadcrumbsPrefix ?? [], + message: getErrorMessageForIncorrectType(parsed, "object"), + }, + ], + }; + } + + // strip out added properties + const addedPropertyKeys = new Set(Object.keys(properties)); + const parsedWithoutAddedProperties = filterObject( + parsed, + Object.keys(parsed).filter((key) => !addedPropertyKeys.has(key)) + ); + + return objectLike.json(parsedWithoutAddedProperties as ParsedObjectShape, opts); + }, + + getType: () => objectLike.getType(), + }; + + return { + ...objectSchema, + ...getSchemaUtils(objectSchema), + ...getObjectLikeUtils(objectSchema), + }; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/index.ts new file mode 100644 index 00000000000..c342e72cf9d --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/index.ts @@ -0,0 +1,2 @@ +export { getObjectLikeUtils, withParsedProperties } from "./getObjectLikeUtils"; +export type { ObjectLikeSchema, ObjectLikeUtils } from "./types"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/types.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/types.ts new file mode 100644 index 00000000000..75b3698729c --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object-like/types.ts @@ -0,0 +1,11 @@ +import { BaseSchema, Schema } from "../../Schema"; + +export type ObjectLikeSchema = Schema & + BaseSchema & + ObjectLikeUtils; + +export interface ObjectLikeUtils { + withParsedProperties: >(properties: { + [K in keyof T]: T[K] | ((parsed: Parsed) => T[K]); + }) => ObjectLikeSchema; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/index.ts new file mode 100644 index 00000000000..e3f4388db28 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/index.ts @@ -0,0 +1,22 @@ +export { getObjectUtils, object } from "./object"; +export { objectWithoutOptionalProperties } from "./objectWithoutOptionalProperties"; +export type { + inferObjectWithoutOptionalPropertiesSchemaFromPropertySchemas, + inferParsedObjectWithoutOptionalPropertiesFromPropertySchemas, +} from "./objectWithoutOptionalProperties"; +export { isProperty, property } from "./property"; +export type { Property } from "./property"; +export type { + BaseObjectSchema, + inferObjectSchemaFromPropertySchemas, + inferParsedObject, + inferParsedObjectFromPropertySchemas, + inferParsedPropertySchema, + inferRawKey, + inferRawObject, + inferRawObjectFromPropertySchemas, + inferRawPropertySchema, + ObjectSchema, + ObjectUtils, + PropertySchemas, +} from "./types"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/object.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/object.ts new file mode 100644 index 00000000000..4abadfb38be --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/object.ts @@ -0,0 +1,333 @@ +import { MaybeValid, Schema, SchemaType, ValidationError } from "../../Schema"; +import { entries } from "../../utils/entries"; +import { filterObject } from "../../utils/filterObject"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; +import { isPlainObject } from "../../utils/isPlainObject"; +import { keys } from "../../utils/keys"; +import { MaybePromise } from "../../utils/MaybePromise"; +import { maybeSkipValidation } from "../../utils/maybeSkipValidation"; +import { partition } from "../../utils/partition"; +import { getObjectLikeUtils } from "../object-like"; +import { getSchemaUtils } from "../schema-utils"; +import { isProperty } from "./property"; +import { + BaseObjectSchema, + inferObjectSchemaFromPropertySchemas, + inferParsedObjectFromPropertySchemas, + inferRawObjectFromPropertySchemas, + ObjectSchema, + ObjectUtils, + PropertySchemas, +} from "./types"; + +interface ObjectPropertyWithRawKey { + rawKey: string; + parsedKey: string; + valueSchema: Schema; +} + +export function object>( + schemas: T +): inferObjectSchemaFromPropertySchemas { + const baseSchema: BaseObjectSchema< + inferRawObjectFromPropertySchemas, + inferParsedObjectFromPropertySchemas + > = { + _getRawProperties: () => + Promise.resolve( + Object.entries(schemas).map(([parsedKey, propertySchema]) => + isProperty(propertySchema) ? propertySchema.rawKey : parsedKey + ) as unknown as (keyof inferRawObjectFromPropertySchemas)[] + ), + _getParsedProperties: () => + Promise.resolve(keys(schemas) as unknown as (keyof inferParsedObjectFromPropertySchemas)[]), + + parse: async (raw, opts) => { + const rawKeyToProperty: Record = {}; + const requiredKeys: string[] = []; + + for (const [parsedKey, schemaOrObjectProperty] of entries(schemas)) { + const rawKey = isProperty(schemaOrObjectProperty) ? schemaOrObjectProperty.rawKey : parsedKey; + const valueSchema: Schema = isProperty(schemaOrObjectProperty) + ? schemaOrObjectProperty.valueSchema + : schemaOrObjectProperty; + + const property: ObjectPropertyWithRawKey = { + rawKey, + parsedKey: parsedKey as string, + valueSchema, + }; + + rawKeyToProperty[rawKey] = property; + + if (await isSchemaRequired(valueSchema)) { + requiredKeys.push(rawKey); + } + } + + return validateAndTransformObject({ + value: raw, + requiredKeys, + getProperty: (rawKey) => { + const property = rawKeyToProperty[rawKey]; + if (property == null) { + return undefined; + } + return { + transformedKey: property.parsedKey, + transform: (propertyValue) => + property.valueSchema.parse(propertyValue, { + ...opts, + breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), rawKey], + }), + }; + }, + unrecognizedObjectKeys: opts?.unrecognizedObjectKeys, + skipValidation: opts?.skipValidation, + breadcrumbsPrefix: opts?.breadcrumbsPrefix, + }); + }, + + json: async (parsed, opts) => { + const requiredKeys: string[] = []; + + for (const [parsedKey, schemaOrObjectProperty] of entries(schemas)) { + const valueSchema: Schema = isProperty(schemaOrObjectProperty) + ? schemaOrObjectProperty.valueSchema + : schemaOrObjectProperty; + + if (await isSchemaRequired(valueSchema)) { + requiredKeys.push(parsedKey as string); + } + } + + return validateAndTransformObject({ + value: parsed, + requiredKeys, + getProperty: ( + parsedKey + ): + | { transformedKey: string; transform: (propertyValue: unknown) => MaybePromise> } + | undefined => { + const property = schemas[parsedKey as keyof T]; + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (property == null) { + return undefined; + } + + if (isProperty(property)) { + return { + transformedKey: property.rawKey, + transform: (propertyValue) => + property.valueSchema.json(propertyValue, { + ...opts, + breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), parsedKey], + }), + }; + } else { + return { + transformedKey: parsedKey, + transform: (propertyValue) => + property.json(propertyValue, { + ...opts, + breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), parsedKey], + }), + }; + } + }, + unrecognizedObjectKeys: opts?.unrecognizedObjectKeys, + skipValidation: opts?.skipValidation, + breadcrumbsPrefix: opts?.breadcrumbsPrefix, + }); + }, + + getType: () => SchemaType.OBJECT, + }; + + return { + ...maybeSkipValidation(baseSchema), + ...getSchemaUtils(baseSchema), + ...getObjectLikeUtils(baseSchema), + ...getObjectUtils(baseSchema), + }; +} + +async function validateAndTransformObject({ + value, + requiredKeys, + getProperty, + unrecognizedObjectKeys = "fail", + skipValidation = false, + breadcrumbsPrefix = [], +}: { + value: unknown; + requiredKeys: string[]; + getProperty: ( + preTransformedKey: string + ) => { transformedKey: string; transform: (propertyValue: unknown) => MaybePromise> } | undefined; + unrecognizedObjectKeys: "fail" | "passthrough" | "strip" | undefined; + skipValidation: boolean | undefined; + breadcrumbsPrefix: string[] | undefined; +}): Promise> { + if (!isPlainObject(value)) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(value, "object"), + }, + ], + }; + } + + const missingRequiredKeys = new Set(requiredKeys); + const errors: ValidationError[] = []; + const transformed: Record = {}; + + for (const [preTransformedKey, preTransformedItemValue] of Object.entries(value)) { + const property = getProperty(preTransformedKey); + + if (property != null) { + missingRequiredKeys.delete(preTransformedKey); + + const value = await property.transform(preTransformedItemValue); + if (value.ok) { + transformed[property.transformedKey] = value.value; + } else { + transformed[preTransformedKey] = preTransformedItemValue; + errors.push(...value.errors); + } + } else { + switch (unrecognizedObjectKeys) { + case "fail": + errors.push({ + path: [...breadcrumbsPrefix, preTransformedKey], + message: `Unexpected key "${preTransformedKey}"`, + }); + break; + case "strip": + break; + case "passthrough": + transformed[preTransformedKey] = preTransformedItemValue; + break; + } + } + } + + errors.push( + ...requiredKeys + .filter((key) => missingRequiredKeys.has(key)) + .map((key) => ({ + path: breadcrumbsPrefix, + message: `Missing required key "${key}"`, + })) + ); + + if (errors.length === 0 || skipValidation) { + return { + ok: true, + value: transformed as Transformed, + }; + } else { + return { + ok: false, + errors, + }; + } +} + +export function getObjectUtils(schema: BaseObjectSchema): ObjectUtils { + return { + extend: (extension: ObjectSchema) => { + const baseSchema: BaseObjectSchema = { + _getParsedProperties: async () => [ + ...(await schema._getParsedProperties()), + ...(await extension._getParsedProperties()), + ], + _getRawProperties: async () => [ + ...(await schema._getRawProperties()), + ...(await extension._getRawProperties()), + ], + parse: async (raw, opts) => { + return validateAndTransformExtendedObject({ + extensionKeys: await extension._getRawProperties(), + value: raw, + transformBase: (rawBase) => schema.parse(rawBase, opts), + transformExtension: (rawExtension) => extension.parse(rawExtension, opts), + }); + }, + json: async (parsed, opts) => { + return validateAndTransformExtendedObject({ + extensionKeys: await extension._getParsedProperties(), + value: parsed, + transformBase: (parsedBase) => schema.json(parsedBase, opts), + transformExtension: (parsedExtension) => extension.json(parsedExtension, opts), + }); + }, + getType: () => SchemaType.OBJECT, + }; + + return { + ...baseSchema, + ...getSchemaUtils(baseSchema), + ...getObjectLikeUtils(baseSchema), + ...getObjectUtils(baseSchema), + }; + }, + }; +} + +async function validateAndTransformExtendedObject({ + extensionKeys, + value, + transformBase, + transformExtension, +}: { + extensionKeys: (keyof PreTransformedExtension)[]; + value: unknown; + transformBase: (value: unknown) => MaybePromise>; + transformExtension: (value: unknown) => MaybePromise>; +}): Promise> { + const extensionPropertiesSet = new Set(extensionKeys); + const [extensionProperties, baseProperties] = partition(keys(value), (key) => + extensionPropertiesSet.has(key as keyof PreTransformedExtension) + ); + + const transformedBase = await transformBase(filterObject(value, baseProperties)); + const transformedExtension = await transformExtension(filterObject(value, extensionProperties)); + + if (transformedBase.ok && transformedExtension.ok) { + return { + ok: true, + value: { + ...transformedBase.value, + ...transformedExtension.value, + }, + }; + } else { + return { + ok: false, + errors: [ + ...(transformedBase.ok ? [] : transformedBase.errors), + ...(transformedExtension.ok ? [] : transformedExtension.errors), + ], + }; + } +} + +async function isSchemaRequired(schema: Schema): Promise { + return !(await isSchemaOptional(schema)); +} + +async function isSchemaOptional(schema: Schema): Promise { + switch (await schema.getType()) { + case SchemaType.ANY: + case SchemaType.UNKNOWN: + case SchemaType.OPTIONAL: + return true; + default: + return false; + } +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/objectWithoutOptionalProperties.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/objectWithoutOptionalProperties.ts new file mode 100644 index 00000000000..a0951f48efc --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/objectWithoutOptionalProperties.ts @@ -0,0 +1,18 @@ +import { object } from "./object"; +import { inferParsedPropertySchema, inferRawObjectFromPropertySchemas, ObjectSchema, PropertySchemas } from "./types"; + +export function objectWithoutOptionalProperties>( + schemas: T +): inferObjectWithoutOptionalPropertiesSchemaFromPropertySchemas { + return object(schemas) as unknown as inferObjectWithoutOptionalPropertiesSchemaFromPropertySchemas; +} + +export type inferObjectWithoutOptionalPropertiesSchemaFromPropertySchemas> = + ObjectSchema< + inferRawObjectFromPropertySchemas, + inferParsedObjectWithoutOptionalPropertiesFromPropertySchemas + >; + +export type inferParsedObjectWithoutOptionalPropertiesFromPropertySchemas> = { + [K in keyof T]: inferParsedPropertySchema; +}; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/property.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/property.ts new file mode 100644 index 00000000000..d245c4b193a --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/property.ts @@ -0,0 +1,23 @@ +import { Schema } from "../../Schema"; + +export function property( + rawKey: RawKey, + valueSchema: Schema +): Property { + return { + rawKey, + valueSchema, + isProperty: true, + }; +} + +export interface Property { + rawKey: RawKey; + valueSchema: Schema; + isProperty: true; +} + +export function isProperty>(maybeProperty: unknown): maybeProperty is O { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + return (maybeProperty as O).isProperty; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/types.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/types.ts new file mode 100644 index 00000000000..17cff4f86dd --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/object/types.ts @@ -0,0 +1,72 @@ +import { BaseSchema, inferParsed, inferRaw, Schema } from "../../Schema"; +import { addQuestionMarksToNullableProperties } from "../../utils/addQuestionMarksToNullableProperties"; +import { ObjectLikeUtils } from "../object-like"; +import { SchemaUtils } from "../schema-utils"; +import { Property } from "./property"; + +export type ObjectSchema = BaseObjectSchema & + ObjectLikeUtils & + ObjectUtils & + SchemaUtils; + +export interface BaseObjectSchema extends BaseSchema { + _getRawProperties: () => Promise<(keyof Raw)[]>; + _getParsedProperties: () => Promise<(keyof Parsed)[]>; +} + +export interface ObjectUtils { + extend: ( + schemas: ObjectSchema + ) => ObjectSchema; +} + +export type inferRawObject> = O extends ObjectSchema ? Raw : never; + +export type inferParsedObject> = O extends ObjectSchema + ? Parsed + : never; + +export type inferObjectSchemaFromPropertySchemas> = ObjectSchema< + inferRawObjectFromPropertySchemas, + inferParsedObjectFromPropertySchemas +>; + +export type inferRawObjectFromPropertySchemas> = + addQuestionMarksToNullableProperties<{ + [ParsedKey in keyof T as inferRawKey]: inferRawPropertySchema; + }>; + +export type inferParsedObjectFromPropertySchemas> = + addQuestionMarksToNullableProperties<{ + [K in keyof T]: inferParsedPropertySchema; + }>; + +export type PropertySchemas = Record< + ParsedKeys, + Property | Schema +>; + +export type inferRawPropertySchema

| Schema> = P extends Property< + any, + infer Raw, + any +> + ? Raw + : P extends Schema + ? inferRaw

+ : never; + +export type inferParsedPropertySchema

| Schema> = P extends Property< + any, + any, + infer Parsed +> + ? Parsed + : P extends Schema + ? inferParsed

+ : never; + +export type inferRawKey< + ParsedKey extends string | number | symbol, + P extends Property | Schema +> = P extends Property ? Raw : ParsedKey; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/any.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/any.ts new file mode 100644 index 00000000000..fcaeb04255a --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/any.ts @@ -0,0 +1,4 @@ +import { SchemaType } from "../../Schema"; +import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator"; + +export const any = createIdentitySchemaCreator(SchemaType.ANY, (value) => ({ ok: true, value })); diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/boolean.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/boolean.ts new file mode 100644 index 00000000000..fad60562120 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/boolean.ts @@ -0,0 +1,25 @@ +import { SchemaType } from "../../Schema"; +import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; + +export const boolean = createIdentitySchemaCreator( + SchemaType.BOOLEAN, + (value, { breadcrumbsPrefix = [] } = {}) => { + if (typeof value === "boolean") { + return { + ok: true, + value, + }; + } else { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(value, "boolean"), + }, + ], + }; + } + } +); diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/index.ts new file mode 100644 index 00000000000..788f9416bfe --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/index.ts @@ -0,0 +1,5 @@ +export { any } from "./any"; +export { boolean } from "./boolean"; +export { number } from "./number"; +export { string } from "./string"; +export { unknown } from "./unknown"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/number.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/number.ts new file mode 100644 index 00000000000..c2689456936 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/number.ts @@ -0,0 +1,25 @@ +import { SchemaType } from "../../Schema"; +import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; + +export const number = createIdentitySchemaCreator( + SchemaType.NUMBER, + (value, { breadcrumbsPrefix = [] } = {}) => { + if (typeof value === "number") { + return { + ok: true, + value, + }; + } else { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(value, "number"), + }, + ], + }; + } + } +); diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/string.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/string.ts new file mode 100644 index 00000000000..949f1f2a630 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/string.ts @@ -0,0 +1,25 @@ +import { SchemaType } from "../../Schema"; +import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; + +export const string = createIdentitySchemaCreator( + SchemaType.STRING, + (value, { breadcrumbsPrefix = [] } = {}) => { + if (typeof value === "string") { + return { + ok: true, + value, + }; + } else { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(value, "string"), + }, + ], + }; + } + } +); diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/unknown.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/unknown.ts new file mode 100644 index 00000000000..4d5249571f5 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/primitives/unknown.ts @@ -0,0 +1,4 @@ +import { SchemaType } from "../../Schema"; +import { createIdentitySchemaCreator } from "../../utils/createIdentitySchemaCreator"; + +export const unknown = createIdentitySchemaCreator(SchemaType.UNKNOWN, (value) => ({ ok: true, value })); diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/record/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/record/index.ts new file mode 100644 index 00000000000..82e25c5c2af --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/record/index.ts @@ -0,0 +1,2 @@ +export { record } from "./record"; +export type { BaseRecordSchema, RecordSchema } from "./types"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/record/record.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/record/record.ts new file mode 100644 index 00000000000..ac1cd22ade0 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/record/record.ts @@ -0,0 +1,131 @@ +import { MaybeValid, Schema, SchemaType, ValidationError } from "../../Schema"; +import { entries } from "../../utils/entries"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; +import { isPlainObject } from "../../utils/isPlainObject"; +import { MaybePromise } from "../../utils/MaybePromise"; +import { maybeSkipValidation } from "../../utils/maybeSkipValidation"; +import { getSchemaUtils } from "../schema-utils"; +import { BaseRecordSchema, RecordSchema } from "./types"; + +export function record( + keySchema: Schema, + valueSchema: Schema +): RecordSchema { + const baseSchema: BaseRecordSchema = { + parse: async (raw, opts) => { + return validateAndTransformRecord({ + value: raw, + isKeyNumeric: (await keySchema.getType()) === SchemaType.NUMBER, + transformKey: (key) => + keySchema.parse(key, { + ...opts, + breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `${key} (key)`], + }), + transformValue: (value, key) => + valueSchema.parse(value, { + ...opts, + breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `${key}`], + }), + breadcrumbsPrefix: opts?.breadcrumbsPrefix, + }); + }, + json: async (parsed, opts) => { + return validateAndTransformRecord({ + value: parsed, + isKeyNumeric: (await keySchema.getType()) === SchemaType.NUMBER, + transformKey: (key) => + keySchema.json(key, { + ...opts, + breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `${key} (key)`], + }), + transformValue: (value, key) => + valueSchema.json(value, { + ...opts, + breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), `${key}`], + }), + breadcrumbsPrefix: opts?.breadcrumbsPrefix, + }); + }, + getType: () => SchemaType.RECORD, + }; + + return { + ...maybeSkipValidation(baseSchema), + ...getSchemaUtils(baseSchema), + }; +} + +async function validateAndTransformRecord({ + value, + isKeyNumeric, + transformKey, + transformValue, + breadcrumbsPrefix = [], +}: { + value: unknown; + isKeyNumeric: boolean; + transformKey: (key: string | number) => MaybePromise>; + transformValue: (value: unknown, key: string | number) => MaybePromise>; + breadcrumbsPrefix: string[] | undefined; +}): Promise>> { + if (!isPlainObject(value)) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(value, "object"), + }, + ], + }; + } + + return entries(value).reduce>>>( + async (accPromise, [stringKey, value]) => { + // skip nullish keys + if (value == null) { + return accPromise; + } + + const acc = await accPromise; + + let key: string | number = stringKey; + if (isKeyNumeric) { + const numberKey = stringKey.length > 0 ? Number(stringKey) : NaN; + if (!isNaN(numberKey)) { + key = numberKey; + } + } + const transformedKey = await transformKey(key); + + const transformedValue = await transformValue(value, key); + + if (acc.ok && transformedKey.ok && transformedValue.ok) { + return { + ok: true, + value: { + ...acc.value, + [transformedKey.value]: transformedValue.value, + }, + }; + } + + const errors: ValidationError[] = []; + if (!acc.ok) { + errors.push(...acc.errors); + } + if (!transformedKey.ok) { + errors.push(...transformedKey.errors); + } + if (!transformedValue.ok) { + errors.push(...transformedValue.errors); + } + + return { + ok: false, + errors, + }; + }, + Promise.resolve({ ok: true, value: {} as Record }) + ); +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/record/types.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/record/types.ts new file mode 100644 index 00000000000..eb82cc7f65c --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/record/types.ts @@ -0,0 +1,17 @@ +import { BaseSchema } from "../../Schema"; +import { SchemaUtils } from "../schema-utils"; + +export type RecordSchema< + RawKey extends string | number, + RawValue, + ParsedKey extends string | number, + ParsedValue +> = BaseRecordSchema & + SchemaUtils, Record>; + +export type BaseRecordSchema< + RawKey extends string | number, + RawValue, + ParsedKey extends string | number, + ParsedValue +> = BaseSchema, Record>; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/JsonError.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/JsonError.ts new file mode 100644 index 00000000000..2b89ca0e7ad --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/JsonError.ts @@ -0,0 +1,9 @@ +import { ValidationError } from "../../Schema"; +import { stringifyValidationError } from "./stringifyValidationErrors"; + +export class JsonError extends Error { + constructor(public readonly errors: ValidationError[]) { + super(errors.map(stringifyValidationError).join("; ")); + Object.setPrototypeOf(this, JsonError.prototype); + } +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/ParseError.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/ParseError.ts new file mode 100644 index 00000000000..d056eb45cf7 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/ParseError.ts @@ -0,0 +1,9 @@ +import { ValidationError } from "../../Schema"; +import { stringifyValidationError } from "./stringifyValidationErrors"; + +export class ParseError extends Error { + constructor(public readonly errors: ValidationError[]) { + super(errors.map(stringifyValidationError).join("; ")); + Object.setPrototypeOf(this, ParseError.prototype); + } +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/getSchemaUtils.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/getSchemaUtils.ts new file mode 100644 index 00000000000..0c0d379d800 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/getSchemaUtils.ts @@ -0,0 +1,99 @@ +import { BaseSchema, Schema, SchemaOptions, SchemaType } from "../../Schema"; +import { JsonError } from "./JsonError"; +import { ParseError } from "./ParseError"; + +export interface SchemaUtils { + optional: () => Schema; + transform: (transformer: SchemaTransformer) => Schema; + parseOrThrow: (raw: unknown, opts?: SchemaOptions) => Promise; + jsonOrThrow: (raw: unknown, opts?: SchemaOptions) => Promise; +} + +export interface SchemaTransformer { + transform: (parsed: Parsed) => Transformed; + untransform: (transformed: any) => Parsed; +} + +export function getSchemaUtils(schema: BaseSchema): SchemaUtils { + return { + optional: () => optional(schema), + transform: (transformer) => transform(schema, transformer), + parseOrThrow: async (raw, opts) => { + const parsed = await schema.parse(raw, opts); + if (parsed.ok) { + return parsed.value; + } + throw new ParseError(parsed.errors); + }, + jsonOrThrow: async (parsed, opts) => { + const raw = await schema.json(parsed, opts); + if (raw.ok) { + return raw.value; + } + throw new JsonError(raw.errors); + }, + }; +} + +/** + * schema utils are defined in one file to resolve issues with circular imports + */ + +export function optional( + schema: BaseSchema +): Schema { + const baseSchema: BaseSchema = { + parse: (raw, opts) => { + if (raw == null) { + return { + ok: true, + value: undefined, + }; + } + return schema.parse(raw, opts); + }, + json: (parsed, opts) => { + if (parsed == null) { + return { + ok: true, + value: null, + }; + } + return schema.json(parsed, opts); + }, + getType: () => SchemaType.OPTIONAL, + }; + + return { + ...baseSchema, + ...getSchemaUtils(baseSchema), + }; +} + +export function transform( + schema: BaseSchema, + transformer: SchemaTransformer +): Schema { + const baseSchema: BaseSchema = { + parse: async (raw, opts) => { + const parsed = await schema.parse(raw, opts); + if (!parsed.ok) { + return parsed; + } + return { + ok: true, + value: transformer.transform(parsed.value), + }; + }, + json: async (transformed, opts) => { + const parsed = await transformer.untransform(transformed); + return schema.json(parsed, opts); + }, + getType: () => schema.getType(), + }; + + return { + ...baseSchema, + ...getSchemaUtils(baseSchema), + }; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/index.ts new file mode 100644 index 00000000000..aa04e051dfa --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/index.ts @@ -0,0 +1,4 @@ +export { getSchemaUtils, optional, transform } from "./getSchemaUtils"; +export type { SchemaUtils } from "./getSchemaUtils"; +export { JsonError } from "./JsonError"; +export { ParseError } from "./ParseError"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/stringifyValidationErrors.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/stringifyValidationErrors.ts new file mode 100644 index 00000000000..4160f0a2617 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/schema-utils/stringifyValidationErrors.ts @@ -0,0 +1,8 @@ +import { ValidationError } from "../../Schema"; + +export function stringifyValidationError(error: ValidationError): string { + if (error.path.length === 0) { + return error.message; + } + return `${error.path.join(" -> ")}: ${error.message}`; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/set/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/set/index.ts new file mode 100644 index 00000000000..f3310e8bdad --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/set/index.ts @@ -0,0 +1 @@ +export { set } from "./set"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/set/set.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/set/set.ts new file mode 100644 index 00000000000..3113bcba307 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/set/set.ts @@ -0,0 +1,43 @@ +import { BaseSchema, Schema, SchemaType } from "../../Schema"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; +import { maybeSkipValidation } from "../../utils/maybeSkipValidation"; +import { list } from "../list"; +import { getSchemaUtils } from "../schema-utils"; + +export function set(schema: Schema): Schema> { + const listSchema = list(schema); + const baseSchema: BaseSchema> = { + parse: async (raw, opts) => { + const parsedList = await listSchema.parse(raw, opts); + if (parsedList.ok) { + return { + ok: true, + value: new Set(parsedList.value), + }; + } else { + return parsedList; + } + }, + json: async (parsed, opts) => { + if (!(parsed instanceof Set)) { + return { + ok: false, + errors: [ + { + path: opts?.breadcrumbsPrefix ?? [], + message: getErrorMessageForIncorrectType(parsed, "Set"), + }, + ], + }; + } + const jsonList = await listSchema.json([...parsed], opts); + return jsonList; + }, + getType: () => SchemaType.SET, + }; + + return { + ...maybeSkipValidation(baseSchema), + ...getSchemaUtils(baseSchema), + }; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/index.ts new file mode 100644 index 00000000000..75b71cb3565 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/index.ts @@ -0,0 +1,6 @@ +export type { + inferParsedUnidiscriminatedUnionSchema, + inferRawUnidiscriminatedUnionSchema, + UndiscriminatedUnionSchema, +} from "./types"; +export { undiscriminatedUnion } from "./undiscriminatedUnion"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/types.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/types.ts new file mode 100644 index 00000000000..43e7108a060 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/types.ts @@ -0,0 +1,10 @@ +import { inferParsed, inferRaw, Schema } from "../../Schema"; + +export type UndiscriminatedUnionSchema = Schema< + inferRawUnidiscriminatedUnionSchema, + inferParsedUnidiscriminatedUnionSchema +>; + +export type inferRawUnidiscriminatedUnionSchema = inferRaw; + +export type inferParsedUnidiscriminatedUnionSchema = inferParsed; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/undiscriminatedUnion.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/undiscriminatedUnion.ts new file mode 100644 index 00000000000..771dc6a7efa --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/undiscriminated-union/undiscriminatedUnion.ts @@ -0,0 +1,61 @@ +import { BaseSchema, MaybeValid, Schema, SchemaOptions, SchemaType, ValidationError } from "../../Schema"; +import { MaybePromise } from "../../utils/MaybePromise"; +import { maybeSkipValidation } from "../../utils/maybeSkipValidation"; +import { getSchemaUtils } from "../schema-utils"; +import { inferParsedUnidiscriminatedUnionSchema, inferRawUnidiscriminatedUnionSchema } from "./types"; + +export function undiscriminatedUnion, ...Schema[]]>( + schemas: Schemas +): Schema, inferParsedUnidiscriminatedUnionSchema> { + const baseSchema: BaseSchema< + inferRawUnidiscriminatedUnionSchema, + inferParsedUnidiscriminatedUnionSchema + > = { + parse: async (raw, opts) => { + return validateAndTransformUndiscriminatedUnion>( + (schema, opts) => schema.parse(raw, opts), + schemas, + opts + ); + }, + json: async (parsed, opts) => { + return validateAndTransformUndiscriminatedUnion>( + (schema, opts) => schema.json(parsed, opts), + schemas, + opts + ); + }, + getType: () => SchemaType.UNDISCRIMINATED_UNION, + }; + + return { + ...maybeSkipValidation(baseSchema), + ...getSchemaUtils(baseSchema), + }; +} + +async function validateAndTransformUndiscriminatedUnion( + transform: (schema: Schema, opts: SchemaOptions) => MaybePromise>, + schemas: Schema[], + opts: SchemaOptions | undefined +): Promise> { + const errors: ValidationError[] = []; + for (const [index, schema] of schemas.entries()) { + const transformed = await transform(schema, { ...opts, skipValidation: false }); + if (transformed.ok) { + return transformed; + } else { + for (const error of transformed.errors) { + errors.push({ + path: error.path, + message: `[Variant ${index}] ${error.message}`, + }); + } + } + } + + return { + ok: false, + errors, + }; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/discriminant.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/discriminant.ts new file mode 100644 index 00000000000..55065bc8946 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/discriminant.ts @@ -0,0 +1,14 @@ +export function discriminant( + parsedDiscriminant: ParsedDiscriminant, + rawDiscriminant: RawDiscriminant +): Discriminant { + return { + parsedDiscriminant, + rawDiscriminant, + }; +} + +export interface Discriminant { + parsedDiscriminant: ParsedDiscriminant; + rawDiscriminant: RawDiscriminant; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/index.ts new file mode 100644 index 00000000000..85fc008a2d8 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/index.ts @@ -0,0 +1,10 @@ +export { discriminant } from "./discriminant"; +export type { Discriminant } from "./discriminant"; +export type { + inferParsedDiscriminant, + inferParsedUnion, + inferRawDiscriminant, + inferRawUnion, + UnionSubtypes, +} from "./types"; +export { union } from "./union"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/types.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/types.ts new file mode 100644 index 00000000000..6f82c868b2d --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/types.ts @@ -0,0 +1,26 @@ +import { inferParsedObject, inferRawObject, ObjectSchema } from "../object"; +import { Discriminant } from "./discriminant"; + +export type UnionSubtypes = { + [K in DiscriminantValues]: ObjectSchema; +}; + +export type inferRawUnion, U extends UnionSubtypes> = { + [K in keyof U]: Record, K> & inferRawObject; +}[keyof U]; + +export type inferParsedUnion, U extends UnionSubtypes> = { + [K in keyof U]: Record, K> & inferParsedObject; +}[keyof U]; + +export type inferRawDiscriminant> = D extends string + ? D + : D extends Discriminant + ? Raw + : never; + +export type inferParsedDiscriminant> = D extends string + ? D + : D extends Discriminant + ? Parsed + : never; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/union.ts b/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/union.ts new file mode 100644 index 00000000000..ed659beb62d --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/builders/union/union.ts @@ -0,0 +1,173 @@ +import { BaseSchema, MaybeValid, SchemaType } from "../../Schema"; +import { getErrorMessageForIncorrectType } from "../../utils/getErrorMessageForIncorrectType"; +import { isPlainObject } from "../../utils/isPlainObject"; +import { keys } from "../../utils/keys"; +import { MaybePromise } from "../../utils/MaybePromise"; +import { maybeSkipValidation } from "../../utils/maybeSkipValidation"; +import { enum_ } from "../enum"; +import { ObjectSchema } from "../object"; +import { getObjectLikeUtils, ObjectLikeSchema } from "../object-like"; +import { getSchemaUtils } from "../schema-utils"; +import { Discriminant } from "./discriminant"; +import { inferParsedDiscriminant, inferParsedUnion, inferRawDiscriminant, inferRawUnion, UnionSubtypes } from "./types"; + +export function union, U extends UnionSubtypes>( + discriminant: D, + union: U +): ObjectLikeSchema, inferParsedUnion> { + const rawDiscriminant = + typeof discriminant === "string" ? discriminant : (discriminant.rawDiscriminant as inferRawDiscriminant); + const parsedDiscriminant = + typeof discriminant === "string" + ? discriminant + : (discriminant.parsedDiscriminant as inferParsedDiscriminant); + + const discriminantValueSchema = enum_(keys(union) as string[]); + + const baseSchema: BaseSchema, inferParsedUnion> = { + parse: async (raw, opts) => { + return transformAndValidateUnion({ + value: raw, + discriminant: rawDiscriminant, + transformedDiscriminant: parsedDiscriminant, + transformDiscriminantValue: (discriminantValue) => + discriminantValueSchema.parse(discriminantValue, { + allowUnrecognizedEnumValues: opts?.allowUnrecognizedUnionMembers, + breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), rawDiscriminant], + }), + getAdditionalPropertiesSchema: (discriminantValue) => union[discriminantValue], + allowUnrecognizedUnionMembers: opts?.allowUnrecognizedUnionMembers, + transformAdditionalProperties: (additionalProperties, additionalPropertiesSchema) => + additionalPropertiesSchema.parse(additionalProperties, opts), + breadcrumbsPrefix: opts?.breadcrumbsPrefix, + }); + }, + json: async (parsed, opts) => { + return transformAndValidateUnion({ + value: parsed, + discriminant: parsedDiscriminant, + transformedDiscriminant: rawDiscriminant, + transformDiscriminantValue: (discriminantValue) => + discriminantValueSchema.json(discriminantValue, { + allowUnrecognizedEnumValues: opts?.allowUnrecognizedUnionMembers, + breadcrumbsPrefix: [...(opts?.breadcrumbsPrefix ?? []), parsedDiscriminant], + }), + getAdditionalPropertiesSchema: (discriminantValue) => union[discriminantValue], + allowUnrecognizedUnionMembers: opts?.allowUnrecognizedUnionMembers, + transformAdditionalProperties: (additionalProperties, additionalPropertiesSchema) => + additionalPropertiesSchema.json(additionalProperties, opts), + breadcrumbsPrefix: opts?.breadcrumbsPrefix, + }); + }, + getType: () => SchemaType.UNION, + }; + + return { + ...maybeSkipValidation(baseSchema), + ...getSchemaUtils(baseSchema), + ...getObjectLikeUtils(baseSchema), + }; +} + +async function transformAndValidateUnion< + TransformedDiscriminant extends string, + TransformedDiscriminantValue extends string, + TransformedAdditionalProperties +>({ + value, + discriminant, + transformedDiscriminant, + transformDiscriminantValue, + getAdditionalPropertiesSchema, + allowUnrecognizedUnionMembers = false, + transformAdditionalProperties, + breadcrumbsPrefix = [], +}: { + value: unknown; + discriminant: string; + transformedDiscriminant: TransformedDiscriminant; + transformDiscriminantValue: (discriminantValue: unknown) => MaybePromise>; + getAdditionalPropertiesSchema: (discriminantValue: string) => ObjectSchema | undefined; + allowUnrecognizedUnionMembers: boolean | undefined; + transformAdditionalProperties: ( + additionalProperties: unknown, + additionalPropertiesSchema: ObjectSchema + ) => MaybePromise>; + breadcrumbsPrefix: string[] | undefined; +}): Promise< + MaybeValid & TransformedAdditionalProperties> +> { + if (!isPlainObject(value)) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: getErrorMessageForIncorrectType(value, "object"), + }, + ], + }; + } + + const { [discriminant]: discriminantValue, ...additionalProperties } = value; + + if (discriminantValue == null) { + return { + ok: false, + errors: [ + { + path: breadcrumbsPrefix, + message: `Missing discriminant ("${discriminant}")`, + }, + ], + }; + } + + const transformedDiscriminantValue = await transformDiscriminantValue(discriminantValue); + if (!transformedDiscriminantValue.ok) { + return { + ok: false, + errors: transformedDiscriminantValue.errors, + }; + } + + const additionalPropertiesSchema = getAdditionalPropertiesSchema(transformedDiscriminantValue.value); + + if (additionalPropertiesSchema == null) { + if (allowUnrecognizedUnionMembers) { + return { + ok: true, + value: { + [transformedDiscriminant]: transformedDiscriminantValue.value, + ...additionalProperties, + } as Record & TransformedAdditionalProperties, + }; + } else { + return { + ok: false, + errors: [ + { + path: [...breadcrumbsPrefix, discriminant], + message: "Unexpected discriminant value", + }, + ], + }; + } + } + + const transformedAdditionalProperties = await transformAdditionalProperties( + additionalProperties, + additionalPropertiesSchema + ); + if (!transformedAdditionalProperties.ok) { + return transformedAdditionalProperties; + } + + return { + ok: true, + value: { + [transformedDiscriminant]: discriminantValue, + ...transformedAdditionalProperties.value, + } as Record & TransformedAdditionalProperties, + }; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/index.ts b/packages/docs-config-sdk/src/sdk/core/schemas/index.ts new file mode 100644 index 00000000000..5429d8b43eb --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/index.ts @@ -0,0 +1,2 @@ +export * from "./builders"; +export type { inferParsed, inferRaw, Schema, SchemaOptions } from "./Schema"; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/utils/MaybePromise.ts b/packages/docs-config-sdk/src/sdk/core/schemas/utils/MaybePromise.ts new file mode 100644 index 00000000000..9cd354b3418 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/utils/MaybePromise.ts @@ -0,0 +1 @@ +export type MaybePromise = T | Promise; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/utils/addQuestionMarksToNullableProperties.ts b/packages/docs-config-sdk/src/sdk/core/schemas/utils/addQuestionMarksToNullableProperties.ts new file mode 100644 index 00000000000..4111d703cd0 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/utils/addQuestionMarksToNullableProperties.ts @@ -0,0 +1,15 @@ +export type addQuestionMarksToNullableProperties = { + [K in OptionalKeys]?: T[K]; +} & Pick>; + +export type OptionalKeys = { + [K in keyof T]-?: undefined extends T[K] + ? K + : null extends T[K] + ? K + : 1 extends (any extends T[K] ? 0 : 1) + ? never + : K; +}[keyof T]; + +export type RequiredKeys = Exclude>; diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/utils/createIdentitySchemaCreator.ts b/packages/docs-config-sdk/src/sdk/core/schemas/utils/createIdentitySchemaCreator.ts new file mode 100644 index 00000000000..de107cf5ee1 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/utils/createIdentitySchemaCreator.ts @@ -0,0 +1,21 @@ +import { getSchemaUtils } from "../builders/schema-utils"; +import { BaseSchema, MaybeValid, Schema, SchemaOptions, SchemaType } from "../Schema"; +import { maybeSkipValidation } from "./maybeSkipValidation"; + +export function createIdentitySchemaCreator( + schemaType: SchemaType, + validate: (value: unknown, opts?: SchemaOptions) => MaybeValid +): () => Schema { + return () => { + const baseSchema: BaseSchema = { + parse: validate, + json: validate, + getType: () => schemaType, + }; + + return { + ...maybeSkipValidation(baseSchema), + ...getSchemaUtils(baseSchema), + }; + }; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/utils/entries.ts b/packages/docs-config-sdk/src/sdk/core/schemas/utils/entries.ts new file mode 100644 index 00000000000..e122952137d --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/utils/entries.ts @@ -0,0 +1,3 @@ +export function entries(object: T): [keyof T, T[keyof T]][] { + return Object.entries(object) as [keyof T, T[keyof T]][]; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/utils/filterObject.ts b/packages/docs-config-sdk/src/sdk/core/schemas/utils/filterObject.ts new file mode 100644 index 00000000000..2c25a3455bc --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/utils/filterObject.ts @@ -0,0 +1,10 @@ +export function filterObject(obj: T, keysToInclude: K[]): Pick { + const keysToIncludeSet = new Set(keysToInclude); + return Object.entries(obj).reduce((acc, [key, value]) => { + if (keysToIncludeSet.has(key as K)) { + acc[key as K] = value; + } + return acc; + // eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter + }, {} as Pick); +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/utils/getErrorMessageForIncorrectType.ts b/packages/docs-config-sdk/src/sdk/core/schemas/utils/getErrorMessageForIncorrectType.ts new file mode 100644 index 00000000000..438012df418 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/utils/getErrorMessageForIncorrectType.ts @@ -0,0 +1,21 @@ +export function getErrorMessageForIncorrectType(value: unknown, expectedType: string): string { + return `Expected ${expectedType}. Received ${getTypeAsString(value)}.`; +} + +function getTypeAsString(value: unknown): string { + if (Array.isArray(value)) { + return "list"; + } + if (value === null) { + return "null"; + } + switch (typeof value) { + case "string": + return `"${value}"`; + case "number": + case "boolean": + case "undefined": + return `${value}`; + } + return typeof value; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/utils/isPlainObject.ts b/packages/docs-config-sdk/src/sdk/core/schemas/utils/isPlainObject.ts new file mode 100644 index 00000000000..db82a722c35 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/utils/isPlainObject.ts @@ -0,0 +1,17 @@ +// borrowed from https://github.com/lodash/lodash/blob/master/isPlainObject.js +export function isPlainObject(value: unknown): value is Record { + if (typeof value !== "object" || value === null) { + return false; + } + + if (Object.getPrototypeOf(value) === null) { + return true; + } + + let proto = value; + while (Object.getPrototypeOf(proto) !== null) { + proto = Object.getPrototypeOf(proto); + } + + return Object.getPrototypeOf(value) === proto; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/utils/keys.ts b/packages/docs-config-sdk/src/sdk/core/schemas/utils/keys.ts new file mode 100644 index 00000000000..01867098287 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/utils/keys.ts @@ -0,0 +1,3 @@ +export function keys(object: T): (keyof T)[] { + return Object.keys(object) as (keyof T)[]; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/utils/maybeSkipValidation.ts b/packages/docs-config-sdk/src/sdk/core/schemas/utils/maybeSkipValidation.ts new file mode 100644 index 00000000000..99c02c32bda --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/utils/maybeSkipValidation.ts @@ -0,0 +1,39 @@ +import { BaseSchema, MaybeValid, SchemaOptions } from "../Schema"; +import { MaybePromise } from "./MaybePromise"; + +export function maybeSkipValidation, Raw, Parsed>(schema: S): S { + return { + ...schema, + json: transformAndMaybeSkipValidation(schema.json), + parse: transformAndMaybeSkipValidation(schema.parse), + }; +} + +function transformAndMaybeSkipValidation( + transform: (value: unknown, opts?: SchemaOptions) => MaybePromise> +): (value: unknown, opts?: SchemaOptions) => MaybePromise> { + return async (value, opts): Promise> => { + const transformed = await transform(value, opts); + const { skipValidation = false } = opts ?? {}; + if (!transformed.ok && skipValidation) { + // eslint-disable-next-line no-console + console.warn( + [ + "Failed to validate.", + ...transformed.errors.map( + (error) => + " - " + + (error.path.length > 0 ? `${error.path.join(".")}: ${error.message}` : error.message) + ), + ].join("\n") + ); + + return { + ok: true, + value: value as T, + }; + } else { + return transformed; + } + }; +} diff --git a/packages/docs-config-sdk/src/sdk/core/schemas/utils/partition.ts b/packages/docs-config-sdk/src/sdk/core/schemas/utils/partition.ts new file mode 100644 index 00000000000..f58d6f3d35f --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/core/schemas/utils/partition.ts @@ -0,0 +1,12 @@ +export function partition(items: readonly T[], predicate: (item: T) => boolean): [T[], T[]] { + const trueItems: T[] = [], + falseItems: T[] = []; + for (const item of items) { + if (predicate(item)) { + trueItems.push(item); + } else { + falseItems.push(item); + } + } + return [trueItems, falseItems]; +} diff --git a/packages/docs-config-sdk/src/sdk/errors/FernDocsConfigError.ts b/packages/docs-config-sdk/src/sdk/errors/FernDocsConfigError.ts new file mode 100644 index 00000000000..c7d4d9b46cb --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/errors/FernDocsConfigError.ts @@ -0,0 +1,45 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export class FernDocsConfigError extends Error { + readonly statusCode?: number; + readonly body?: unknown; + + constructor({ message, statusCode, body }: { message?: string; statusCode?: number; body?: unknown }) { + super(buildMessage({ message, statusCode, body })); + Object.setPrototypeOf(this, FernDocsConfigError.prototype); + if (statusCode != null) { + this.statusCode = statusCode; + } + + if (body !== undefined) { + this.body = body; + } + } +} + +function buildMessage({ + message, + statusCode, + body, +}: { + message: string | undefined; + statusCode: number | undefined; + body: unknown | undefined; +}): string { + let lines: string[] = []; + if (message != null) { + lines.push(message); + } + + if (statusCode != null) { + lines.push(`Status code: ${statusCode.toString()}`); + } + + if (body != null) { + lines.push(`Body: ${JSON.stringify(body, undefined, 2)}`); + } + + return lines.join("\n"); +} diff --git a/packages/docs-config-sdk/src/sdk/errors/FernDocsConfigTimeoutError.ts b/packages/docs-config-sdk/src/sdk/errors/FernDocsConfigTimeoutError.ts new file mode 100644 index 00000000000..b51f6e6aa55 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/errors/FernDocsConfigTimeoutError.ts @@ -0,0 +1,10 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export class FernDocsConfigTimeoutError extends Error { + constructor() { + super("Timeout"); + Object.setPrototypeOf(this, FernDocsConfigTimeoutError.prototype); + } +} diff --git a/packages/docs-config-sdk/src/sdk/errors/index.ts b/packages/docs-config-sdk/src/sdk/errors/index.ts new file mode 100644 index 00000000000..3eb978f8573 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/errors/index.ts @@ -0,0 +1,2 @@ +export { FernDocsConfigError } from "./FernDocsConfigError"; +export { FernDocsConfigTimeoutError } from "./FernDocsConfigTimeoutError"; diff --git a/packages/docs-config-sdk/src/sdk/index.ts b/packages/docs-config-sdk/src/sdk/index.ts new file mode 100644 index 00000000000..9449cccdf7b --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/index.ts @@ -0,0 +1,2 @@ +export * as FernDocsConfig from "./api"; +export { FernDocsConfigError, FernDocsConfigTimeoutError } from "./errors"; diff --git a/packages/docs-config-sdk/src/sdk/serialization/index.ts b/packages/docs-config-sdk/src/sdk/serialization/index.ts new file mode 100644 index 00000000000..3e5335fe421 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/index.ts @@ -0,0 +1 @@ +export * from "./resources"; diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/index.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/index.ts new file mode 100644 index 00000000000..eea524d6557 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/index.ts @@ -0,0 +1 @@ +export * from "./types"; diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ApiSectionConfiguration.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ApiSectionConfiguration.ts new file mode 100644 index 00000000000..42d2a7a8aa7 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ApiSectionConfiguration.ts @@ -0,0 +1,28 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const ApiSectionConfiguration: core.serialization.ObjectSchema< + serializers.ApiSectionConfiguration.Raw, + FernDocsConfig.ApiSectionConfiguration +> = core.serialization.object({ + api: core.serialization.string(), + apiName: core.serialization.property("api-name", core.serialization.string().optional()), + audiences: core.serialization.list(core.serialization.string()).optional(), + displayErrors: core.serialization.property("display-errors", core.serialization.boolean().optional()), + snippets: core.serialization.lazyObject(async () => (await import("../../..")).SnippetsConfiguration).optional(), +}); + +export declare namespace ApiSectionConfiguration { + interface Raw { + api: string; + "api-name"?: string | null; + audiences?: string[] | null; + "display-errors"?: boolean | null; + snippets?: serializers.SnippetsConfiguration.Raw | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/AudiencesConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/AudiencesConfig.ts new file mode 100644 index 00000000000..bff3ef57186 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/AudiencesConfig.ts @@ -0,0 +1,19 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const AudiencesConfig: core.serialization.Schema< + serializers.AudiencesConfig.Raw, + FernDocsConfig.AudiencesConfig +> = core.serialization.undiscriminatedUnion([ + core.serialization.string(), + core.serialization.list(core.serialization.string()), +]); + +export declare namespace AudiencesConfig { + type Raw = string | string[]; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorConfig.ts new file mode 100644 index 00000000000..dba1a218d73 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorConfig.ts @@ -0,0 +1,17 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const ColorConfig: core.serialization.Schema = + core.serialization.undiscriminatedUnion([ + core.serialization.string(), + core.serialization.lazyObject(async () => (await import("../../..")).ColorThemedConfig), + ]); + +export declare namespace ColorConfig { + type Raw = string | serializers.ColorThemedConfig.Raw; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorThemedConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorThemedConfig.ts new file mode 100644 index 00000000000..2add2682a76 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorThemedConfig.ts @@ -0,0 +1,22 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const ColorThemedConfig: core.serialization.ObjectSchema< + serializers.ColorThemedConfig.Raw, + FernDocsConfig.ColorThemedConfig +> = core.serialization.object({ + dark: core.serialization.string().optional(), + light: core.serialization.string().optional(), +}); + +export declare namespace ColorThemedConfig { + interface Raw { + dark?: string | null; + light?: string | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorsConfiguration.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorsConfiguration.ts new file mode 100644 index 00000000000..0315767e7a3 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/ColorsConfiguration.ts @@ -0,0 +1,22 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const ColorsConfiguration: core.serialization.ObjectSchema< + serializers.ColorsConfiguration.Raw, + FernDocsConfig.ColorsConfiguration +> = core.serialization.object({ + accentPrimary: core.serialization.lazy(async () => (await import("../../..")).ColorConfig).optional(), + background: core.serialization.lazy(async () => (await import("../../..")).ColorConfig).optional(), +}); + +export declare namespace ColorsConfiguration { + interface Raw { + accentPrimary?: serializers.ColorConfig.Raw | null; + background?: serializers.ColorConfig.Raw | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/CssConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/CssConfig.ts new file mode 100644 index 00000000000..970b5f754d5 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/CssConfig.ts @@ -0,0 +1,17 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const CssConfig: core.serialization.Schema = + core.serialization.undiscriminatedUnion([ + core.serialization.string(), + core.serialization.list(core.serialization.string()), + ]); + +export declare namespace CssConfig { + type Raw = string | string[]; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsConfiguration.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsConfiguration.ts new file mode 100644 index 00000000000..77ba07df0b4 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsConfiguration.ts @@ -0,0 +1,58 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const DocsConfiguration: core.serialization.ObjectSchema< + serializers.DocsConfiguration.Raw, + FernDocsConfig.DocsConfiguration +> = core.serialization.object({ + instances: core.serialization.list( + core.serialization.lazyObject(async () => (await import("../../..")).DocsInstances) + ), + navigation: core.serialization.lazy(async () => (await import("../../..")).NavigationConfig).optional(), + tabs: core.serialization + .record( + core.serialization.lazy(async () => (await import("../../..")).TabId), + core.serialization.lazyObject(async () => (await import("../../..")).TabConfig) + ) + .optional(), + versions: core.serialization + .list(core.serialization.lazyObject(async () => (await import("../../..")).VersionConfig)) + .optional(), + title: core.serialization.string().optional(), + logo: core.serialization.lazyObject(async () => (await import("../../..")).LogoConfiguration).optional(), + favicon: core.serialization.string().optional(), + backgroundImage: core.serialization.property("background-image", core.serialization.string().optional()), + colors: core.serialization.lazyObject(async () => (await import("../../..")).ColorsConfiguration).optional(), + navbarLinks: core.serialization.property( + "navbar-links", + core.serialization.list(core.serialization.lazy(async () => (await import("../../..")).NavbarLink)).optional() + ), + typography: core.serialization.lazyObject(async () => (await import("../../..")).DocsTypographyConfig).optional(), + layout: core.serialization.lazyObject(async () => (await import("../../..")).LayoutConfig).optional(), + css: core.serialization.lazy(async () => (await import("../../..")).CssConfig).optional(), + js: core.serialization.lazy(async () => (await import("../../..")).JsConfig).optional(), +}); + +export declare namespace DocsConfiguration { + interface Raw { + instances: serializers.DocsInstances.Raw[]; + navigation?: serializers.NavigationConfig.Raw | null; + tabs?: Record | null; + versions?: serializers.VersionConfig.Raw[] | null; + title?: string | null; + logo?: serializers.LogoConfiguration.Raw | null; + favicon?: string | null; + "background-image"?: string | null; + colors?: serializers.ColorsConfiguration.Raw | null; + "navbar-links"?: serializers.NavbarLink.Raw[] | null; + typography?: serializers.DocsTypographyConfig.Raw | null; + layout?: serializers.LayoutConfig.Raw | null; + css?: serializers.CssConfig.Raw | null; + js?: serializers.JsConfig.Raw | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsInstances.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsInstances.ts new file mode 100644 index 00000000000..e80cbf31826 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsInstances.ts @@ -0,0 +1,31 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const DocsInstances: core.serialization.ObjectSchema< + serializers.DocsInstances.Raw, + FernDocsConfig.DocsInstances +> = core.serialization.object({ + url: core.serialization.string(), + customDomain: core.serialization.property("custom-domain", core.serialization.string().optional()), + audiences: core.serialization.lazy(async () => (await import("../../..")).AudiencesConfig).optional(), + private: core.serialization.boolean().optional(), + editThisPage: core.serialization.property( + "edit-this-page", + core.serialization.lazyObject(async () => (await import("../../..")).EditThisPageConfig).optional() + ), +}); + +export declare namespace DocsInstances { + interface Raw { + url: string; + "custom-domain"?: string | null; + audiences?: serializers.AudiencesConfig.Raw | null; + private?: boolean | null; + "edit-this-page"?: serializers.EditThisPageConfig.Raw | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsTypographyConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsTypographyConfig.ts new file mode 100644 index 00000000000..32ba43cf559 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/DocsTypographyConfig.ts @@ -0,0 +1,24 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const DocsTypographyConfig: core.serialization.ObjectSchema< + serializers.DocsTypographyConfig.Raw, + FernDocsConfig.DocsTypographyConfig +> = core.serialization.object({ + headingsFont: core.serialization.lazyObject(async () => (await import("../../..")).FontConfig).optional(), + bodyFont: core.serialization.lazyObject(async () => (await import("../../..")).FontConfig).optional(), + codeFont: core.serialization.lazyObject(async () => (await import("../../..")).FontConfig).optional(), +}); + +export declare namespace DocsTypographyConfig { + interface Raw { + headingsFont?: serializers.FontConfig.Raw | null; + bodyFont?: serializers.FontConfig.Raw | null; + codeFont?: serializers.FontConfig.Raw | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/EditThisPageConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/EditThisPageConfig.ts new file mode 100644 index 00000000000..87f23fc57e2 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/EditThisPageConfig.ts @@ -0,0 +1,20 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const EditThisPageConfig: core.serialization.ObjectSchema< + serializers.EditThisPageConfig.Raw, + FernDocsConfig.EditThisPageConfig +> = core.serialization.object({ + github: core.serialization.lazyObject(async () => (await import("../../..")).GithubEditThisPageConfig).optional(), +}); + +export declare namespace EditThisPageConfig { + interface Raw { + github?: serializers.GithubEditThisPageConfig.Raw | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfig.ts new file mode 100644 index 00000000000..b5f6228b42d --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfig.ts @@ -0,0 +1,37 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const FontConfig: core.serialization.ObjectSchema = + core.serialization.object({ + name: core.serialization.string().optional(), + path: core.serialization.string().optional(), + weight: core.serialization.string().optional(), + style: core.serialization.lazy(async () => (await import("../../..")).FontStyle).optional(), + paths: core.serialization + .list(core.serialization.lazy(async () => (await import("../../..")).FontConfigPath)) + .optional(), + display: core.serialization.lazy(async () => (await import("../../..")).FontDisplay).optional(), + fallback: core.serialization.list(core.serialization.string()).optional(), + fontVariationSettings: core.serialization.property( + "font-variation-settings", + core.serialization.string().optional() + ), + }); + +export declare namespace FontConfig { + interface Raw { + name?: string | null; + path?: string | null; + weight?: string | null; + style?: serializers.FontStyle.Raw | null; + paths?: serializers.FontConfigPath.Raw[] | null; + display?: serializers.FontDisplay.Raw | null; + fallback?: string[] | null; + "font-variation-settings"?: string | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfigPath.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfigPath.ts new file mode 100644 index 00000000000..6599f639cbc --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfigPath.ts @@ -0,0 +1,17 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const FontConfigPath: core.serialization.Schema = + core.serialization.undiscriminatedUnion([ + core.serialization.string(), + core.serialization.lazyObject(async () => (await import("../../..")).FontConfigVariant), + ]); + +export declare namespace FontConfigPath { + type Raw = string | serializers.FontConfigVariant.Raw; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfigVariant.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfigVariant.ts new file mode 100644 index 00000000000..d226f61984e --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontConfigVariant.ts @@ -0,0 +1,24 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const FontConfigVariant: core.serialization.ObjectSchema< + serializers.FontConfigVariant.Raw, + FernDocsConfig.FontConfigVariant +> = core.serialization.object({ + path: core.serialization.string(), + weight: core.serialization.string().optional(), + style: core.serialization.lazy(async () => (await import("../../..")).FontStyle).optional(), +}); + +export declare namespace FontConfigVariant { + interface Raw { + path: string; + weight?: string | null; + style?: serializers.FontStyle.Raw | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontDisplay.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontDisplay.ts new file mode 100644 index 00000000000..7e7d70ab353 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontDisplay.ts @@ -0,0 +1,14 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const FontDisplay: core.serialization.Schema = + core.serialization.enum_(["auto", "block", "swap", "fallback", "optional"]); + +export declare namespace FontDisplay { + type Raw = "auto" | "block" | "swap" | "fallback" | "optional"; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontStyle.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontStyle.ts new file mode 100644 index 00000000000..6d8f1108768 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/FontStyle.ts @@ -0,0 +1,14 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const FontStyle: core.serialization.Schema = + core.serialization.enum_(["normal", "italic"]); + +export declare namespace FontStyle { + type Raw = "normal" | "italic"; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/GithubEditThisPageConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/GithubEditThisPageConfig.ts new file mode 100644 index 00000000000..f73456a0057 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/GithubEditThisPageConfig.ts @@ -0,0 +1,26 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const GithubEditThisPageConfig: core.serialization.ObjectSchema< + serializers.GithubEditThisPageConfig.Raw, + FernDocsConfig.GithubEditThisPageConfig +> = core.serialization.object({ + host: core.serialization.string().optional(), + owner: core.serialization.string(), + repo: core.serialization.string(), + branch: core.serialization.string().optional(), +}); + +export declare namespace GithubEditThisPageConfig { + interface Raw { + host?: string | null; + owner: string; + repo: string; + branch?: string | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsConfig.ts new file mode 100644 index 00000000000..bed70663eec --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsConfig.ts @@ -0,0 +1,17 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const JsConfig: core.serialization.Schema = + core.serialization.undiscriminatedUnion([ + core.serialization.lazy(async () => (await import("../../..")).JsConfigOptions), + core.serialization.list(core.serialization.lazy(async () => (await import("../../..")).JsConfigOptions)), + ]); + +export declare namespace JsConfig { + type Raw = serializers.JsConfigOptions.Raw | serializers.JsConfigOptions.Raw[]; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsConfigOptions.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsConfigOptions.ts new file mode 100644 index 00000000000..75ac2bfde6a --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsConfigOptions.ts @@ -0,0 +1,19 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const JsConfigOptions: core.serialization.Schema< + serializers.JsConfigOptions.Raw, + FernDocsConfig.JsConfigOptions +> = core.serialization.undiscriminatedUnion([ + core.serialization.lazyObject(async () => (await import("../../..")).JsRemoteConfig), + core.serialization.lazy(async () => (await import("../../..")).JsFileConfig), +]); + +export declare namespace JsConfigOptions { + type Raw = serializers.JsRemoteConfig.Raw | serializers.JsFileConfig.Raw; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsFileConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsFileConfig.ts new file mode 100644 index 00000000000..422ad4aabd9 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsFileConfig.ts @@ -0,0 +1,17 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const JsFileConfig: core.serialization.Schema = + core.serialization.undiscriminatedUnion([ + core.serialization.string(), + core.serialization.lazyObject(async () => (await import("../../..")).JsFileConfigSettings), + ]); + +export declare namespace JsFileConfig { + type Raw = string | serializers.JsFileConfigSettings.Raw; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsFileConfigSettings.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsFileConfigSettings.ts new file mode 100644 index 00000000000..392697e4b5e --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsFileConfigSettings.ts @@ -0,0 +1,22 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const JsFileConfigSettings: core.serialization.ObjectSchema< + serializers.JsFileConfigSettings.Raw, + FernDocsConfig.JsFileConfigSettings +> = core.serialization.object({ + path: core.serialization.string(), + strategy: core.serialization.lazy(async () => (await import("../../..")).JsScriptStrategy).optional(), +}); + +export declare namespace JsFileConfigSettings { + interface Raw { + path: string; + strategy?: serializers.JsScriptStrategy.Raw | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsRemoteConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsRemoteConfig.ts new file mode 100644 index 00000000000..97f406af170 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsRemoteConfig.ts @@ -0,0 +1,22 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const JsRemoteConfig: core.serialization.ObjectSchema< + serializers.JsRemoteConfig.Raw, + FernDocsConfig.JsRemoteConfig +> = core.serialization.object({ + url: core.serialization.string(), + strategy: core.serialization.lazy(async () => (await import("../../..")).JsScriptStrategy).optional(), +}); + +export declare namespace JsRemoteConfig { + interface Raw { + url: string; + strategy?: serializers.JsScriptStrategy.Raw | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsScriptStrategy.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsScriptStrategy.ts new file mode 100644 index 00000000000..d7deccd1750 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/JsScriptStrategy.ts @@ -0,0 +1,16 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const JsScriptStrategy: core.serialization.Schema< + serializers.JsScriptStrategy.Raw, + FernDocsConfig.JsScriptStrategy +> = core.serialization.enum_(["beforeInteractive", "afterInteractive", "lazyOnload"]); + +export declare namespace JsScriptStrategy { + type Raw = "beforeInteractive" | "afterInteractive" | "lazyOnload"; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LayoutConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LayoutConfig.ts new file mode 100644 index 00000000000..b0a4159d802 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LayoutConfig.ts @@ -0,0 +1,34 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const LayoutConfig: core.serialization.ObjectSchema = + core.serialization.object({ + pageWidth: core.serialization.property("page-width", core.serialization.string().optional()), + contentWidth: core.serialization.property("content-width", core.serialization.string().optional()), + sidebarWidth: core.serialization.property("sidebar-width", core.serialization.string().optional()), + headerHeight: core.serialization.property("header-height", core.serialization.string().optional()), + searchbarPlacement: core.serialization.property( + "searchbar-placement", + core.serialization.lazy(async () => (await import("../../..")).SidebarOrHeaderPlacement).optional() + ), + tabsPlacement: core.serialization.property( + "tabs-placement", + core.serialization.lazy(async () => (await import("../../..")).SidebarOrHeaderPlacement).optional() + ), + }); + +export declare namespace LayoutConfig { + interface Raw { + "page-width"?: string | null; + "content-width"?: string | null; + "sidebar-width"?: string | null; + "header-height"?: string | null; + "searchbar-placement"?: serializers.SidebarOrHeaderPlacement.Raw | null; + "tabs-placement"?: serializers.SidebarOrHeaderPlacement.Raw | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LinkConfiguration.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LinkConfiguration.ts new file mode 100644 index 00000000000..0dfc51ecdcf --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LinkConfiguration.ts @@ -0,0 +1,22 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const LinkConfiguration: core.serialization.ObjectSchema< + serializers.LinkConfiguration.Raw, + FernDocsConfig.LinkConfiguration +> = core.serialization.object({ + link: core.serialization.string(), + href: core.serialization.string(), +}); + +export declare namespace LinkConfiguration { + interface Raw { + link: string; + href: string; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LogoConfiguration.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LogoConfiguration.ts new file mode 100644 index 00000000000..bb534369dd7 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/LogoConfiguration.ts @@ -0,0 +1,26 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const LogoConfiguration: core.serialization.ObjectSchema< + serializers.LogoConfiguration.Raw, + FernDocsConfig.LogoConfiguration +> = core.serialization.object({ + dark: core.serialization.string().optional(), + light: core.serialization.string().optional(), + height: core.serialization.number().optional(), + href: core.serialization.string().optional(), +}); + +export declare namespace LogoConfiguration { + interface Raw { + dark?: string | null; + light?: string | null; + height?: number | null; + href?: string | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavbarLink.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavbarLink.ts new file mode 100644 index 00000000000..6959148deb1 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavbarLink.ts @@ -0,0 +1,45 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const NavbarLink: core.serialization.Schema = + core.serialization + .union("type", { + filled: core.serialization.lazyObject(async () => (await import("../../..")).NavbarLinkConfiguration), + outlined: core.serialization.lazyObject(async () => (await import("../../..")).NavbarLinkConfiguration), + minimal: core.serialization.lazyObject(async () => (await import("../../..")).NavbarLinkConfiguration), + primary: core.serialization.lazyObject(async () => (await import("../../..")).NavbarLinkConfiguration), + secondary: core.serialization.lazyObject(async () => (await import("../../..")).NavbarLinkConfiguration), + }) + .transform({ + transform: (value) => value, + untransform: (value) => value, + }); + +export declare namespace NavbarLink { + type Raw = NavbarLink.Filled | NavbarLink.Outlined | NavbarLink.Minimal | NavbarLink.Primary | NavbarLink.Secondary; + + interface Filled extends serializers.NavbarLinkConfiguration.Raw { + type: "filled"; + } + + interface Outlined extends serializers.NavbarLinkConfiguration.Raw { + type: "outlined"; + } + + interface Minimal extends serializers.NavbarLinkConfiguration.Raw { + type: "minimal"; + } + + interface Primary extends serializers.NavbarLinkConfiguration.Raw { + type: "primary"; + } + + interface Secondary extends serializers.NavbarLinkConfiguration.Raw { + type: "secondary"; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavbarLinkConfiguration.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavbarLinkConfiguration.ts new file mode 100644 index 00000000000..48f052a14d2 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavbarLinkConfiguration.ts @@ -0,0 +1,24 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const NavbarLinkConfiguration: core.serialization.ObjectSchema< + serializers.NavbarLinkConfiguration.Raw, + FernDocsConfig.NavbarLinkConfiguration +> = core.serialization.object({ + href: core.serialization.string().optional(), + url: core.serialization.string().optional(), + text: core.serialization.string(), +}); + +export declare namespace NavbarLinkConfiguration { + interface Raw { + href?: string | null; + url?: string | null; + text: string; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavigationConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavigationConfig.ts new file mode 100644 index 00000000000..ad6a0dea5a0 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavigationConfig.ts @@ -0,0 +1,19 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const NavigationConfig: core.serialization.Schema< + serializers.NavigationConfig.Raw, + FernDocsConfig.NavigationConfig +> = core.serialization.undiscriminatedUnion([ + core.serialization.lazy(async () => (await import("../../..")).UntabbedNavigationConifg), + core.serialization.lazy(async () => (await import("../../..")).TabbedNavigationConfig), +]); + +export declare namespace NavigationConfig { + type Raw = serializers.UntabbedNavigationConifg.Raw | serializers.TabbedNavigationConfig.Raw; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavigationItem.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavigationItem.ts new file mode 100644 index 00000000000..17b87cd4a2d --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/NavigationItem.ts @@ -0,0 +1,23 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const NavigationItem: core.serialization.Schema = + core.serialization.undiscriminatedUnion([ + core.serialization.lazyObject(async () => (await import("../../..")).PageConfiguration), + core.serialization.lazyObject(async () => (await import("../../..")).SectionConfiguration), + core.serialization.lazyObject(async () => (await import("../../..")).ApiSectionConfiguration), + core.serialization.lazyObject(async () => (await import("../../..")).LinkConfiguration), + ]); + +export declare namespace NavigationItem { + type Raw = + | serializers.PageConfiguration.Raw + | serializers.SectionConfiguration.Raw + | serializers.ApiSectionConfiguration.Raw + | serializers.LinkConfiguration.Raw; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/PageConfiguration.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/PageConfiguration.ts new file mode 100644 index 00000000000..b4af4a12fb5 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/PageConfiguration.ts @@ -0,0 +1,24 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const PageConfiguration: core.serialization.ObjectSchema< + serializers.PageConfiguration.Raw, + FernDocsConfig.PageConfiguration +> = core.serialization.object({ + page: core.serialization.string(), + path: core.serialization.string(), + slug: core.serialization.string().optional(), +}); + +export declare namespace PageConfiguration { + interface Raw { + page: string; + path: string; + slug?: string | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SectionConfiguration.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SectionConfiguration.ts new file mode 100644 index 00000000000..c1a71d26ec9 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SectionConfiguration.ts @@ -0,0 +1,26 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const SectionConfiguration: core.serialization.ObjectSchema< + serializers.SectionConfiguration.Raw, + FernDocsConfig.SectionConfiguration +> = core.serialization.object({ + section: core.serialization.string(), + contents: core.serialization.list(core.serialization.lazy(async () => (await import("../../..")).NavigationItem)), + collapsed: core.serialization.boolean().optional(), + slug: core.serialization.string().optional(), +}); + +export declare namespace SectionConfiguration { + interface Raw { + section: string; + contents: serializers.NavigationItem.Raw[]; + collapsed?: boolean | null; + slug?: string | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SidebarOrHeaderPlacement.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SidebarOrHeaderPlacement.ts new file mode 100644 index 00000000000..a636c2d4bf9 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SidebarOrHeaderPlacement.ts @@ -0,0 +1,16 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const SidebarOrHeaderPlacement: core.serialization.Schema< + serializers.SidebarOrHeaderPlacement.Raw, + FernDocsConfig.SidebarOrHeaderPlacement +> = core.serialization.enum_(["header", "sidebar"]); + +export declare namespace SidebarOrHeaderPlacement { + type Raw = "header" | "sidebar"; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SnippetsConfiguration.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SnippetsConfiguration.ts new file mode 100644 index 00000000000..da4ab7942c5 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/SnippetsConfiguration.ts @@ -0,0 +1,26 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const SnippetsConfiguration: core.serialization.ObjectSchema< + serializers.SnippetsConfiguration.Raw, + FernDocsConfig.SnippetsConfiguration +> = core.serialization.object({ + python: core.serialization.string().optional(), + typescript: core.serialization.string().optional(), + go: core.serialization.string().optional(), + java: core.serialization.string().optional(), +}); + +export declare namespace SnippetsConfiguration { + interface Raw { + python?: string | null; + typescript?: string | null; + go?: string | null; + java?: string | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabConfig.ts new file mode 100644 index 00000000000..d5418793dd1 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabConfig.ts @@ -0,0 +1,22 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const TabConfig: core.serialization.ObjectSchema = + core.serialization.object({ + displayName: core.serialization.property("display-name", core.serialization.string()), + icon: core.serialization.string(), + slug: core.serialization.string().optional(), + }); + +export declare namespace TabConfig { + interface Raw { + "display-name": string; + icon: string; + slug?: string | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabId.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabId.ts new file mode 100644 index 00000000000..cfb1022642c --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabId.ts @@ -0,0 +1,14 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const TabId: core.serialization.Schema = + core.serialization.string(); + +export declare namespace TabId { + type Raw = string; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabbedNavigationConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabbedNavigationConfig.ts new file mode 100644 index 00000000000..d5655132678 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabbedNavigationConfig.ts @@ -0,0 +1,16 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const TabbedNavigationConfig: core.serialization.Schema< + serializers.TabbedNavigationConfig.Raw, + FernDocsConfig.TabbedNavigationConfig +> = core.serialization.list(core.serialization.lazyObject(async () => (await import("../../..")).TabbedNavigationItem)); + +export declare namespace TabbedNavigationConfig { + type Raw = serializers.TabbedNavigationItem.Raw[]; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabbedNavigationItem.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabbedNavigationItem.ts new file mode 100644 index 00000000000..75d09b1aa04 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/TabbedNavigationItem.ts @@ -0,0 +1,22 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const TabbedNavigationItem: core.serialization.ObjectSchema< + serializers.TabbedNavigationItem.Raw, + FernDocsConfig.TabbedNavigationItem +> = core.serialization.object({ + tab: core.serialization.lazy(async () => (await import("../../..")).TabId), + layout: core.serialization.list(core.serialization.lazy(async () => (await import("../../..")).NavigationItem)), +}); + +export declare namespace TabbedNavigationItem { + interface Raw { + tab: serializers.TabId.Raw; + layout: serializers.NavigationItem.Raw[]; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/UntabbedNavigationConifg.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/UntabbedNavigationConifg.ts new file mode 100644 index 00000000000..0f14eef3586 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/UntabbedNavigationConifg.ts @@ -0,0 +1,16 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const UntabbedNavigationConifg: core.serialization.Schema< + serializers.UntabbedNavigationConifg.Raw, + FernDocsConfig.UntabbedNavigationConifg +> = core.serialization.list(core.serialization.lazy(async () => (await import("../../..")).NavigationItem)); + +export declare namespace UntabbedNavigationConifg { + type Raw = serializers.NavigationItem.Raw[]; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionAvailability.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionAvailability.ts new file mode 100644 index 00000000000..85aea0cad50 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionAvailability.ts @@ -0,0 +1,16 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const VersionAvailability: core.serialization.Schema< + serializers.VersionAvailability.Raw, + FernDocsConfig.VersionAvailability +> = core.serialization.enum_(["deprecated", "ga", "stable", "beta"]); + +export declare namespace VersionAvailability { + type Raw = "deprecated" | "ga" | "stable" | "beta"; +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionConfig.ts new file mode 100644 index 00000000000..1a37768d4c0 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionConfig.ts @@ -0,0 +1,26 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const VersionConfig: core.serialization.ObjectSchema< + serializers.VersionConfig.Raw, + FernDocsConfig.VersionConfig +> = core.serialization.object({ + displayName: core.serialization.property("display-name", core.serialization.string()), + path: core.serialization.string(), + slug: core.serialization.string().optional(), + availability: core.serialization.lazy(async () => (await import("../../..")).VersionAvailability).optional(), +}); + +export declare namespace VersionConfig { + interface Raw { + "display-name": string; + path: string; + slug?: string | null; + availability?: serializers.VersionAvailability.Raw | null; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionFileConfig.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionFileConfig.ts new file mode 100644 index 00000000000..7dbc91662a7 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/VersionFileConfig.ts @@ -0,0 +1,20 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as FernDocsConfig from "../../../../api"; +import * as core from "../../../../core"; + +export const VersionFileConfig: core.serialization.ObjectSchema< + serializers.VersionFileConfig.Raw, + FernDocsConfig.VersionFileConfig +> = core.serialization.object({ + navigation: core.serialization.lazy(async () => (await import("../../..")).NavigationConfig), +}); + +export declare namespace VersionFileConfig { + interface Raw { + navigation: serializers.NavigationConfig.Raw; + } +} diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/index.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/index.ts new file mode 100644 index 00000000000..0f292b9d80e --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/docs/types/index.ts @@ -0,0 +1,41 @@ +export * from "./DocsConfiguration"; +export * from "./TabId"; +export * from "./TabConfig"; +export * from "./DocsInstances"; +export * from "./EditThisPageConfig"; +export * from "./GithubEditThisPageConfig"; +export * from "./AudiencesConfig"; +export * from "./VersionConfig"; +export * from "./VersionAvailability"; +export * from "./VersionFileConfig"; +export * from "./NavigationConfig"; +export * from "./UntabbedNavigationConifg"; +export * from "./TabbedNavigationConfig"; +export * from "./TabbedNavigationItem"; +export * from "./NavigationItem"; +export * from "./LogoConfiguration"; +export * from "./DocsTypographyConfig"; +export * from "./LayoutConfig"; +export * from "./SidebarOrHeaderPlacement"; +export * from "./FontConfig"; +export * from "./FontStyle"; +export * from "./FontDisplay"; +export * from "./FontConfigPath"; +export * from "./FontConfigVariant"; +export * from "./PageConfiguration"; +export * from "./SectionConfiguration"; +export * from "./ApiSectionConfiguration"; +export * from "./LinkConfiguration"; +export * from "./SnippetsConfiguration"; +export * from "./ColorsConfiguration"; +export * from "./ColorConfig"; +export * from "./ColorThemedConfig"; +export * from "./NavbarLink"; +export * from "./NavbarLinkConfiguration"; +export * from "./CssConfig"; +export * from "./JsConfig"; +export * from "./JsConfigOptions"; +export * from "./JsRemoteConfig"; +export * from "./JsFileConfig"; +export * from "./JsFileConfigSettings"; +export * from "./JsScriptStrategy"; diff --git a/packages/docs-config-sdk/src/sdk/serialization/resources/index.ts b/packages/docs-config-sdk/src/sdk/serialization/resources/index.ts new file mode 100644 index 00000000000..e6bc80c6a88 --- /dev/null +++ b/packages/docs-config-sdk/src/sdk/serialization/resources/index.ts @@ -0,0 +1,2 @@ +export * as docs from "./docs"; +export * from "./docs/types"; diff --git a/packages/docs-config-sdk/tsconfig.json b/packages/docs-config-sdk/tsconfig.json new file mode 100644 index 00000000000..eb37bb4f427 --- /dev/null +++ b/packages/docs-config-sdk/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../shared/tsconfig.shared.json", + "compilerOptions": { "composite": true, "outDir": "lib", "rootDir": "src" }, + "include": ["./src"] +} diff --git a/shared/.prettierignore b/shared/.prettierignore index 3e5fd0b467c..b48163ab847 100644 --- a/shared/.prettierignore +++ b/shared/.prettierignore @@ -1,4 +1,5 @@ ../packages/ir-sdk/** +../packages/docs-config-sdk/** ../packages/cli/openapi-ir-sdk/** ../packages/seed/src/config/** ../scripts/** diff --git a/yarn.lock b/yarn.lock index 8aca5e24b27..b307ac31f87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2541,16 +2541,31 @@ __metadata: languageName: unknown linkType: soft +"@fern-api/docs-config-sdk@workspace:*, @fern-api/docs-config-sdk@workspace:packages/docs-config-sdk": + version: 0.0.0-use.local + resolution: "@fern-api/docs-config-sdk@workspace:packages/docs-config-sdk" + dependencies: + "@types/jest": ^29.0.3 + "@types/node": ^18.7.18 + depcheck: ^1.4.6 + eslint: ^8.56.0 + jest: ^29.7.0 + organize-imports-cli: ^0.10.0 + prettier: ^2.7.1 + typescript: 4.6.4 + languageName: unknown + linkType: soft + "@fern-api/docs-configuration@workspace:*, @fern-api/docs-configuration@workspace:packages/cli/config-management/docs-configuration": version: 0.0.0-use.local resolution: "@fern-api/docs-configuration@workspace:packages/cli/config-management/docs-configuration" dependencies: "@fern-api/config-management-commons": "workspace:*" "@fern-api/core-utils": "workspace:*" + "@fern-api/docs-config-sdk": "workspace:*" "@fern-api/fdr-sdk": 0.50.8-1-gace1ff5 "@fern-api/fs-utils": "workspace:*" "@fern-api/task-context": "workspace:*" - "@fern-fern/docs-config": 0.0.76 "@types/jest": ^29.0.3 "@types/js-yaml": ^4.0.8 "@types/node": ^18.7.18 @@ -2571,6 +2586,7 @@ __metadata: resolution: "@fern-api/docs-preview@workspace:packages/cli/docs-preview" dependencies: "@fern-api/core-utils": "workspace:*" + "@fern-api/docs-config-sdk": "workspace:*" "@fern-api/docs-configuration": "workspace:*" "@fern-api/fdr-sdk": 0.50.8-1-gace1ff5 "@fern-api/fs-utils": "workspace:*" @@ -2578,7 +2594,6 @@ __metadata: "@fern-api/register": "workspace:*" "@fern-api/task-context": "workspace:*" "@fern-api/workspace-loader": "workspace:*" - "@fern-fern/docs-config": 0.0.76 "@types/cors": ^2.8.13 "@types/express": ^4.17.20 "@types/jest": ^29.0.3 @@ -2838,6 +2853,7 @@ __metadata: dependencies: "@fern-api/auth": "workspace:*" "@fern-api/core": "workspace:*" + "@fern-api/docs-config-sdk": "workspace:*" "@fern-api/fs-utils": "workspace:*" "@fern-api/generators-configuration": "workspace:*" "@fern-api/login": "workspace:*" @@ -2845,7 +2861,6 @@ __metadata: "@fern-api/task-context": "workspace:*" "@fern-api/yaml-formatter": "workspace:*" "@fern-api/yaml-schema": "workspace:*" - "@fern-fern/docs-config": 0.0.76 "@types/fs-extra": ^11.0.1 "@types/jest": ^29.0.3 "@types/js-yaml": ^4.0.8 @@ -3374,6 +3389,7 @@ __metadata: "@fern-api/config-management-commons": "workspace:*" "@fern-api/core": "workspace:*" "@fern-api/core-utils": "workspace:*" + "@fern-api/docs-config-sdk": "workspace:*" "@fern-api/docs-configuration": "workspace:*" "@fern-api/fdr-sdk": 0.50.8-1-gace1ff5 "@fern-api/fs-utils": "workspace:*" @@ -3385,7 +3401,6 @@ __metadata: "@fern-api/register": "workspace:*" "@fern-api/task-context": "workspace:*" "@fern-api/workspace-loader": "workspace:*" - "@fern-fern/docs-config": 0.0.76 "@fern-fern/fiddle-sdk": ^0.0.411 "@types/decompress": ^4.2.7 "@types/jest": ^29.0.3 @@ -3617,6 +3632,7 @@ __metadata: "@fern-api/core": "workspace:*" "@fern-api/core-utils": "workspace:*" "@fern-api/dependencies-configuration": "workspace:*" + "@fern-api/docs-config-sdk": "workspace:*" "@fern-api/fs-utils": "workspace:*" "@fern-api/generators-configuration": "workspace:*" "@fern-api/openapi-ir-sdk": "workspace:*" @@ -3626,7 +3642,6 @@ __metadata: "@fern-api/semver-utils": "workspace:*" "@fern-api/task-context": "workspace:*" "@fern-api/yaml-schema": "workspace:*" - "@fern-fern/docs-config": 0.0.76 "@fern-fern/fiddle-sdk": ^0.0.411 "@types/jest": ^29.0.3 "@types/js-yaml": ^4.0.8 @@ -3678,10 +3693,10 @@ __metadata: dependencies: "@fern-api/config-management-commons": "workspace:*" "@fern-api/core-utils": "workspace:*" + "@fern-api/docs-config-sdk": "workspace:*" "@fern-api/fs-utils": "workspace:*" "@fern-api/semver-utils": "workspace:*" "@fern-api/task-context": "workspace:*" - "@fern-fern/docs-config": 0.0.76 "@fern-fern/legacy-docs-config": 0.0.58 "@types/inquirer": ^9.0.3 "@types/jest": ^29.0.3 @@ -3710,9 +3725,9 @@ __metadata: resolution: "@fern-api/yaml-schema@workspace:packages/cli/yaml/yaml-schema" dependencies: "@fern-api/core-utils": "workspace:*" + "@fern-api/docs-config-sdk": "workspace:*" "@fern-api/fs-utils": "workspace:*" "@fern-api/ir-sdk": "workspace:*" - "@fern-fern/docs-config": 0.0.76 "@types/jest": ^29.0.3 "@types/js-yaml": ^4.0.8 "@types/node": ^18.7.18 @@ -3727,13 +3742,6 @@ __metadata: languageName: unknown linkType: soft -"@fern-fern/docs-config@npm:0.0.76": - version: 0.0.76 - resolution: "@fern-fern/docs-config@npm:0.0.76" - checksum: 97fbaacd7ac1fc32de42b73781a07a8b44fb8a3756cad7ed07143e20e2f9ddff12532f633e0e7d008e887bd2bc9fd449edd6927774327a5609afa8fee6f08286 - languageName: node - linkType: hard - "@fern-fern/fiddle-sdk@npm:^0.0.411": version: 0.0.411 resolution: "@fern-fern/fiddle-sdk@npm:0.0.411"