docs: enhance how references are generated (#5805)

* adjusted configurations

* enhancements to tool and configurations

* change reference in docs

* fixed issue in workflows reference

* added project name

* more optimizations

* fix context error

* added a types reference

* resolved missing types

* fix reference reflection types not having children

* add an expand url parameter

* added new option to the README

* added details about new option
This commit is contained in:
Shahed Nasser authored and GitHub committed 2023-12-05 15:29:41 +02:00
1 parent a418e6cebc
commit 892d737c1f
4358 files changed
+947851 -534735

No files matched your search

@@ -11,6 +11,9 @@ const require = createRequire(import.meta.url)
const referenceNames = process.argv.slice(2) || ["all"] const referenceNames = process.argv.slice(2) || ["all"]
const basePath = path.join(require.resolve("typedoc-config"), "..") const basePath = path.join(require.resolve("typedoc-config"), "..")
let generatedCount = 0
let totalCount = 0
let ranMerger = false
if (!referenceNames.length) { if (!referenceNames.length) {
console.error( console.error(
@@ -27,15 +30,19 @@ referenceNames.forEach((name) => {
// `typedoc-config` directory, except for files starting // `typedoc-config` directory, except for files starting
// with `_` // with `_`
const files = globSync("[^_]**.js", { const files = globSync("[^_]**.js", {
cwd: path.join(basePath), cwd: basePath,
}) })
totalCount = files.length
files.forEach((file) => generateReference(file)) files.forEach((file) => generateReference(file))
} else if (name === "merge") {
runMerger()
} else { } else {
totalCount = 1
generateReference(`${name}.js`) generateReference(`${name}.js`)
} }
}) })
function generateReference(referenceName: string) { export function generateReference(referenceName: string) {
const configPathName = path.join(basePath, referenceName) const configPathName = path.join(basePath, referenceName)
// check if the config file exists // check if the config file exists
@@ -54,6 +61,12 @@ function generateReference(referenceName: string) {
typedocProcess.stdout?.on("data", (chunk: string) => { typedocProcess.stdout?.on("data", (chunk: string) => {
formatColoredLog(colorLog, referenceName, chunk.trim()) formatColoredLog(colorLog, referenceName, chunk.trim())
}) })
typedocProcess.on("exit", (code) => {
generatedCount++
if (generatedCount >= totalCount && !ranMerger && code !== 1) {
runMerger()
}
})
typedocProcess.stderr?.on("data", (chunk: string) => { typedocProcess.stderr?.on("data", (chunk: string) => {
// split multiline outputs // split multiline outputs
const split: string[] = chunk.split("\n") const split: string[] = chunk.split("\n")
@@ -79,3 +92,10 @@ function formatColoredLog(
) { ) {
console.log(`${chalkInstance(title)} -> ${message}`) console.log(`${chalkInstance(title)} -> ${message}`)
} }
function runMerger() {
// run merger
console.log(chalk.bgBlueBright("\n\nRunning Merger\n\n"))
ranMerger = true
generateReference("_merger.js")
}
+1
View File
@@ -8,6 +8,7 @@
"scripts": { "scripts": {
"generate:announcement": "ts-node ./doc-change-release.ts", "generate:announcement": "ts-node ./doc-change-release.ts",
"generate:reference": "ts-node ./generate-reference.ts", "generate:reference": "ts-node ./generate-reference.ts",
"merge:references": "yarn generate:reference merge",
"check:freshness": "ts-node ./freshness-check.ts", "check:freshness": "ts-node ./freshness-check.ts",
"generate:message": "ts-node ./get-generate-diff-message.ts" "generate:message": "ts-node ./get-generate-diff-message.ts"
}, },
+2
View File
@@ -8,5 +8,7 @@
"include": ["*.ts"], "include": ["*.ts"],
"ts-node": { "ts-node": {
"esm": true, "esm": true,
"experimentalSpecifierResolution": "node",
"transpileOnly": true
}, },
} }
+9 -2
View File
@@ -5,8 +5,7 @@ const pathPrefix = path.join(__dirname, "..", "..", "..")
/** @type {import('typedoc').TypeDocOptions} */ /** @type {import('typedoc').TypeDocOptions} */
module.exports = { module.exports = {
// extends: [typedocConfig], plugin: ["typedoc-plugin-custom"],
plugin: ["typedoc-plugin-markdown-medusa", "typedoc-plugin-custom"],
readme: "none", readme: "none",
eslintPathName: path.join( eslintPathName: path.join(
pathPrefix, pathPrefix,
@@ -15,6 +14,14 @@ module.exports = {
pluginsResolvePath: path.join(pathPrefix, "www"), pluginsResolvePath: path.join(pathPrefix, "www"),
exclude: [path.join(pathPrefix, "node_modules/**")], exclude: [path.join(pathPrefix, "node_modules/**")],
excludeInternal: true, excludeInternal: true,
excludeExternals: true,
excludeReferences: true,
disableSources: true,
validation: {
notExported: false,
// invalidLink: false,
},
// logLevel: "Error",
// Uncomment this when debugging // Uncomment this when debugging
// showConfig: true, // showConfig: true,
} }
@@ -0,0 +1,412 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path")
const globalTypedocOptions = require("./_base")
const baseSectionsOptions = {
member_sources_definedIn: false,
reflection_hierarchy: false,
member_sources_inheritedFrom: false,
member_sources_implementationOf: false,
reflection_implementedBy: false,
member_signature_sources: false,
reflection_callable: false,
reflection_indexable: false,
reflection_implements: false,
member_signature_title: false,
member_signature_returns: false,
title_reflectionPath: false,
}
const modulesSectionsOptions = {
...baseSectionsOptions,
member_signature_typeParameters: false,
member_declaration_typeParameters: false,
}
const modulesOptions = {
sections: modulesSectionsOptions,
expandMembers: true,
}
/** @type {import('typedoc').TypeDocOptions} */
module.exports = {
...globalTypedocOptions,
entryPoints: [
path.join(__dirname, "..", "..", "typedoc-json-output", "*.json"),
],
entryPointStrategy: "merge",
entryDocument: "_index.mdx",
out: path.join(
__dirname,
"..",
"..",
"..",
"www",
"apps",
"docs",
"content",
"references"
),
name: "references",
indexTitle: "Medusa References",
plugin: [...globalTypedocOptions.plugin, "typedoc-plugin-markdown-medusa"],
excludeReferences: true,
excludeNotDocumented: true,
hideInPageTOC: true,
hideBreadcrumbs: true,
objectLiteralTypeDeclarationStyle: "component",
mdxOutput: true,
maxLevel: 3,
allReflectionsHaveOwnDocument: [
"inventory",
"pricing",
"product",
"stock-location",
"workflows",
],
formatting: {
"*": {
showCommentsAsHeader: true,
sections: baseSectionsOptions,
parameterStyle: "component",
parameterComponent: "ParameterTypes",
mdxImports: [
`import ParameterTypes from "@site/src/components/ParameterTypes"`,
],
},
internal: {
maxLevel: 1,
},
// ENTITIES CONFIG
"^entities": {
reflectionGroups: {
Constructors: false,
Methods: false,
},
frontmatterData: {
displayed_sidebar: "entitiesSidebar",
},
maxLevel: 2,
parameterComponentExtraProps: {
expandUrl:
"https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records",
},
},
"^entities/classes": {
frontmatterData: {
displayed_sidebar: "entitiesSidebar",
slug: "/references/entities/classes/{{alias}}",
},
},
"^entities/.*(Order|Swap|Cart|LineItem)": {
maxLevel: 1,
},
// FULFILLMENT CONFIG
"^fulfillment": {
reflectionGroups: {
Properties: false,
},
frontmatterData: {
displayed_sidebar: "modules",
},
maxLevel: 2,
},
"^fulfillment/.*AbstractFulfillmentService": {
reflectionDescription: `In this document, you’ll learn how to create a fulfillment provider to a Medusa backend and the methods you must implement in it. If you’re unfamiliar with the Shipping architecture in Medusa, make sure to [check out the overview first](https://docs.medusajs.com/modules/carts-and-checkout/shipping).`,
frontmatterData: {
displayed_sidebar: "modules",
slug: "/modules/carts-and-checkout/backend/add-fulfillment-provider",
},
reflectionTitle: {
fullReplacement: "How to Create a Fulfillment Provider",
},
},
// INVENTORY CONFIG
"^inventory": {
...modulesOptions,
frontmatterData: {
displayed_sidebar: "inventoryReference",
},
},
"^IInventoryService/methods": {
reflectionDescription:
"This documentation provides a reference to the `{{alias}}` {{kind}}. This belongs to the Inventory Module.",
frontmatterData: {
displayed_sidebar: "inventoryReference",
slug: "/references/inventory/{{alias}}",
sidebar_label: "{{alias}}",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: "- Inventory Module Reference",
},
},
"^inventory/.*IInventoryService\\.md": {
reflectionDescription:
"This section of the documentation provides a reference to the `IInventoryService` interface’s methods. This is the interface developers use to use the functionalities provided by the Inventory Module.",
frontmatterData: {
displayed_sidebar: "inventoryReference",
slug: "/references/inventory",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: " Reference",
},
},
// JS CLIENT CONFIG
"^js_client": {
sections: {
...baseSectionsOptions,
member_declaration_title: false,
},
reflectionGroups: {
Constructors: false,
},
frontmatterData: {
displayed_sidebar: "jsClientSidebar",
},
parameterComponentExtraProps: {
expandUrl:
"https://docs.medusajs.com/js-client/overview#expanding-fields",
},
maxLevel: 4,
},
"^js_client/classes/": {
frontmatterData: {
displayed_sidebar: "jsClientSidebar",
slug: "/references/js-client/{{alias}}",
},
},
"^js_client/.*AdminOrdersResource": {
maxLevel: 2,
},
"^js_client/.*LineItemsResource": {
maxLevel: 3,
},
"^(js_client/.*modules/.*internal|internal.*/modules)": {
reflectionGroups: {
Constructors: false,
"Type Aliases": false,
Enumerations: false,
"Enumeration Members": false,
Classes: false,
Functions: false,
Interfaces: false,
References: false,
},
},
"^internal.*/.*js_client.*": {
reflectionGroups: {
Constructors: false,
},
frontmatterData: {
displayed_sidebar: "jsClientSidebar",
},
},
// MEDUSA CONFIG
"^medusa": {
frontmatterData: {
displayed_sidebar: "homepage",
},
maxLevel: 2,
parameterComponentExtraProps: {
expandUrl:
"https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records",
},
},
// PRICING CONFIG
"^pricing": {
...modulesOptions,
frontmatterData: {
displayed_sidebar: "pricingReference",
},
},
"^IPricingModuleService/methods": {
reflectionDescription:
"This documentation provides a reference to the `{{alias}}` {{kind}}. This belongs to the Pricing Module.",
frontmatterData: {
displayed_sidebar: "pricingReference",
badge: {
variant: "orange",
text: "Beta",
},
slug: "/references/pricing/{{alias}}",
sidebar_label: "{{alias}}",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: "- Pricing Module Reference",
},
},
"^pricing/.*IPricingModuleService\\.md": {
reflectionDescription:
"This section of the documentation provides a reference to the `IPricingModuleService` interface’s methods. This is the interface developers use to use the functionalities provided by the Pricing Module.",
frontmatterData: {
displayed_sidebar: "pricingReference",
badge: {
variant: "orange",
text: "Beta",
},
slug: "/references/pricing",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: " Reference",
},
},
// PRODUCT CONFIG
"^product": {
...modulesOptions,
frontmatterData: {
displayed_sidebar: "productReference",
},
},
"^IProductModuleService/methods": {
reflectionDescription:
"This documentation provides a reference to the {{alias}} {{kind}}. This belongs to the Product Module.",
frontmatterData: {
displayed_sidebar: "productReference",
badge: {
variant: "orange",
text: "Beta",
},
slug: "/references/product/{{alias}}",
sidebar_label: "{{alias}}",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: "- Product Module Reference",
},
},
"^product/.*IProductModuleService\\.md": {
reflectionDescription:
"This section of the documentation provides a reference to the `IProductModuleService` interface’s methods. This is the interface developers use to use the functionalities provided by the Product Module.",
frontmatterData: {
displayed_sidebar: "productReference",
badge: {
variant: "orange",
text: "Beta",
},
slug: "/references/product",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: " Reference",
},
},
// SERVICES CONFIG
"^services": {
frontmatterData: {
displayed_sidebar: "servicesSidebar",
},
maxLevel: 1,
},
// STOCK LOCATION CONFIG
"^stock-location": {
...modulesOptions,
frontmatterData: {
displayed_sidebar: "stockLocationReference",
},
},
"^IStockLocationService/methods": {
reflectionDescription:
"This documentation provides a reference to the `{{alias}}` {{kind}}. This belongs to the Stock Location Module.",
frontmatterData: {
displayed_sidebar: "stockLocationReference",
slug: "/references/stock-location/{{alias}}",
sidebar_label: "{{alias}}",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: "- Stock Location Module Reference",
},
},
"^stock-location/.*IStockLocationService\\.md": {
reflectionDescription:
"This section of the documentation provides a reference to the `IStockLocationService` interface’s methods. This is the interface developers use to use the functionalities provided by the Stock Location Module.",
frontmatterData: {
displayed_sidebar: "stockLocationReference",
slug: "/references/stock-location",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: " Reference",
},
},
// WORKFLOWS CONFIG
"^workflows": {
expandMembers: true,
sections: {
...baseSectionsOptions,
member_getterSetter: false,
},
frontmatterData: {
displayed_sidebar: "workflowsSidebar",
},
maxLevel: 2,
},
"^modules/workflows\\.md": {
reflectionDescription:
"This section of the documentation provides a reference to the utility functions of the `@medusajs/workflows-sdk` package.",
reflectionGroups: {
Namespaces: false,
Enumerations: false,
Classes: false,
Interfaces: false,
"Type Aliases": false,
Variables: false,
"Enumeration Members": false,
},
frontmatterData: {
displayed_sidebar: "workflowsSidebar",
slug: "/references/workflows",
},
reflectionTitle: {
fullReplacement: "Workflows API Reference",
},
},
"^workflows/functions": {
maxLevel: 1,
reflectionDescription:
"This documentation provides a reference to the `{{alias}}` {{kind}}. It belongs to the `@medusajs/workflows-sdk` package.",
frontmatterData: {
displayed_sidebar: "workflowsSidebar",
slug: "/references/workflows/{{alias}}",
sidebar_label: "{{alias}}",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: "- Workflows API Reference",
},
},
"^workflows/.*classes/.*StepResponse": {
reflectionGroups: {
Properties: false,
},
},
"^workflows/.*transform": {
reflectionGroups: {
"Type Parameters": false,
},
},
},
}
+7 -83
View File
@@ -1,89 +1,13 @@
/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path")
const globalTypedocOptions = require("./_base") const globalTypedocOptions = require("./_base")
const getConfig = require("./utils/get-config")
const pathPrefix = path.join(__dirname, "..", "..", "..") module.exports = (options) => {
return getConfig({
module.exports = ({ ...options,
entryPointPath, tsConfigName: "types.json",
outPath,
tsconfigPath = "",
moduleName = "",
documentsToFormat = [],
extraOptions = {},
}) => {
const formatting = {}
documentsToFormat.forEach(
({ pattern, additionalFormatting, useDefaults = false }) => {
formatting[pattern] = {
...(!useDefaults
? {
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: "Reference",
},
expandMembers: true,
showCommentsAsHeader: true,
parameterStyle: "component",
useTsLinkResolution: false,
sections: {
reflection_typeParameters: false,
member_declaration_typeParameters: false,
reflection_implements: false,
reflection_implementedBy: false,
reflection_callable: false,
reflection_indexable: false,
member_signature_typeParameters: false,
member_signature_sources: false,
member_signature_title: false,
title_reflectionPath: false,
member_sources_definedIn: false,
member_signature_returns: false,
},
reflectionGroups: {
Constructors: false,
Properties: false,
},
parameterComponent: "ParameterTypes",
mdxImports: [
`import ParameterTypes from "@site/src/components/ParameterTypes"`,
],
}
: {
showCommentsAsHeader: true,
sections: {
member_sources_definedIn: false,
reflection_hierarchy: false,
},
parameterStyle: "component",
parameterComponent: "ParameterTypes",
mdxImports: [
`import ParameterTypes from "@site/src/components/ParameterTypes"`,
],
}),
...additionalFormatting,
}
}
)
return {
...globalTypedocOptions,
entryPoints: [path.join(pathPrefix, entryPointPath)],
out: [path.join(pathPrefix, outPath)],
tsconfig: tsconfigPath.length
? path.join(pathPrefix, tsconfigPath)
: path.join(__dirname, "extended-tsconfig", "types.json"),
name: `${moduleName} Reference`,
indexTitle: `${moduleName} Reference`,
entryDocument: "index.md",
entryPointStrategy: "expand", entryPointStrategy: "expand",
hideInPageTOC: true,
hideBreadcrumbs: true,
plugin: [...globalTypedocOptions.plugin, "typedoc-plugin-rename-defaults"], plugin: [...globalTypedocOptions.plugin, "typedoc-plugin-rename-defaults"],
formatting, enableInternalResolve: true,
allReflectionsHaveOwnDocument: true, })
objectLiteralTypeDeclarationStyle: "component",
mdxOutput: true,
...extraOptions,
}
} }
+6 -48
View File
@@ -1,50 +1,8 @@
/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path") const getConfig = require("./utils/get-config")
const globalTypedocOptions = require("./_base")
const pathPrefix = path.join(__dirname, "..", "..", "..") module.exports = getConfig({
entryPointPath: "packages/medusa/src/models/index.ts",
module.exports = { tsConfigName: "medusa.json",
...globalTypedocOptions, name: "entities",
entryPoints: [path.join(pathPrefix, "packages/medusa/src/models/index.ts")], })
out: [path.join(pathPrefix, "www/apps/docs/content/references/entities")],
tsconfig: path.join(__dirname, "extended-tsconfig", "medusa.json"),
name: "Entities Reference",
indexTitle: "Entities Reference",
entryDocument: "index.mdx",
hideInPageTOC: true,
hideBreadcrumbs: true,
formatting: {
"*": {
showCommentsAsHeader: true,
sections: {
member_sources_definedIn: false,
reflection_hierarchy: false,
member_sources_inheritedFrom: false,
member_sources_implementationOf: false,
reflection_implementedBy: false,
member_signature_sources: false,
reflection_callable: false,
reflection_indexable: false,
},
parameterStyle: "component",
parameterComponent: "ParameterTypes",
mdxImports: [
`import ParameterTypes from "@site/src/components/ParameterTypes"`,
],
reflectionGroups: {
Constructors: false,
Methods: false,
},
frontmatterData: {
displayed_sidebar: "entitiesSidebar",
},
},
"(Order|Swap|Cart|LineItem)": {
maxLevel: 1,
},
},
objectLiteralTypeDeclarationStyle: "component",
mdxOutput: true,
maxLevel: 2,
}
@@ -1,64 +1,9 @@
/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path") const getConfig = require("./utils/get-config")
const globalTypedocOptions = require("./_base")
const pathPrefix = path.join(__dirname, "..", "..", "..") module.exports = getConfig({
entryPointPath: "packages/medusa/src/interfaces/fulfillment-service.ts",
module.exports = { tsConfigName: "medusa.json",
...globalTypedocOptions, name: "fulfillment",
entryPoints: [ // enableInternalResolve: true,
path.join( })
pathPrefix,
"packages/medusa/src/interfaces/fulfillment-service.ts"
),
],
out: [path.join(pathPrefix, "www/apps/docs/content/references/fulfillment")],
tsconfig: path.join(__dirname, "extended-tsconfig", "medusa.json"),
name: "Fulfillment Provider Reference",
indexTitle: "Fulfillment Provider Reference",
entryDocument: "_index.mdx",
hideInPageTOC: true,
hideBreadcrumbs: true,
formatting: {
"*": {
showCommentsAsHeader: true,
sections: {
member_sources_definedIn: false,
reflection_hierarchy: false,
member_sources_inheritedFrom: false,
member_sources_implementationOf: false,
reflection_implementedBy: false,
member_signature_sources: false,
reflection_callable: false,
reflection_indexable: false,
reflection_implements: false,
member_signature_title: false,
member_signature_returns: false,
},
parameterStyle: "component",
parameterComponent: "ParameterTypes",
mdxImports: [
`import ParameterTypes from "@site/src/components/ParameterTypes"`,
],
reflectionGroups: {
Properties: false,
},
frontmatterData: {
displayed_sidebar: "modules",
},
},
AbstractFulfillmentService: {
reflectionDescription: `In this document, you’ll learn how to create a fulfillment provider to a Medusa backend and the methods you must implement in it. If you’re unfamiliar with the Shipping architecture in Medusa, make sure to [check out the overview first](https://docs.medusajs.com/modules/carts-and-checkout/shipping).`,
frontmatterData: {
displayed_sidebar: "modules",
slug: "/modules/carts-and-checkout/backend/add-fulfillment-provider",
},
reflectionTitle: {
fullReplacement: "How to Create a Fulfillment Provider",
},
},
},
objectLiteralTypeDeclarationStyle: "component",
mdxOutput: true,
maxLevel: 2,
}
+1 -41
View File
@@ -3,45 +3,5 @@ const modulesConfig = require("./_modules")
module.exports = modulesConfig({ module.exports = modulesConfig({
entryPointPath: "packages/types/src/inventory/service.ts", entryPointPath: "packages/types/src/inventory/service.ts",
outPath: "www/apps/docs/content/references/inventory", name: "inventory",
moduleName: "Inventory Module Reference",
documentsToFormat: [
{
pattern: "*",
useDefaults: true,
additionalFormatting: {
frontmatterData: {
displayed_sidebar: "inventoryReference",
},
},
},
{
pattern: "IInventoryService/methods",
additionalFormatting: {
reflectionDescription:
"This documentation provides a reference to the `{{alias}}` {{kind}}. This belongs to the Inventory Module.",
frontmatterData: {
displayed_sidebar: "inventoryReference",
slug: "/references/inventory/{{alias}}",
sidebar_label: "{{alias}}",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: "- Inventory Module Reference",
},
},
},
{
pattern: "IInventoryService.md",
additionalFormatting: {
reflectionDescription:
"This section of the documentation provides a reference to the `IInventoryService` interface’s methods. This is the interface developers use to use the functionalities provided by the Inventory Module.",
frontmatterData: {
displayed_sidebar: "inventoryReference",
slug: "/references/inventory",
},
},
},
],
}) })
+10 -75
View File
@@ -1,87 +1,22 @@
/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path") const path = require("path")
const globalTypedocOptions = require("./_base") const globalTypedocOptions = require("./_base")
const getConfig = require("./utils/get-config")
const pathPrefix = path.join(__dirname, "..", "..", "..") const pathPrefix = path.join(__dirname, "..", "..", "..")
const defaultFormattingOptions = { module.exports = getConfig({
showCommentsAsHeader: true, entryPointPath: "packages/medusa-js/src/resources",
sections: { tsConfigName: "js-client.json",
member_sources_definedIn: false, name: "js-client",
reflection_hierarchy: false,
member_signature_typeParameters: false,
member_signature_sources: false,
member_signature_title: false,
member_signature_returns: false,
title_reflectionPath: false,
reflection_callable: false,
reflection_indexable: false,
reflection_implementedBy: false,
member_declaration_title: false,
},
parameterStyle: "component",
parameterComponent: "ParameterTypes",
mdxImports: [
`import ParameterTypes from "@site/src/components/ParameterTypes"`,
],
reflectionGroups: {
Constructors: false,
},
frontmatterData: {
displayed_sidebar: "jsClientSidebar",
},
}
const classesFormattingOptions = {
...defaultFormattingOptions,
frontmatterData: {
...defaultFormattingOptions.frontmatterData,
slug: "/references/js-client/{{alias}}",
},
}
/** @type {import('typedoc').TypeDocOptions} */
module.exports = {
...globalTypedocOptions,
entryPoints: [path.join(pathPrefix, "packages/medusa-js/src/resources")],
out: [path.join(pathPrefix, "www/apps/docs/content/references/js-client")],
tsconfig: path.join(__dirname, "extended-tsconfig", "js-client.json"),
name: "JS Client Reference",
indexTitle: "JS Client Reference",
entryDocument: "index.mdx",
hideInPageTOC: true,
hideBreadcrumbs: true,
plugin: [...globalTypedocOptions.plugin, "typedoc-plugin-rename-defaults"], plugin: [...globalTypedocOptions.plugin, "typedoc-plugin-rename-defaults"],
exclude: [ exclude: [
...globalTypedocOptions.exclude, ...globalTypedocOptions.exclude,
path.join(pathPrefix, "packages/medusa-js/src/resources/base.ts"), path.join(pathPrefix, "packages/medusa-js/src/resources/base.ts"),
], ],
internalModule: "internal", // internalModule: "internal",
formatting: {
"*": defaultFormattingOptions,
"^classes/": classesFormattingOptions,
AdminOrdersResource: {
maxLevel: 2,
},
internal: {
maxLevel: 1,
},
"internal/modules/internal": {
reflectionGroups: {
...defaultFormattingOptions.reflectionGroups,
"Type Aliases": false,
Enumerations: false,
Classes: false,
Functions: false,
Interfaces: false,
},
},
},
objectLiteralTypeDeclarationStyle: "component",
mdxOutput: true,
maxLevel: 4,
ignoreApi: true, ignoreApi: true,
outputModules: false, // outputModules: false,
outputNamespace: false, // outputNamespace: false,
excludeReferences: true, // excludeReferences: true,
} })
@@ -0,0 +1,11 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const getConfig = require("./utils/get-config")
module.exports = getConfig({
entryPointPath: "packages/medusa/src/index.js",
tsConfigName: "medusa.json",
name: "medusa",
jsonFileName: "0-medusa",
enableInternalResolve: true,
exclude: ["**/models/**.ts", "**/services/**.ts"],
})
@@ -9,5 +9,8 @@
"typedoc": "0.25.x" "typedoc": "0.25.x"
}, },
"main": "_base.js", "main": "_base.js",
"version": "0.0.0" "version": "0.0.0",
"dependencies": {
"glob": "^10.3.10"
}
} }
+1 -49
View File
@@ -3,53 +3,5 @@ const modulesConfig = require("./_modules")
module.exports = modulesConfig({ module.exports = modulesConfig({
entryPointPath: "packages/types/src/pricing/service.ts", entryPointPath: "packages/types/src/pricing/service.ts",
outPath: "www/apps/docs/content/references/pricing", name: "pricing",
moduleName: "Pricing Module Reference",
documentsToFormat: [
{
pattern: "*",
useDefaults: true,
additionalFormatting: {
frontmatterData: {
displayed_sidebar: "pricingReference",
},
},
},
{
pattern: "IPricingModuleService/methods",
additionalFormatting: {
reflectionDescription:
"This documentation provides a reference to the `{{alias}}` {{kind}}. This belongs to the Pricing Module.",
frontmatterData: {
displayed_sidebar: "pricingReference",
badge: {
variant: "orange",
text: "Beta",
},
slug: "/references/pricing/{{alias}}",
sidebar_label: "{{alias}}",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: "- Pricing Module Reference",
},
},
},
{
pattern: "IPricingModuleService.md",
additionalFormatting: {
reflectionDescription:
"This section of the documentation provides a reference to the `IPricingModuleService` interface’s methods. This is the interface developers use to use the functionalities provided by the Pricing Module.",
frontmatterData: {
displayed_sidebar: "pricingReference",
badge: {
variant: "orange",
text: "Beta",
},
slug: "/references/pricing",
},
},
},
],
}) })
+1 -49
View File
@@ -3,53 +3,5 @@ const modulesConfig = require("./_modules")
module.exports = modulesConfig({ module.exports = modulesConfig({
entryPointPath: "packages/types/src/product/service.ts", entryPointPath: "packages/types/src/product/service.ts",
outPath: "www/apps/docs/content/references/product", name: "product",
moduleName: "Product Module Reference",
documentsToFormat: [
{
pattern: "*",
useDefaults: true,
additionalFormatting: {
frontmatterData: {
displayed_sidebar: "productReference",
},
},
},
{
pattern: "IProductModuleService/methods",
additionalFormatting: {
reflectionDescription:
"This documentation provides a reference to the {{alias}} {{kind}}. This belongs to the Product Module.",
frontmatterData: {
displayed_sidebar: "productReference",
badge: {
variant: "orange",
text: "Beta",
},
slug: "/references/product/{{alias}}",
sidebar_label: "{{alias}}",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: "- Product Module Reference",
},
},
},
{
pattern: "IProductModuleService.md",
additionalFormatting: {
reflectionDescription:
"This section of the documentation provides a reference to the `IProductModuleService` interface’s methods. This is the interface developers use to use the functionalities provided by the Product Module.",
frontmatterData: {
displayed_sidebar: "productReference",
badge: {
variant: "orange",
text: "Beta",
},
slug: "/references/product",
},
},
},
],
}) })
+6 -41
View File
@@ -1,43 +1,8 @@
/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path") const getConfig = require("./utils/get-config")
const globalTypedocOptions = require("./_base")
const pathPrefix = path.join(__dirname, "..", "..", "..") module.exports = getConfig({
entryPointPath: "packages/medusa/src/services/index.ts",
module.exports = { tsConfigName: "medusa.json",
...globalTypedocOptions, name: "services",
entryPoints: [path.join(pathPrefix, "packages/medusa/src/services/index.ts")], })
out: [path.join(pathPrefix, "www/apps/docs/content/references/services")],
tsconfig: path.join(__dirname, "extended-tsconfig", "medusa.json"),
name: "Services Reference",
indexTitle: "Services Reference",
entryDocument: "index.md",
hideInPageTOC: true,
hideBreadcrumbs: true,
formatting: {
"*": {
showCommentsAsHeader: true,
sections: {
member_sources_definedIn: false,
reflection_hierarchy: false,
member_sources_inheritedFrom: false,
member_sources_implementationOf: false,
reflection_implementedBy: false,
member_signature_sources: false,
reflection_callable: false,
reflection_indexable: false,
},
parameterStyle: "component",
parameterComponent: "ParameterTypes",
mdxImports: [
`import ParameterTypes from "@site/src/components/ParameterTypes"`,
],
frontmatterData: {
displayed_sidebar: "servicesSidebar",
},
},
},
objectLiteralTypeDeclarationStyle: "component",
mdxOutput: true,
maxLevel: 1,
}
@@ -3,45 +3,5 @@ const modulesConfig = require("./_modules")
module.exports = modulesConfig({ module.exports = modulesConfig({
entryPointPath: "packages/types/src/stock-location/service.ts", entryPointPath: "packages/types/src/stock-location/service.ts",
outPath: "www/apps/docs/content/references/stock-location", name: "stock-location",
moduleName: "Stock Location Module Reference",
documentsToFormat: [
{
pattern: "*",
useDefaults: true,
additionalFormatting: {
frontmatterData: {
displayed_sidebar: "stockLocationReference",
},
},
},
{
pattern: "IStockLocationService/methods",
additionalFormatting: {
reflectionDescription:
"This documentation provides a reference to the `{{alias}}` {{kind}}. This belongs to the Stock Location Module.",
frontmatterData: {
displayed_sidebar: "stockLocationReference",
slug: "/references/stock-location/{{alias}}",
sidebar_label: "{{alias}}",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: "- Stock Location Module Reference",
},
},
},
{
pattern: "IStockLocationService.md",
additionalFormatting: {
reflectionDescription:
"This section of the documentation provides a reference to the `IStockLocationService` interface’s methods. This is the interface developers use to use the functionalities provided by the Stock Location Module.",
frontmatterData: {
displayed_sidebar: "stockLocationReference",
slug: "/references/stock-location",
},
},
},
],
}) })
@@ -1,4 +1,4 @@
{ {
"extends": "../../tsconfig", "extends": "../../tsconfig",
"include": ["*.js"] "include": ["**/*.js"]
} }
@@ -0,0 +1,16 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const getConfig = require("./utils/get-config")
module.exports = getConfig({
entryPointPath: "packages/types/src/index.ts",
tsConfigName: "types.json",
name: "types",
jsonFileName: "0-types",
enableInternalResolve: true,
exclude: [
"**/pricing/**.ts",
"**/product/**.ts",
"**/inventory/**.ts",
"**/stock-location/**.ts",
],
})
@@ -0,0 +1,44 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path")
const globalTypedocOptions = require("../_base")
function getEntryPoints(entryPointPaths) {
if (Array.isArray(entryPointPaths)) {
return entryPointPaths.map((entryPath) =>
path.join(__dirname, "..", "..", "..", "..", entryPath)
)
} else {
return path.join(__dirname, "..", "..", "..", "..", entryPointPaths)
}
}
/**
*
* @param {Record<string, any>} param0 - The configuration options
* @returns {import('typedoc').TypeDocOptions}
*/
function getConfig({
entryPointPath,
tsConfigName,
name,
jsonFileName,
...otherOptions
}) {
return {
...globalTypedocOptions,
entryPoints: getEntryPoints(entryPointPath),
tsconfig: path.join(__dirname, "..", "extended-tsconfig", tsConfigName),
name,
json: path.join(
__dirname,
"..",
"..",
"..",
"typedoc-json-output",
`${jsonFileName || name}.json`
),
...otherOptions,
}
}
module.exports = getConfig
+8 -87
View File
@@ -1,89 +1,10 @@
/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path") const getConfig = require("./utils/get-config")
const globalTypedocOptions = require("./_base")
const pathPrefix = path.join(__dirname, "..", "..", "..") module.exports = getConfig({
entryPointPath: "packages/workflows-sdk/src/utils/composer/index.ts",
module.exports = { // entryPointStrategy: "expand",
...globalTypedocOptions, tsConfigName: "workflows.json",
entryPoints: [ name: "workflows",
path.join(pathPrefix, "packages/workflows-sdk/src/utils/composer/index.ts"), // enableInternalResolve: true,
], })
out: [path.join(pathPrefix, "www/apps/docs/content/references/workflows")],
tsconfig: path.join(__dirname, "extended-tsconfig", "workflows.json"),
name: "Workflows API Reference",
indexTitle: "Workflows API Reference",
entryDocument: "index.mdx",
hideInPageTOC: true,
hideBreadcrumbs: true,
formatting: {
"*": {
expandMembers: true,
showCommentsAsHeader: true,
sections: {
member_sources_definedIn: false,
reflection_hierarchy: false,
member_sources_inheritedFrom: false,
member_sources_implementationOf: false,
reflection_implementedBy: false,
member_signature_sources: false,
reflection_callable: false,
reflection_indexable: false,
member_signature_title: false,
member_signature_returns: false,
member_getterSetter: false,
},
parameterStyle: "component",
parameterComponent: "ParameterTypes",
mdxImports: [
`import ParameterTypes from "@site/src/components/ParameterTypes"`,
],
frontmatterData: {
displayed_sidebar: "workflowsSidebar",
},
},
"index\\.mdx": {
reflectionDescription:
"This section of the documentation provides a reference to the utility functions of the `@medusajs/workflows-sdk` package.",
reflectionGroups: {
Namespaces: false,
Enumerations: false,
Classes: false,
Interfaces: false,
"Type Aliases": false,
Variables: false,
"Enumeration Members": false,
},
},
functions: {
maxLevel: 1,
reflectionDescription:
"This documentation provides a reference to the `{{alias}}` {{kind}}. It belongs to the `@medusajs/workflows-sdk` package.",
frontmatterData: {
displayed_sidebar: "workflowsSidebar",
slug: "/references/workflows/{{alias}}",
sidebar_label: "{{alias}}",
},
reflectionTitle: {
kind: false,
typeParameters: false,
suffix: "- Workflows Reference",
},
},
"classes/StepResponse": {
reflectionGroups: {
Properties: false,
},
},
transform: {
reflectionGroups: {
"Type Parameters": false,
},
},
},
objectLiteralTypeDeclarationStyle: "component",
mdxOutput: true,
maxLevel: 2,
allReflectionsHaveOwnDocument: true,
excludeExternals: true,
}
@@ -8,6 +8,8 @@ A Typedoc plugin that combines utility plugins for documenting references.
The [`resolve-reference-plugin`](./src/resolve-references-plugin.ts) imitates the [`typedoc-plugin-missing-exports`](https://www.npmjs.com/package/typedoc-plugin-missing-exports) plugin. So, it accepts the same options as the [`typedoc-plugin-missing-exports`](https://www.npmjs.com/package/typedoc-plugin-missing-exports) plugin. The [`resolve-reference-plugin`](./src/resolve-references-plugin.ts) imitates the [`typedoc-plugin-missing-exports`](https://www.npmjs.com/package/typedoc-plugin-missing-exports) plugin. So, it accepts the same options as the [`typedoc-plugin-missing-exports`](https://www.npmjs.com/package/typedoc-plugin-missing-exports) plugin.
This plugin only runs if the `enableInternalResolve` option is enabled.
### Frontmatter ### Frontmatter
`frontmatterData` is an object of key-value pairs. If none provided, no frontmatter variables will be added to the Markdown files. `frontmatterData` is an object of key-value pairs. If none provided, no frontmatter variables will be added to the Markdown files.
@@ -9,6 +9,7 @@ import {
Reflection, Reflection,
DeclarationReflection, DeclarationReflection,
ProjectReflection, ProjectReflection,
ParameterType,
} from "typedoc" } from "typedoc"
declare module "typedoc" { declare module "typedoc" {
@@ -27,6 +28,18 @@ export function load(app: Application) {
} }
hasMonkeyPatched = true hasMonkeyPatched = true
app.options.addDeclaration({
name: "internalModule",
help: "Define the name of the module that internal symbols which are not exported should be placed into.",
})
app.options.addDeclaration({
name: "enableInternalResolve",
help: "Whether to run this plugin or not.",
type: ParameterType.Boolean,
defaultValue: false,
})
let activeReflection: Reflection | undefined let activeReflection: Reflection | undefined
const referencedSymbols = new Map<ts.Program, Set<ts.Symbol>>() const referencedSymbols = new Map<ts.Program, Set<ts.Symbol>>()
const symbolToActiveRefl = new Map<ts.Symbol, Reflection>() const symbolToActiveRefl = new Map<ts.Symbol, Reflection>()
@@ -58,6 +71,9 @@ export function load(app: Application) {
// Monkey patch the constructor for references so that we can get every // Monkey patch the constructor for references so that we can get every
const origCreateSymbolReference = ReferenceType.createSymbolReference const origCreateSymbolReference = ReferenceType.createSymbolReference
ReferenceType.createSymbolReference = function (symbol, context, name) { ReferenceType.createSymbolReference = function (symbol, context, name) {
if (!app.options.getValue("enableInternalResolve")) {
return origCreateSymbolReference.call(this, symbol, context, name)
}
ok(activeReflection, "active reflection has not been set") ok(activeReflection, "active reflection has not been set")
const set = referencedSymbols.get(context.program) const set = referencedSymbols.get(context.program)
symbolToActiveRefl.set(symbol, activeReflection) symbolToActiveRefl.set(symbol, activeReflection)
@@ -69,14 +85,12 @@ export function load(app: Application) {
return origCreateSymbolReference.call(this, symbol, context, name) return origCreateSymbolReference.call(this, symbol, context, name)
} }
app.options.addDeclaration({
name: "internalModule",
help: "Define the name of the module that internal symbols which are not exported should be placed into.",
})
app.converter.on( app.converter.on(
Converter.EVENT_CREATE_DECLARATION, Converter.EVENT_CREATE_DECLARATION,
(context: Context, refl: Reflection) => { (context: Context, refl: Reflection) => {
if (!app.options.getValue("enableInternalResolve")) {
return
}
if (refl.kindOf(ReflectionKind.Project | ReflectionKind.Module)) { if (refl.kindOf(ReflectionKind.Project | ReflectionKind.Module)) {
knownPrograms.set(refl, context.program) knownPrograms.set(refl, context.program)
activeReflection = refl activeReflection = refl
@@ -87,6 +101,9 @@ export function load(app: Application) {
app.converter.on( app.converter.on(
Converter.EVENT_RESOLVE_BEGIN, Converter.EVENT_RESOLVE_BEGIN,
function onResolveBegin(context: Context) { function onResolveBegin(context: Context) {
if (!app.options.getValue("enableInternalResolve")) {
return
}
const modules: (DeclarationReflection | ProjectReflection)[] = const modules: (DeclarationReflection | ProjectReflection)[] =
context.project.getChildrenByKind(ReflectionKind.Module) context.project.getChildrenByKind(ReflectionKind.Module)
if (modules.length === 0) { if (modules.length === 0) {
@@ -21,7 +21,9 @@ Aside from the options detailed in [typedoc-plugin-markdown](https://github.com/
- `parameterStyle`: (optional) a string indicating how parameters are displayed. Its value can be `table` (default), `list`, or `component`. - `parameterStyle`: (optional) a string indicating how parameters are displayed. Its value can be `table` (default), `list`, or `component`.
- `showReturnSignature`: (optional) a boolean indicating whether to show the signature for returned values. - `showReturnSignature`: (optional) a boolean indicating whether to show the signature for returned values.
- `frontmatterData`: (optional) an object that will be injected as frontmatter to the pages matching specified pattern. - `frontmatterData`: (optional) an object that will be injected as frontmatter to the pages matching specified pattern.
- `parameterComponent`: (optional) a string indicating the name of a React component to pass the parameters as an object to. This is only used if the `parameterStyle` option is set to `component`. This also must be used with the `mdxOutput` option enabled, and an import string for the component passed to the `mdxImports` option. The React component will receive a `parameters` prop, which is an array of type [Parameter](./src/types.ts#L95). - `parameterComponent`: (optional) a string indicating the name of a React component to pass the parameters as an object to. This is only used if the
- `parameterComponentExtraProps`: (optional) an object that specifies props to pass to the `parameterComponent`.
- `parameterStyle` option is set to `component`. This also must be used with the `mdxOutput` option enabled, and an import string for the component passed to the `mdxImports` option. The React component will receive a `parameters` prop, which is an array of type [Parameter](./src/types.ts#L95).
- `mdxImports`: (optional) an array of strings, each holding an import statement that will be added to the beginning of each page. For example, `["import ParameterTypes from "@site/src/components/ParameterTypes""]`. Must be used along with the `mdxOutput` option enabled. - `mdxImports`: (optional) an array of strings, each holding an import statement that will be added to the beginning of each page. For example, `["import ParameterTypes from "@site/src/components/ParameterTypes""]`. Must be used along with the `mdxOutput` option enabled.
- `maxLevel`: (optional) a number indicating the maximum level parameters and return types are expanded. Default is `3`. - `maxLevel`: (optional) a number indicating the maximum level parameters and return types are expanded. Default is `3`.
@@ -34,10 +34,10 @@ export function load(app: Application) {
}) })
app.options.addDeclaration({ app.options.addDeclaration({
help: "[Markdown Plugin] Output all reflections into seperate output files.", help: "[Markdown Plugin] Specify module names where all reflections are outputted into seperate files.",
name: "allReflectionsHaveOwnDocument", name: "allReflectionsHaveOwnDocument",
type: ParameterType.Boolean, type: ParameterType.Array,
defaultValue: false, defaultValue: [],
}) })
app.options.addDeclaration({ app.options.addDeclaration({
@@ -8,18 +8,32 @@ export default function (theme: MarkdownTheme) {
Handlebars.registerHelper( Handlebars.registerHelper(
"parameterComponent", "parameterComponent",
function (this: ReflectionParameterType[]) { function (this: ReflectionParameterType[]) {
const { parameterComponent, maxLevel } = const { parameterComponent, maxLevel, parameterComponentExtraProps } =
theme.getFormattingOptionsForLocation() theme.getFormattingOptionsForLocation()
const parameters = this.reduce( const parameters = this.reduce(
(acc: ReflectionParameterType[], current) => parseParams(current, acc), (acc: ReflectionParameterType[], current) => parseParams(current, acc),
[] []
).map((parameter) => reflectionComponentFormatter(parameter, 1, maxLevel)) ).map((parameter) =>
reflectionComponentFormatter({
reflection: parameter,
level: 1,
maxLevel,
})
)
let extraProps: string[] = []
if (parameterComponentExtraProps) {
extraProps = Object.entries(parameterComponentExtraProps).map(
([key, value]) => `${key}=${JSON.stringify(value)}`
)
}
return `<${parameterComponent} parameters={${JSON.stringify( return `<${parameterComponent} parameters={${JSON.stringify(
parameters, parameters,
null, null,
2 2
)}} />` )}} ${extraProps.join(" ")}/>`
} }
) )
} }
@@ -21,7 +21,10 @@ export default function () {
function list(parameters: ReflectionParameterType[]) { function list(parameters: ReflectionParameterType[]) {
const items = parameters.map((parameter) => { const items = parameters.map((parameter) => {
return reflectionFormatter(parameter, "list") return reflectionFormatter({
reflection: parameter,
type: "list",
})
}) })
return items.join("\n") return items.join("\n")
@@ -20,7 +20,9 @@ export default function () {
const headers = getTableHeaders(parameters) const headers = getTableHeaders(parameters)
const rows = parameters.map((parameter) => const rows = parameters.map((parameter) =>
reflectionTableFormatter(parameter) reflectionTableFormatter({
reflection: parameter,
})
) )
return `\n| ${headers.join(" | ")} |\n| ${headers return `\n| ${headers.join(" | ")} |\n| ${headers
@@ -88,7 +88,12 @@ function getReturnFromComment(theme: MarkdownTheme, comment: Comment) {
commentPart.target instanceof DeclarationReflection commentPart.target instanceof DeclarationReflection
) { ) {
const content = commentPart.target.children?.map((childItem) => const content = commentPart.target.children?.map((childItem) =>
reflectionFormatter(childItem, parameterStyle, 1, maxLevel) reflectionFormatter({
reflection: childItem,
type: parameterStyle,
level: 1,
maxLevel,
})
) )
result += result +=
parameterStyle === "component" parameterStyle === "component"
@@ -6,13 +6,6 @@ export default function (theme: MarkdownTheme) {
Handlebars.registerHelper("titleLevel", function (this: Reflection): string { Handlebars.registerHelper("titleLevel", function (this: Reflection): string {
const { currentTitleLevel } = theme const { currentTitleLevel } = theme
// let titleLevel = currentTitleLevel
// if (isChild) {
// titleLevel++
// theme.setCurrentTitleLevel(titleLevel + 1)
// }
return Array(currentTitleLevel).fill("#").join("") return Array(currentTitleLevel).fill("#").join("")
}) })
} }
@@ -49,7 +49,10 @@ export default function (theme: MarkdownTheme) {
function getListMarkdownContent(properties: DeclarationReflection[]) { function getListMarkdownContent(properties: DeclarationReflection[]) {
const items = properties.map((property) => const items = properties.map((property) =>
reflectionFormatter(property, "list") reflectionFormatter({
reflection: property,
type: "list",
})
) )
return items.join("\n") return items.join("\n")
@@ -61,7 +64,12 @@ function getComponentMarkdownContent(
maxLevel?: number | undefined maxLevel?: number | undefined
) { ) {
const parameters = properties.map((property) => const parameters = properties.map((property) =>
reflectionFormatter(property, "component", 1, maxLevel) reflectionFormatter({
reflection: property,
type: "component",
level: 1,
maxLevel,
})
) )
return `<${parameterComponent} parameters={${JSON.stringify( return `<${parameterComponent} parameters={${JSON.stringify(
@@ -10,7 +10,11 @@ export default function (theme: MarkdownTheme) {
const { parameterComponent, maxLevel } = const { parameterComponent, maxLevel } =
theme.getFormattingOptionsForLocation() theme.getFormattingOptionsForLocation()
const parameters = this.map((parameter) => const parameters = this.map((parameter) =>
reflectionComponentFormatter(parameter, 1, maxLevel) reflectionComponentFormatter({
reflection: parameter,
level: 1,
maxLevel,
})
) )
return `<${parameterComponent} parameters={${JSON.stringify( return `<${parameterComponent} parameters={${JSON.stringify(
@@ -13,7 +13,10 @@ export default function () {
function list(parameters: TypeParameterReflection[]) { function list(parameters: TypeParameterReflection[]) {
const items = parameters.map((parameter) => const items = parameters.map((parameter) =>
reflectionFormatter(parameter, "list") reflectionFormatter({
reflection: parameter,
type: "list",
})
) )
return items.join("\n") return items.join("\n")
@@ -13,7 +13,11 @@ export default function () {
const showTypeCol = hasTypes(this) const showTypeCol = hasTypes(this)
const headers = getTableHeaders(this, showTypeCol) const headers = getTableHeaders(this, showTypeCol)
const rows = this.map((parameter) => reflectionTableFormatter(parameter)) const rows = this.map((parameter) =>
reflectionTableFormatter({
reflection: parameter,
})
)
return `\n| ${headers.join(" | ")} |\n| ${headers return `\n| ${headers.join(" | ")} |\n| ${headers
.map(() => ":------") .map(() => ":------")
@@ -39,7 +39,11 @@ export default function () {
collapse: Collapse = "none", collapse: Collapse = "none",
emphasis = true emphasis = true
) { ) {
return getType(this, collapse, emphasis) return getType({
reflectionType: this,
collapse,
wrapBackticks: emphasis,
})
} }
) )
} }
@@ -28,7 +28,7 @@ import {
} from "./types" } from "./types"
export class MarkdownTheme extends Theme { export class MarkdownTheme extends Theme {
allReflectionsHaveOwnDocument!: boolean allReflectionsHaveOwnDocument!: string[]
entryDocument: string entryDocument: string
entryPoints!: string[] entryPoints!: string[]
filenameSeparator!: string filenameSeparator!: string
@@ -64,7 +64,7 @@ export class MarkdownTheme extends Theme {
super(renderer) super(renderer)
// prettier-ignore // prettier-ignore
this.allReflectionsHaveOwnDocument = this.getOption("allReflectionsHaveOwnDocument") as boolean this.allReflectionsHaveOwnDocument = this.getOption("allReflectionsHaveOwnDocument") as string[]
this.entryDocument = this.getOption("entryDocument") as string this.entryDocument = this.getOption("entryDocument") as string
this.entryPoints = this.getOption("entryPoints") as string[] this.entryPoints = this.getOption("entryPoints") as string[]
this.filenameSeparator = this.getOption("filenameSeparator") as string this.filenameSeparator = this.getOption("filenameSeparator") as string
@@ -147,6 +147,7 @@ export class MarkdownTheme extends Theme {
urls: UrlMapping[] urls: UrlMapping[]
): UrlMapping[] { ): UrlMapping[] {
const mapping = this.getMappings( const mapping = this.getMappings(
reflection,
reflection.parent?.isProject() ? "" : reflection.parent?.getAlias() reflection.parent?.isProject() ? "" : reflection.parent?.getAlias()
).find((mapping) => reflection.kindOf(mapping.kind)) ).find((mapping) => reflection.kindOf(mapping.kind))
if (mapping) { if (mapping) {
@@ -278,7 +279,31 @@ export class MarkdownTheme extends Theme {
} }
} }
getMappings(directoryPrefix?: string): Mapping[] { getModuleParents(reflection: DeclarationReflection): DeclarationReflection[] {
const parents: DeclarationReflection[] = []
let currentParent = reflection?.parent as DeclarationReflection | undefined
do {
if (currentParent?.kind === ReflectionKind.Module) {
parents.push(currentParent)
}
currentParent = currentParent?.parent as DeclarationReflection | undefined
} while (currentParent)
return parents
}
getAllReflectionsHaveOwnDocument(reflection: DeclarationReflection): boolean {
const moduleParents = this.getModuleParents(reflection)
return moduleParents.some((parent) =>
this.allReflectionsHaveOwnDocument.includes(parent.name)
)
}
getMappings(
reflection: DeclarationReflection,
directoryPrefix?: string
): Mapping[] {
return [ return [
{ {
kind: [ReflectionKind.Module], kind: [ReflectionKind.Module],
@@ -316,7 +341,7 @@ export class MarkdownTheme extends Theme {
directory: path.join(directoryPrefix || "", "types"), directory: path.join(directoryPrefix || "", "types"),
template: this.getReflectionMemberTemplate(), template: this.getReflectionMemberTemplate(),
}, },
...(this.allReflectionsHaveOwnDocument ...(this.getAllReflectionsHaveOwnDocument(reflection)
? [ ? [
{ {
kind: [ReflectionKind.Variable], kind: [ReflectionKind.Variable],
@@ -76,6 +76,7 @@ export type FormattingOptionType = {
parameterStyle?: ParameterStyle parameterStyle?: ParameterStyle
frontmatterData?: Record<string, unknown> frontmatterData?: Record<string, unknown>
parameterComponent?: string parameterComponent?: string
parameterComponentExtraProps?: Record<string, unknown>
mdxImports?: string[] mdxImports?: string[]
maxLevel?: number maxLevel?: number
} }
@@ -1,6 +1,7 @@
import { import {
Comment, Comment,
DeclarationReflection, DeclarationReflection,
ProjectReflection,
ReflectionKind, ReflectionKind,
ReflectionType, ReflectionType,
} from "typedoc" } from "typedoc"
@@ -22,29 +23,35 @@ const ALLOWED_KINDS: ReflectionKind[] = [
ReflectionKind.Reference, ReflectionKind.Reference,
] ]
export default function reflectionFormatter( type ReflectionFormatterOptions = {
reflection: ReflectionParameterType, reflection: ReflectionParameterType
type: ParameterStyle = "table", level?: number
level = 1,
maxLevel?: number | undefined maxLevel?: number | undefined
): string | Parameter { project?: ProjectReflection
type?: ParameterStyle
}
export default function reflectionFormatter({
type = "table",
...options
}: ReflectionFormatterOptions): string | Parameter {
switch (type) { switch (type) {
case "list": case "list":
return reflectionListFormatter(reflection, level) return reflectionListFormatter(options)
case "component": case "component":
return reflectionComponentFormatter(reflection, level, maxLevel) return reflectionComponentFormatter(options)
case "table": case "table":
return reflectionTableFormatter(reflection) return reflectionTableFormatter(options)
default: default:
return "" return ""
} }
} }
export function reflectionListFormatter( export function reflectionListFormatter({
reflection: ReflectionParameterType, reflection,
level = 1, level = 1,
maxLevel?: number | undefined maxLevel,
): string { }: ReflectionFormatterOptions): string {
const prefix = `${Array(level - 1) const prefix = `${Array(level - 1)
.fill("\t") .fill("\t")
.join("")}-` .join("")}-`
@@ -81,7 +88,13 @@ export function reflectionListFormatter(
if (!itemChildrenKind) { if (!itemChildrenKind) {
itemChildrenKind = childItem.kind itemChildrenKind = childItem.kind
} }
itemChildren.push(reflectionListFormatter(childItem, level + 1)) itemChildren.push(
reflectionListFormatter({
reflection: childItem,
level: level + 1,
maxLevel,
})
)
}) })
if (itemChildren.length) { if (itemChildren.length) {
item += ` ${getItemExpandText( item += ` ${getItemExpandText(
@@ -94,11 +107,12 @@ export function reflectionListFormatter(
return item return item
} }
export function reflectionComponentFormatter( export function reflectionComponentFormatter({
reflection: ReflectionParameterType, reflection,
level = 1, level = 1,
maxLevel?: number | undefined maxLevel,
): Parameter { project,
}: ReflectionFormatterOptions): Parameter {
const defaultValue = getDefaultValue(reflection) || "" const defaultValue = getDefaultValue(reflection) || ""
const optional = const optional =
reflection.flags.isOptional || reflection.kind === ReflectionKind.EnumMember reflection.flags.isOptional || reflection.kind === ReflectionKind.EnumMember
@@ -106,8 +120,17 @@ export function reflectionComponentFormatter(
const componentItem: Parameter = { const componentItem: Parameter = {
name: reflection.name, name: reflection.name,
type: reflection.type type: reflection.type
? getType(reflection.type, "object") ? getType({
: getReflectionType(reflection, "object", true), reflectionType: reflection.type,
collapse: "object",
project: reflection.project,
})
: getReflectionType({
reflectionType: reflection,
collapse: "object",
wrapBackticks: true,
project: reflection.project,
}),
description: comments description: comments
? Handlebars.helpers.comments(comments, true, false) ? Handlebars.helpers.comments(comments, true, false)
: "", : "",
@@ -124,9 +147,18 @@ export function reflectionComponentFormatter(
(reflection.type || hasChildren) && (reflection.type || hasChildren) &&
level + 1 <= (maxLevel || MarkdownTheme.MAX_LEVEL) level + 1 <= (maxLevel || MarkdownTheme.MAX_LEVEL)
) { ) {
// if (
// reflection.name === "user" &&
// reflection.type &&
// "name" in reflection.type &&
// reflection.type.name.startsWith("Omit") &&
// "typeArguments" in reflection.type
// ) {
// console.log(reflection)
// }
const children = hasChildren const children = hasChildren
? reflection.children ? reflection.children
: getTypeChildren(reflection.type!, reflection.project) : getTypeChildren(reflection.type!, project || reflection.project)
children children
?.filter((childItem: DeclarationReflection) => ?.filter((childItem: DeclarationReflection) =>
@@ -134,7 +166,12 @@ export function reflectionComponentFormatter(
) )
.forEach((childItem: DeclarationReflection) => { .forEach((childItem: DeclarationReflection) => {
componentItem.children?.push( componentItem.children?.push(
reflectionComponentFormatter(childItem, level + 1, maxLevel) reflectionComponentFormatter({
reflection: childItem,
level: level + 1,
maxLevel,
project,
})
) )
}) })
} }
@@ -142,9 +179,9 @@ export function reflectionComponentFormatter(
return componentItem return componentItem
} }
export function reflectionTableFormatter( export function reflectionTableFormatter({
parameter: ReflectionParameterType reflection: parameter,
): string { }: ReflectionFormatterOptions): string {
const showDefaults = hasDefaultValues([parameter]) const showDefaults = hasDefaultValues([parameter])
const hasComments = !!parameter.comment?.hasVisibleComponent() const hasComments = !!parameter.comment?.hasVisibleComponent()
@@ -170,7 +207,11 @@ export function reflectionTableFormatter(
row.push( row.push(
parameter.type parameter.type
? Handlebars.helpers.type.call(parameter.type, "object") ? Handlebars.helpers.type.call(parameter.type, "object")
: getReflectionType(parameter, "object", true) : getReflectionType({
reflectionType: parameter,
collapse: "object",
wrapBackticks: true,
})
) )
if (showDefaults) { if (showDefaults) {
@@ -14,6 +14,7 @@ import {
reflectionComponentFormatter, reflectionComponentFormatter,
} from "./reflection-formatter" } from "./reflection-formatter"
import { MarkdownTheme } from "../theme" import { MarkdownTheme } from "../theme"
import { getProjectChild, getTypeChildren } from "utils"
type ReturnReflectionComponentFormatterParams = { type ReturnReflectionComponentFormatterParams = {
reflectionType: SomeType reflectionType: SomeType
@@ -30,8 +31,18 @@ export function returnReflectionComponentFormatter({
level = 1, level = 1,
maxLevel, maxLevel,
}: ReturnReflectionComponentFormatterParams): Parameter[] { }: ReturnReflectionComponentFormatterParams): Parameter[] {
const typeName = getType(reflectionType, "object", false, true) const typeName = getType({
const type = getType(reflectionType, "object") reflectionType,
collapse: "object",
wrapBackticks: false,
hideLink: true,
project,
})
const type = getType({
reflectionType: reflectionType,
collapse: "object",
project,
})
const componentItem: Parameter[] = [] const componentItem: Parameter[] = []
const canRetrieveChildren = level + 1 <= (maxLevel || MarkdownTheme.MAX_LEVEL) const canRetrieveChildren = level + 1 <= (maxLevel || MarkdownTheme.MAX_LEVEL)
if (reflectionType.type === "reference") { if (reflectionType.type === "reference") {
@@ -82,27 +93,52 @@ export function returnReflectionComponentFormatter({
} }
} else { } else {
const reflection = (reflectionType.reflection || const reflection = (reflectionType.reflection ||
project.getChildByName(reflectionType.name)) as DeclarationReflection getProjectChild(project, reflectionType.name)) as DeclarationReflection
if (reflection) { if (reflection) {
if (reflection.children?.length) { const reflectionChildren = canRetrieveChildren
reflection.children.forEach((childItem) => { ? reflection.children ||
getTypeChildren(reflectionType, project, level)
: undefined
if (reflectionChildren?.length) {
reflectionChildren.forEach((childItem) => {
componentItem.push( componentItem.push(
reflectionComponentFormatter( reflectionComponentFormatter({
childItem as DeclarationReflection, reflection: childItem as DeclarationReflection,
level, level,
maxLevel maxLevel,
) project,
})
) )
}) })
} else { } else {
componentItem.push( componentItem.push(
reflectionComponentFormatter( reflectionComponentFormatter({
reflection as DeclarationReflection, reflection,
level, level,
maxLevel maxLevel,
) project,
})
) )
} }
} else {
componentItem.push({
name: "name" in reflectionType ? reflectionType.name : typeName,
type,
optional:
"flags" in reflectionType
? (reflectionType.flags as ReflectionFlags).isOptional
: false,
defaultValue:
"declaration" in reflectionType
? getDefaultValue(
reflectionType.declaration as DeclarationReflection
) || ""
: "",
description: comment ? getReturnComment(comment) : "",
expandable: comment?.hasModifier(`@expandable`) || false,
featureFlag: Handlebars.helpers.featureFlag(comment),
children: [],
})
} }
} }
} else if (reflectionType.type === "array") { } else if (reflectionType.type === "array") {
@@ -7,6 +7,7 @@ import {
IntersectionType, IntersectionType,
IntrinsicType, IntrinsicType,
LiteralType, LiteralType,
ProjectReflection,
QueryType, QueryType,
ReferenceType, ReferenceType,
ReflectionType, ReflectionType,
@@ -21,116 +22,164 @@ import {
import * as Handlebars from "handlebars" import * as Handlebars from "handlebars"
import { ReflectionParameterType } from "../types" import { ReflectionParameterType } from "../types"
import { escapeChars, getHTMLChar } from "../utils" import { escapeChars, getHTMLChar } from "../utils"
import { getProjectChild } from "utils"
export type Collapse = "object" | "function" | "all" | "none" export type Collapse = "object" | "function" | "all" | "none"
export default function getType( export type TypeOptions<T = SomeType> = {
reflectionType: SomeType, reflectionType: T
collapse: Collapse = "none", collapse?: Collapse
wrapBackticks = true, wrapBackticks?: boolean
hideLink = false, hideLink?: boolean
escape?: boolean escape?: boolean
): string { project?: ProjectReflection
}
export default function getType({
reflectionType,
...options
}: TypeOptions): string {
if (reflectionType instanceof ReferenceType) { if (reflectionType instanceof ReferenceType) {
return getReferenceType(reflectionType, wrapBackticks, hideLink, escape) return getReferenceType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof ArrayType && reflectionType.elementType) { if (reflectionType instanceof ArrayType && reflectionType.elementType) {
return getArrayType(reflectionType, wrapBackticks, hideLink, escape) return getArrayType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof UnionType && reflectionType.types) { if (reflectionType instanceof UnionType && reflectionType.types) {
return getUnionType(reflectionType, wrapBackticks, hideLink, escape) return getUnionType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof IntersectionType && reflectionType.types) { if (reflectionType instanceof IntersectionType && reflectionType.types) {
return getIntersectionType(reflectionType, wrapBackticks, hideLink, escape) return getIntersectionType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof TupleType && reflectionType.elements) { if (reflectionType instanceof TupleType && reflectionType.elements) {
return getTupleType(reflectionType, wrapBackticks, hideLink, escape) return getTupleType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof IntrinsicType && reflectionType.name) { if (reflectionType instanceof IntrinsicType && reflectionType.name) {
return getIntrinsicType(reflectionType, wrapBackticks, escape) return getIntrinsicType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof ReflectionType) { if (reflectionType instanceof ReflectionType) {
return getReflectionType( return getReflectionType({
reflectionType.declaration, reflectionType: reflectionType.declaration,
collapse, ...options,
wrapBackticks, })
hideLink
)
} }
if (reflectionType instanceof DeclarationReflection) { if (reflectionType instanceof DeclarationReflection) {
return getReflectionType(reflectionType, collapse, wrapBackticks, hideLink) return getReflectionType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof TypeOperatorType) { if (reflectionType instanceof TypeOperatorType) {
return getTypeOperatorType(reflectionType, wrapBackticks, hideLink, escape) return getTypeOperatorType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof QueryType) { if (reflectionType instanceof QueryType) {
return getQueryType(reflectionType, wrapBackticks, hideLink, escape) return getQueryType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof ConditionalType) { if (reflectionType instanceof ConditionalType) {
return getConditionalType(reflectionType, wrapBackticks, hideLink, escape) return getConditionalType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof IndexedAccessType) { if (reflectionType instanceof IndexedAccessType) {
return getIndexAccessType(reflectionType, wrapBackticks, hideLink, escape) return getIndexAccessType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof UnknownType) { if (reflectionType instanceof UnknownType) {
return getUnknownType(reflectionType, escape) return getUnknownType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof InferredType) { if (reflectionType instanceof InferredType) {
return getInferredType(reflectionType, escape) return getInferredType({
reflectionType,
...options,
})
} }
if (reflectionType instanceof LiteralType) { if (reflectionType instanceof LiteralType) {
return getLiteralType(reflectionType, wrapBackticks, escape) return getLiteralType({
reflectionType,
...options,
})
} }
return reflectionType ? escapeChars(reflectionType.toString()) : "" return reflectionType ? escapeChars(reflectionType.toString()) : ""
} }
export function getReflectionType( export function getReflectionType({
model: ReflectionParameterType, reflectionType: model,
collapse: Collapse, collapse,
wrapBackticks = true, wrapBackticks = true,
hideLink = false hideLink = false,
): string { }: TypeOptions<ReflectionParameterType>): string {
if ("signatures" in model && model.signatures) { if ("signatures" in model && model.signatures) {
return collapse === "function" || collapse === "all" return collapse === "function" || collapse === "all"
? `${wrapBackticks ? "`" : ""}fn${wrapBackticks ? "`" : ""}` ? `${wrapBackticks ? "`" : ""}fn${wrapBackticks ? "`" : ""}`
: getFunctionType( : getFunctionType({
model.signatures, modelSignatures: model.signatures,
wrapBackticks, wrapBackticks,
hideLink, hideLink,
!wrapBackticks escape: !wrapBackticks,
) })
} }
return collapse === "object" || collapse === "all" return collapse === "object" || collapse === "all"
? `${wrapBackticks ? "`" : ""}object${wrapBackticks ? "`" : ""}` ? `${wrapBackticks ? "`" : ""}object${wrapBackticks ? "`" : ""}`
: `${wrapBackticks ? "`" : ""}${getDeclarationType( : `${wrapBackticks ? "`" : ""}${getDeclarationType({
model as DeclarationReflection, reflectionType: model as DeclarationReflection,
wrapBackticks, wrapBackticks,
hideLink, hideLink,
!wrapBackticks escape: !wrapBackticks,
)}${wrapBackticks ? "`" : ""}` })}${wrapBackticks ? "`" : ""}`
} }
export function getDeclarationType( export function getDeclarationType({
model: DeclarationReflection, reflectionType: model,
wrapBackticks = true, wrapBackticks = true,
hideLink = false, hideLink = false,
escape?: boolean escape,
): string { ...options
}: TypeOptions<DeclarationReflection>): string {
escape = getShouldEscape(wrapBackticks, escape) escape = getShouldEscape(wrapBackticks, escape)
if (model.indexSignature || model.children) { if (model.indexSignature || model.children) {
@@ -143,13 +192,13 @@ export function getDeclarationType(
) )
: "" : ""
const obj = declarationIndexSignature.type const obj = declarationIndexSignature.type
? getType( ? getType({
declarationIndexSignature.type, reflectionType: declarationIndexSignature.type,
"none", wrapBackticks: false,
false,
hideLink, hideLink,
escape escape,
) ...options,
})
: "" : ""
indexSignature = `${key}: ${obj}; ` indexSignature = `${key}: ${obj}; `
} }
@@ -158,7 +207,13 @@ export function getDeclarationType(
model.children.map((obj) => { model.children.map((obj) => {
return `${obj.name}${obj.flags.isOptional ? "?" : ""}: ${ return `${obj.name}${obj.flags.isOptional ? "?" : ""}: ${
obj.type obj.type
? getType(obj.type, "none", false, hideLink, escape) ? getType({
reflectionType: obj.type,
wrapBackticks: false,
hideLink,
escape,
...options,
})
: getFormattedStr(obj.toString(), false, escape) : getFormattedStr(obj.toString(), false, escape)
} ${ } ${
obj.defaultValue && obj.defaultValue !== "..." obj.defaultValue && obj.defaultValue !== "..."
@@ -179,12 +234,15 @@ export function getDeclarationType(
return getFormattedStr("{}", wrapBackticks, escape) return getFormattedStr("{}", wrapBackticks, escape)
} }
export function getFunctionType( export function getFunctionType({
modelSignatures: SignatureReflection[], modelSignatures,
wrapBackticks: boolean, wrapBackticks = true,
hideLink = false, hideLink = false,
escape?: boolean escape,
): string { ...options
}: Omit<TypeOptions, "reflectionType"> & {
modelSignatures: SignatureReflection[]
}): string {
escape = getShouldEscape(wrapBackticks, escape) escape = getShouldEscape(wrapBackticks, escape)
const functions = modelSignatures.map((fn) => { const functions = modelSignatures.map((fn) => {
@@ -201,24 +259,36 @@ export function getFunctionType(
wrapBackticks ? "`" : "" wrapBackticks ? "`" : ""
}: ${ }: ${
param.type param.type
? getType(param.type, "none", wrapBackticks, hideLink, escape) ? getType({
reflectionType: param.type,
wrapBackticks,
hideLink,
escape,
...options,
})
: getFormattedStr(param.toString(), wrapBackticks, escape) : getFormattedStr(param.toString(), wrapBackticks, escape)
}` }`
}) })
: [] : []
const returns = fn.type const returns = fn.type
? getType(fn.type, "none", wrapBackticks, hideLink, escape) ? getType({
reflectionType: fn.type,
wrapBackticks,
hideLink,
escape,
...options,
})
: getFormattedStr(fn.toString(), wrapBackticks, escape) : getFormattedStr(fn.toString(), wrapBackticks, escape)
return typeParams + `(${params.join(", ")}) => ${returns}` return typeParams + `(${params.join(", ")}) => ${returns}`
}) })
return functions.join("") return functions.join("")
} }
export function getLiteralType( export function getLiteralType({
model: LiteralType, reflectionType: model,
wrapBackticks: boolean, wrapBackticks = true,
escape?: boolean escape,
): string { }: TypeOptions<LiteralType>): string {
escape = getShouldEscape(wrapBackticks, escape) escape = getShouldEscape(wrapBackticks, escape)
return getFormattedStr( return getFormattedStr(
@@ -228,26 +298,33 @@ export function getLiteralType(
) )
} }
export function getReferenceType( export function getReferenceType({
model: ReferenceType, reflectionType: model,
wrapBackticks = true, wrapBackticks = true,
hideLink = false, hideLink = false,
escape?: boolean escape,
): string { project,
...options
}: TypeOptions<ReferenceType>): string {
escape = getShouldEscape(wrapBackticks, escape) escape = getShouldEscape(wrapBackticks, escape)
const shouldShowLink = !hideLink && model.name !== "Record" const shouldShowLink = !hideLink && model.name !== "Record"
const wrappedInBackticks = wrapBackticks && !shouldShowLink const wrappedInBackticks = wrapBackticks && !shouldShowLink
if (model.reflection || (model.name && model.typeArguments)) { let modelReflection = model.reflection
if (!modelReflection && project) {
// try to load reflection
modelReflection = getProjectChild(project!, model.name)
}
if (modelReflection || (model.name && model.typeArguments)) {
const reflection: string[] = [wrappedInBackticks ? "`" : ""] const reflection: string[] = [wrappedInBackticks ? "`" : ""]
if (model.reflection?.url) { if (modelReflection?.url) {
reflection.push( reflection.push(
shouldShowLink shouldShowLink
? `[${model.reflection.name}](${Handlebars.helpers.relativeURL( ? `[${modelReflection.name}](${Handlebars.helpers.relativeURL(
model.reflection.url modelReflection.url
)})` )})`
: getFormattedStr(model.reflection.name, false, escape) : getFormattedStr(modelReflection.name, false, escape)
) )
} else { } else {
reflection.push( reflection.push(
@@ -262,7 +339,13 @@ export function getReferenceType(
reflection.push( reflection.push(
`${wrappedInBackticks ? "<" : getHTMLChar("<")}${model.typeArguments `${wrappedInBackticks ? "<" : getHTMLChar("<")}${model.typeArguments
.map((typeArgument) => .map((typeArgument) =>
getType(typeArgument, "none", false, hideLink, false) getType({
reflectionType: typeArgument,
wrapBackticks: false,
hideLink,
escape: false,
...options,
})
) )
.join(", ")}${wrappedInBackticks ? ">" : getHTMLChar(">")}` .join(", ")}${wrappedInBackticks ? ">" : getHTMLChar(">")}`
) )
@@ -281,151 +364,191 @@ export function getReferenceType(
: getFormattedStr(model.name, wrapBackticks, escape) : getFormattedStr(model.name, wrapBackticks, escape)
} }
export function getArrayType( export function getArrayType({
model: ArrayType, reflectionType: model,
wrapBackticks: boolean,
hideLink = false, hideLink = false,
escape?: boolean ...options
): string { }: TypeOptions<ArrayType>): string {
const arrayType = getType( const arrayType = getType({
model.elementType, reflectionType: model.elementType,
"none",
wrapBackticks,
hideLink, hideLink,
escape ...options,
) })
return model.elementType.type === "union" return model.elementType.type === "union"
? `(${arrayType})[]` ? `(${arrayType})[]`
: `${arrayType}[]` : `${arrayType}[]`
} }
export function getUnionType( export function getUnionType({
model: UnionType, reflectionType: model,
wrapBackticks: boolean,
hideLink = false, hideLink = false,
escape?: boolean ...options
): string { }: TypeOptions<UnionType>): string {
return model.types return model.types
.map((unionType) => .map((unionType) =>
getType(unionType, "none", wrapBackticks, hideLink, escape) getType({
reflectionType: unionType,
hideLink,
...options,
})
) )
.join(` \\| `) .join(` \\| `)
} }
export function getIntersectionType( export function getIntersectionType({
model: IntersectionType, reflectionType: model,
wrapBackticks: boolean,
hideLink = false, hideLink = false,
escape?: boolean ...options
): string { }: TypeOptions<IntersectionType>): string {
return model.types return model.types
.map((intersectionType) => .map((intersectionType) =>
getType(intersectionType, "none", wrapBackticks, hideLink, escape) getType({
reflectionType: intersectionType,
hideLink,
...options,
})
) )
.join(" & ") .join(" & ")
} }
export function getTupleType( export function getTupleType({
model: TupleType, reflectionType: model,
wrapBackticks: boolean,
hideLink = false, hideLink = false,
escape?: boolean ...options
): string { }: TypeOptions<TupleType>): string {
return `[${model.elements return `[${model.elements
.map((element) => getType(element, "none", wrapBackticks, hideLink, escape)) .map((element) =>
getType({
reflectionType: element,
hideLink,
...options,
})
)
.join(", ")}]` .join(", ")}]`
} }
export function getIntrinsicType( export function getIntrinsicType({
model: IntrinsicType, reflectionType: model,
wrapBackticks: boolean, wrapBackticks = true,
escape?: boolean escape,
): string { }: TypeOptions<IntrinsicType>): string {
escape = getShouldEscape(wrapBackticks, escape) escape = getShouldEscape(wrapBackticks, escape)
return getFormattedStr(model.name, wrapBackticks, escape) return getFormattedStr(model.name, wrapBackticks, escape)
} }
export function getTypeOperatorType( export function getTypeOperatorType({
model: TypeOperatorType, reflectionType: model,
wrapBackticks: boolean,
hideLink = false, hideLink = false,
escape?: boolean ...options
): string { }: TypeOptions<TypeOperatorType>): string {
return `${model.operator} ${getType( return `${model.operator} ${getType({
model.target, reflectionType: model.target,
"none",
wrapBackticks,
hideLink, hideLink,
escape ...options,
)}` })}`
} }
export function getQueryType( export function getQueryType({
model: QueryType, reflectionType: model,
wrapBackticks: boolean,
hideLink = false, hideLink = false,
escape?: boolean ...options
): string { }: TypeOptions<QueryType>): string {
return `typeof ${getType( return `typeof ${getType({
model.queryType, reflectionType: model.queryType,
"none",
wrapBackticks,
hideLink, hideLink,
escape ...options,
)}` })}`
} }
export function getInferredType(model: InferredType, escape?: boolean): string { export function getInferredType({
reflectionType: model,
escape,
}: TypeOptions<InferredType>): string {
escape = getShouldEscape(false, escape) escape = getShouldEscape(false, escape)
return `infer ${getFormattedStr(model.name, false, escape)}` return `infer ${getFormattedStr(model.name, false, escape)}`
} }
export function getUnknownType(model: UnknownType, escape?: boolean): string { export function getUnknownType({
reflectionType: model,
escape,
}: TypeOptions<UnknownType>): string {
escape = getShouldEscape(false, escape) escape = getShouldEscape(false, escape)
return getFormattedStr(model.name, false, escape) return getFormattedStr(model.name, false, escape)
} }
export function getConditionalType( export function getConditionalType({
model: ConditionalType, reflectionType: model,
wrapBackticks: boolean,
hideLink = false, hideLink = false,
escape?: boolean ...options
): string { }: TypeOptions<ConditionalType>): string {
const md: string[] = [] const md: string[] = []
if (model.checkType) { if (model.checkType) {
md.push(getType(model.checkType, "none", wrapBackticks, hideLink, escape)) md.push(
getType({
reflectionType: model.checkType,
hideLink,
...options,
})
)
} }
md.push("extends") md.push("extends")
if (model.extendsType) { if (model.extendsType) {
md.push(getType(model.extendsType, "none", wrapBackticks, hideLink, escape)) md.push(
getType({
reflectionType: model.extendsType,
hideLink,
...options,
})
)
} }
md.push("?") md.push("?")
if (model.trueType) { if (model.trueType) {
md.push(getType(model.trueType, "none", wrapBackticks, hideLink, escape)) md.push(
getType({
reflectionType: model.trueType,
hideLink,
...options,
})
)
} }
md.push(":") md.push(":")
if (model.falseType) { if (model.falseType) {
md.push(getType(model.falseType, "none", wrapBackticks, hideLink, escape)) md.push(
getType({
reflectionType: model.falseType,
hideLink,
...options,
})
)
} }
return md.join(" ") return md.join(" ")
} }
export function getIndexAccessType( export function getIndexAccessType({
model: IndexedAccessType, reflectionType: model,
wrapBackticks: boolean,
hideLink = false, hideLink = false,
escape?: boolean ...options
): string { }: TypeOptions<IndexedAccessType>): string {
const md: string[] = [] const md: string[] = []
if (model.objectType) { if (model.objectType) {
md.push(getType(model.objectType, "none", wrapBackticks, hideLink, escape)) md.push(
getType({
reflectionType: model.objectType,
hideLink,
...options,
})
)
} }
if (model.indexType) { if (model.indexType) {
md.push( md.push(
`[${getType(model.indexType, "none", wrapBackticks, hideLink, escape)}]` `[${getType({
reflectionType: model.indexType,
hideLink,
...options,
})}]`
) )
} }
return md.join("") return md.join("")
@@ -4,28 +4,34 @@ import {
ReflectionKind, ReflectionKind,
} from "typedoc" } from "typedoc"
const MAX_LEVEL = 3
export function getProjectChild( export function getProjectChild(
project: ProjectReflection, project: ProjectReflection,
childName: string childName: string,
level = 1
): DeclarationReflection | undefined { ): DeclarationReflection | undefined {
let reflection: DeclarationReflection | undefined = project.getChildByName( let reflection: DeclarationReflection | undefined = project.getChildByName(
childName childName
) as DeclarationReflection ) as DeclarationReflection
const splitChildName = childName.split(".") const splitChildName = childName.split(".")
const canExpandFurther = level <= MAX_LEVEL
if (!reflection && splitChildName.length > 1) { if (!reflection && splitChildName.length > 1 && canExpandFurther) {
reflection = getProjectChild( reflection = getProjectChild(
project, project,
splitChildName[splitChildName.length - 1] splitChildName[splitChildName.length - 1],
level + 1
) )
} }
if ( if (
!reflection && !reflection &&
project.parent && project.parent &&
project.parent instanceof ProjectReflection project.parent instanceof ProjectReflection &&
canExpandFurther
) { ) {
reflection = getProjectChild(project.parent, childName) reflection = getProjectChild(project.parent, childName, level + 1)
} }
if (!reflection) { if (!reflection) {
@@ -1,16 +1,23 @@
import { DeclarationReflection, ProjectReflection, SomeType } from "typedoc" import { DeclarationReflection, ProjectReflection, SomeType } from "typedoc"
import { getProjectChild } from "./get-project-child" import { getProjectChild } from "./get-project-child"
const MAX_LEVEL = 3
export function getTypeChildren( export function getTypeChildren(
reflectionType: SomeType, reflectionType: SomeType,
project: ProjectReflection | undefined project: ProjectReflection | undefined,
level = 1
): DeclarationReflection[] { ): DeclarationReflection[] {
let children: DeclarationReflection[] = [] let children: DeclarationReflection[] = []
if (level > MAX_LEVEL) {
return children
}
switch (reflectionType.type) { switch (reflectionType.type) {
case "intersection": case "intersection":
reflectionType.types.forEach((intersectionType) => { reflectionType.types.forEach((intersectionType) => {
children.push(...getTypeChildren(intersectionType, project)) children.push(...getTypeChildren(intersectionType, project, level + 1))
}) })
break break
case "reference": case "reference":
@@ -25,6 +32,13 @@ export function getTypeChildren(
if (referencedReflection instanceof DeclarationReflection) { if (referencedReflection instanceof DeclarationReflection) {
if (referencedReflection.children) { if (referencedReflection.children) {
children = referencedReflection.children children = referencedReflection.children
} else if (referencedReflection.type) {
children = getTypeChildren(
referencedReflection.type,
project,
level + 1
)
}
} else if (reflectionType.typeArguments?.length) { } else if (reflectionType.typeArguments?.length) {
reflectionType.typeArguments.forEach((typeArgument, index) => { reflectionType.typeArguments.forEach((typeArgument, index) => {
if (reflectionType.name === "Omit" && index > 0) { if (reflectionType.name === "Omit" && index > 0) {
@@ -37,23 +51,23 @@ export function getTypeChildren(
if (childItem.type === "literal") { if (childItem.type === "literal") {
removeChild(childItem.value?.toString(), children) removeChild(childItem.value?.toString(), children)
} else { } else {
getTypeChildren(childItem, project).forEach((child) => { getTypeChildren(childItem, project, level + 1).forEach(
(child) => {
removeChild(child.name, children) removeChild(child.name, children)
}) }
)
} }
}) })
} }
} else { } else {
const typeArgumentChildren = getTypeChildren( const typeArgumentChildren = getTypeChildren(
typeArgument, typeArgument,
project project,
level + 1
) )
children.push(...typeArgumentChildren) children.push(...typeArgumentChildren)
} }
}) })
} else if (referencedReflection.type) {
children = getTypeChildren(referencedReflection.type, project)
}
} }
break break
case "reflection": case "reflection":
@@ -62,7 +76,7 @@ export function getTypeChildren(
] ]
break break
case "array": case "array":
children = getTypeChildren(reflectionType.elementType, project) children = getTypeChildren(reflectionType.elementType, project, level + 1)
} }
return filterChildren(children) return filterChildren(children)
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+2
View File
@@ -4210,6 +4210,8 @@ __metadata:
"typedoc-config@*, typedoc-config@workspace:packages/typedoc-config": "typedoc-config@*, typedoc-config@workspace:packages/typedoc-config":
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "typedoc-config@workspace:packages/typedoc-config" resolution: "typedoc-config@workspace:packages/typedoc-config"
dependencies:
glob: ^10.3.10
peerDependencies: peerDependencies:
typedoc: 0.25.x typedoc: 0.25.x
languageName: unknown languageName: unknown
+1
View File
@@ -33,6 +33,7 @@ export * from "./line-item-adjustment"
export * from "./line-item-tax-line" export * from "./line-item-tax-line"
export * from "./money-amount" export * from "./money-amount"
export * from "./note" export * from "./note"
export * from "./notification-provider"
export * from "./notification" export * from "./notification"
export * from "./oauth" export * from "./oauth"
export * from "./order" export * from "./order"
@@ -9,7 +9,6 @@ import { SymbolMedusaWorkflowComposerContext } from "./helpers"
* @returns The step results. The results are ordered in the array by the order they're passed in the function's parameter. * @returns The step results. The results are ordered in the array by the order they're passed in the function's parameter.
* *
* @example * @example
* ```ts
* import { * import {
* createWorkflow, * createWorkflow,
* parallelize * parallelize
@@ -77,7 +77,7 @@ export interface StepExecutionContext {
*/ */
metadata: TransactionPayload["metadata"] metadata: TransactionPayload["metadata"]
/** /**
* {@inheritDoc Context} * {@inheritDoc types!Context}
*/ */
context: Context context: Context
} }
@@ -21,7 +21,7 @@ You can also create a custom batch job or overwrite Medusa’s batch jobs.
### BatchJob Entity Overview ### BatchJob Entity Overview
A batch job is stored in the database as a [BatchJob](../../references/entities/classes/BatchJob.mdx) entity. Some of its important attributes are: A batch job is stored in the database as a [BatchJob](../../references/entities/classes/entities.BatchJob.mdx) entity. Some of its important attributes are:
- `status`: A string that determines the current status of the Batch Job. - `status`: A string that determines the current status of the Batch Job.
- `context`: An object that can be used to store configurations related to the batch job. For example, you can use it to store listing configurations such as the limit or offset of the list to be retrieved during the processing of the batch job. - `context`: An object that can be used to store configurations related to the batch job. For example, you can use it to store listing configurations such as the limit or offset of the list to be retrieved during the processing of the batch job.
@@ -1948,7 +1948,7 @@ Triggered when a payment is created.
</td> </td>
<td> <td>
The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/Payment.mdx) for an idea of what fields to expect. The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/entities.Payment.mdx) for an idea of what fields to expect.
</td> </td>
</tr> </tr>
@@ -1966,7 +1966,7 @@ Triggered when a payment is updated.
</td> </td>
<td> <td>
The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/Payment.mdx) for an idea of what fields to expect. The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/entities.Payment.mdx) for an idea of what fields to expect.
</td> </td>
</tr> </tr>
@@ -1984,7 +1984,7 @@ Triggered when a payment is captured.
</td> </td>
<td> <td>
The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/Payment.mdx) for an idea of what fields to expect. The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/entities.Payment.mdx) for an idea of what fields to expect.
</td> </td>
</tr> </tr>
@@ -2002,7 +2002,7 @@ Triggered when the capturing of a payment fails.
</td> </td>
<td> <td>
The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/Payment.mdx) for an idea of what fields to expect. The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/entities.Payment.mdx) for an idea of what fields to expect.
In addition, an error object is passed within the same object as the Payment Processor: In addition, an error object is passed within the same object as the Payment Processor:
@@ -2034,7 +2034,7 @@ Triggered when a refund of a payment is created.
</td> </td>
<td> <td>
The entire refund passed as an object. You can refer to the [Refund entity](../../references/entities/classes/Refund.mdx) for an idea of what fields to expect. The entire refund passed as an object. You can refer to the [Refund entity](../../references/entities/classes/entities.Refund.mdx) for an idea of what fields to expect.
</td> </td>
</tr> </tr>
@@ -2052,7 +2052,7 @@ Triggered when a payment's refund fails.
</td> </td>
<td> <td>
The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/Payment.mdx) for an idea of what fields to expect. The entire payment passed as an object. You can refer to the [Payment entity](../../references/entities/classes/entities.Payment.mdx) for an idea of what fields to expect.
</td> </td>
</tr> </tr>
@@ -2095,7 +2095,7 @@ Triggered when a payment collection is created.
</td> </td>
<td> <td>
The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/PaymentCollection.mdx) for an idea of what fields to expect. The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/entities.PaymentCollection.mdx) for an idea of what fields to expect.
</td> </td>
</tr> </tr>
@@ -2113,7 +2113,7 @@ Triggered when a payment collection is update.
</td> </td>
<td> <td>
The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/PaymentCollection.mdx) for an idea of what fields to expect. The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/entities.PaymentCollection.mdx) for an idea of what fields to expect.
</td> </td>
</tr> </tr>
@@ -2131,7 +2131,7 @@ Triggered when a payment collection is deleted.
</td> </td>
<td> <td>
The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/PaymentCollection.mdx) for an idea of what fields to expect. The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/entities.PaymentCollection.mdx) for an idea of what fields to expect.
</td> </td>
</tr> </tr>
@@ -2149,7 +2149,7 @@ Triggered when a payment collection is either marked authorized or its payment s
</td> </td>
<td> <td>
The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/PaymentCollection.mdx) for an idea of what fields to expect. The entire payment collection passed as an object. You can refer to the [Payment Collection entity](../../references/entities/classes/entities.PaymentCollection.mdx) for an idea of what fields to expect.
</td> </td>
</tr> </tr>
@@ -2216,7 +2216,7 @@ Triggered when a product and data associated with it (options, variant orders, e
</td> </td>
<td> <td>
The entire product passed as an object. You can refer to the [Product entity](../../references/entities/classes/Product.mdx) for an idea of what fields to expect. The entire product passed as an object. You can refer to the [Product entity](../../references/entities/classes/entities.Product.mdx) for an idea of what fields to expect.
In one case, when the `/admin/products/{id}` API Route is used to update the product, the payload is an object of the following format: In one case, when the `/admin/products/{id}` API Route is used to update the product, the payload is an object of the following format:
@@ -102,7 +102,7 @@ You can learn more about plugins and how to create them in the [Plugins](../plug
::: :::
Continuing on with the previous example, if you want to use the [`OrderService`](../../references/services/classes/OrderService.mdx) later when sending notifications, you can inject it into the constructor: Continuing on with the previous example, if you want to use the [`OrderService`](../../references/services/classes/services.OrderService.mdx) later when sending notifications, you can inject it into the constructor:
```ts ```ts
import { import {
@@ -130,7 +130,7 @@ class EmailSenderService extends AbstractNotificationService {
### sendNotification ### sendNotification
When an event is triggered that your Notification Provider is registered as a handler for, the [`NotificationService`](../../references/services/classes/NotificationService.mdx) in Medusa’s core will execute the `sendNotification` method of your Notification Provider. When an event is triggered that your Notification Provider is registered as a handler for, the [`NotificationService`](../../references/services/classes/services.NotificationService.mdx) in Medusa’s core will execute the `sendNotification` method of your Notification Provider.
In this method, you can perform the necessary operation to send the Notification. Following the example above, you can send an email to the customer when they place an order. In this method, you can perform the necessary operation to send the Notification. Following the example above, you can send an email to the customer when they place an order.
@@ -138,7 +138,7 @@ This method receives three parameters:
1. `eventName`: This is the name of the event that was triggered. For example, `order.placed`. 1. `eventName`: This is the name of the event that was triggered. For example, `order.placed`.
2. `eventData`: This is the data payload of the event that was triggered. For example, if the `order.placed` event is triggered, the `eventData` object contains the property `id` which is the ID of the order that was placed. 2. `eventData`: This is the data payload of the event that was triggered. For example, if the `order.placed` event is triggered, the `eventData` object contains the property `id` which is the ID of the order that was placed.
3. `attachmentGenerator`: If you’ve previously attached a generator to the `NotificationService` using the [`registerAttachmentGenerator`](../../references/services/classes/NotificationService.mdx#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null. 3. `attachmentGenerator`: If you’ve previously attached a generator to the `NotificationService` using the [`registerAttachmentGenerator`](../../references/services/classes/services.NotificationService.mdx#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null.
:::info :::info
@@ -200,13 +200,13 @@ The `to` and `data` properties are used in the `NotificationService` in Medusa
### resendNotification ### resendNotification
Using the [Resend Notification API Route](https://docs.medusajs.com/api/admin#notifications_postnotificationsnotificationresend), an admin user can resend a Notification to the customer. The [`NotificationService`](../../references/services/classes/NotificationService.mdx) in Medusa’s core then executes the `resendNotification` method in your Notification Provider. Using the [Resend Notification API Route](https://docs.medusajs.com/api/admin#notifications_postnotificationsnotificationresend), an admin user can resend a Notification to the customer. The [`NotificationService`](../../references/services/classes/services.NotificationService.mdx) in Medusa’s core then executes the `resendNotification` method in your Notification Provider.
This method receives three parameters: This method receives three parameters:
1. `notification`: This is the original Notification record that was created after you sent the notification with `sendNotification`. You can get an overview of the entity and its attributes in the [architecture overview](./overview.mdx#notification-entity-overview), but most notably it includes the `to` and `data` attributes which are populated originally using the `to` and `data` properties of the object you return in `sendNotification`. 1. `notification`: This is the original Notification record that was created after you sent the notification with `sendNotification`. You can get an overview of the entity and its attributes in the [architecture overview](./overview.mdx#notification-entity-overview), but most notably it includes the `to` and `data` attributes which are populated originally using the `to` and `data` properties of the object you return in `sendNotification`.
2. `config`: In the Resend Notification API Route you may specify an alternative receiver of the notification using the `to` request body parameter. For example, you may want to resend the order confirmation email to a different email. If that’s the case, you have access to it in the `config` parameter object. Otherwise, `config` will be an empty object. 2. `config`: In the Resend Notification API Route you may specify an alternative receiver of the notification using the `to` request body parameter. For example, you may want to resend the order confirmation email to a different email. If that’s the case, you have access to it in the `config` parameter object. Otherwise, `config` will be an empty object.
3. `attachmentGenerator`: If you’ve previously attached a generator to the Notification Service using the [`registerAttachmentGenerator`](../../references/services/classes/NotificationService.mdx#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null. 3. `attachmentGenerator`: If you’ve previously attached a generator to the Notification Service using the [`registerAttachmentGenerator`](../../references/services/classes/services.NotificationService.mdx#registerattachmentgenerator) method, you have access to it here. You can use the `attachmentGenerator` to generate on-demand invoices or other documents. The default value of this parameter is null.
Similarly to the `sendNotification` method, this method must return an object containing two properties: Similarly to the `sendNotification` method, this method must return an object containing two properties:
@@ -25,7 +25,7 @@ An example of a notification provider is SendGrid. When an order is placed, the
### How Notification Provider is Created ### How Notification Provider is Created
A Notification Provider is essentially a Medusa [Service](../services/create-service.mdx) with a unique identifier, and it extends the [`NotificationService`](../../references/services/classes/NotificationService.mdx) provided by the `medusa-interfaces` package. It can be created as part of a [Plugin](../plugins/overview.mdx), or it can be created just as a Service file in your Medusa backend. A Notification Provider is essentially a Medusa [Service](../services/create-service.mdx) with a unique identifier, and it extends the [`NotificationService`](../../references/services/classes/services.NotificationService.mdx) provided by the `medusa-interfaces` package. It can be created as part of a [Plugin](../plugins/overview.mdx), or it can be created just as a Service file in your Medusa backend.
As a developer, you mainly work with the Notification Provider when integrating a third-party service that handles notifications in Medusa. As a developer, you mainly work with the Notification Provider when integrating a third-party service that handles notifications in Medusa.
@@ -58,7 +58,7 @@ A Notification also represents a resent notification. So, when a notification is
### Notification Entity Overview ### Notification Entity Overview
The two most important properties in the [`Notification`](../../references/entities/classes/Notification.mdx) entity are the `to` and `data` properties. The two most important properties in the [`Notification`](../../references/entities/classes/entities.Notification.mdx) entity are the `to` and `data` properties.
The `to` property is a string that represents the receiver of the Notification. For example, if the Notification was sent to an email address, the `to` property holds the email address the Notification was sent to. The `to` property is a string that represents the receiver of the Notification. For example, if the Notification was sent to an email address, the `to` property holds the email address the Notification was sent to.
@@ -88,7 +88,7 @@ You then resolve the `JobSchedulerService` and use the `jobSchedulerService.crea
- The first parameter is a unique name to give to the scheduled job. In the example above, you use the name `publish-products`. - The first parameter is a unique name to give to the scheduled job. In the example above, you use the name `publish-products`.
- The second parameter is an object which can be used to [pass data to the job](#pass-data-to-the-scheduled-job). - The second parameter is an object which can be used to [pass data to the job](#pass-data-to-the-scheduled-job).
- The third parameter is the scheduled job expression pattern. In this example, it will execute the scheduled job once a day at 12 AM. - The third parameter is the scheduled job expression pattern. In this example, it will execute the scheduled job once a day at 12 AM.
- The fourth parameter is the function to execute. This is where you add the code to execute once the scheduled job runs. In this example, you retrieve the draft products using the [ProductService](../../references/services/classes/ProductService.mdx) and update the status of each of these products to `published`. - The fourth parameter is the function to execute. This is where you add the code to execute once the scheduled job runs. In this example, you retrieve the draft products using the [ProductService](../../references/services/classes/services.ProductService.mdx) and update the status of each of these products to `published`.
:::tip :::tip
@@ -613,4 +613,4 @@ In this document, you’ll find common examples of how you can use the Pricing m
## More Examples ## More Examples
The [module interface reference](../../references/pricing/interfaces/IPricingModuleService.mdx) provides a reference to all the methods available for use with examples for each. The [module interface reference](../../references/pricing/interfaces/pricing.IPricingModuleService.mdx) provides a reference to all the methods available for use with examples for each.
@@ -155,4 +155,4 @@ For example:
You can refer to the [Example Usages documentation page](./examples.mdx) for examples of using the Pricing module. You can refer to the [Example Usages documentation page](./examples.mdx) for examples of using the Pricing module.
You can also refer to the [Module Interface Reference](../../references/pricing/interfaces/IPricingModuleService.mdx) for a detailed reference on all available methods. You can also refer to the [Module Interface Reference](../../references/pricing/interfaces/pricing.IPricingModuleService.mdx) for a detailed reference on all available methods.
@@ -185,4 +185,4 @@ module.exports = nextConfig
You can refer to the [Example Usages documentation page](./examples.mdx) for examples of using the Pricing module. You can refer to the [Example Usages documentation page](./examples.mdx) for examples of using the Pricing module.
You can also refer to the [Module Interface Reference](../../references/pricing/interfaces/IPricingModuleService.mdx) for a detailed reference on all available methods. You can also refer to the [Module Interface Reference](../../references/pricing/interfaces/pricing.IPricingModuleService.mdx) for a detailed reference on all available methods.
@@ -383,4 +383,4 @@ In this document, you’ll find common examples of how you can use the Product m
## More Examples ## More Examples
The [module interface reference](../../references/product/interfaces/IProductModuleService.mdx) provides a reference to all the methods available for use with examples for each. The [module interface reference](../../references/product/interfaces/product.IProductModuleService.mdx) provides a reference to all the methods available for use with examples for each.
@@ -150,4 +150,4 @@ For example:
You can refer to the [Example Usages documentation page](./examples.mdx) for examples of using the Product module. You can refer to the [Example Usages documentation page](./examples.mdx) for examples of using the Product module.
You can also refer to the [Module Interface Reference](../../references/product/interfaces/IProductModuleService.mdx) for a detailed reference on all available methods. You can also refer to the [Module Interface Reference](../../references/product/interfaces/product.IProductModuleService.mdx) for a detailed reference on all available methods.
@@ -195,4 +195,4 @@ module.exports = nextConfig
You can refer to the [Example Usages documentation page](./examples.mdx) for examples of using the Product module. You can refer to the [Example Usages documentation page](./examples.mdx) for examples of using the Product module.
You can also refer to the [Module Interface Reference](../../references/product/interfaces/IProductModuleService.mdx) for a detailed reference on all available methods. You can also refer to the [Module Interface Reference](../../references/product/interfaces/product.IProductModuleService.mdx) for a detailed reference on all available methods.
+4 -4
View File
@@ -66,7 +66,7 @@ After initialization, you can use the client's properties and methods to send re
You'll find in the sidebar of this reference names of different resources. These resources are properties in the Medusa client instance you initialize. You can access the methods or nested resources of each of the properties to send requests to the backend. You'll find in the sidebar of this reference names of different resources. These resources are properties in the Medusa client instance you initialize. You can access the methods or nested resources of each of the properties to send requests to the backend.
For example, to create a new customer you can access the [create](../references/js-client/classes/CustomersResource.mdx#create) method under the [customers](../references/js-client/classes/CustomersResource.mdx) property of your client: For example, to create a new customer you can access the [create](../references/js_client/classes/js_client.CustomersResource.mdx#create) method under the [customers](../references/js_client/classes/js_client.CustomersResource.mdx) property of your client:
```ts ```ts
import Medusa from "@medusajs/medusa-js" import Medusa from "@medusajs/medusa-js"
@@ -119,7 +119,7 @@ const medusa = new Medusa({
You can use a JWT token to authenticate both admin users and customers. Authentication state is managed by the client, which is ideal for Jamstack applications and mobile applications. You can use a JWT token to authenticate both admin users and customers. Authentication state is managed by the client, which is ideal for Jamstack applications and mobile applications.
You can authenticate the admin user using the [admin.auth.getToken](../references/js-client/classes/AdminAuthResource.mdx#getToken) method, and the customer using the [auth.getToken](../references/js-client/classes/AuthResource.mdx#getToken) method. You can authenticate the admin user using the [admin.auth.getToken](../references/js_client/classes/js_client.AdminAuthResource.mdx#getToken) method, and the customer using the [auth.getToken](../references/js_client/classes/js_client.AuthResource.mdx#getToken) method.
Once the user or customer is authenticated successfully, the Medusa client automatically attaches an Authorization Bearer header to all subsequent requests. Once the user or customer is authenticated successfully, the Medusa client automatically attaches an Authorization Bearer header to all subsequent requests.
@@ -164,7 +164,7 @@ For example:
You can authenticate admin users or customers using cookie session ID. You can authenticate admin users or customers using cookie session ID.
You can authenticate the admin user using the [admin.auth.createSession](../references/js-client/classes/AdminAuthResource.mdx#createSession) method, and the customer using the [auth.authenticate](../references/js-client/classes/AuthResource.mdx#authenticate) method. You can authenticate the admin user using the [admin.auth.createSession](../references/js_client/classes/js_client.AdminAuthResource.mdx#createSession) method, and the customer using the [auth.authenticate](../references/js_client/classes/js_client.AuthResource.mdx#authenticate) method.
Once the user or customer is authenticated successfully, the Medusa client sets and attached the session ID in the cookie for all subsequent requests. Once the user or customer is authenticated successfully, the Medusa client sets and attached the session ID in the cookie for all subsequent requests.
@@ -209,7 +209,7 @@ For example:
You can authenticate admin users with a personal API Token. You can authenticate admin users with a personal API Token.
If a user doesn't have a personal API token, create one with the [admin.users.update](../references/js-client/classes/AdminUsersResource.mdx#update) method: If a user doesn't have a personal API token, create one with the [admin.users.update](../references/js_client/classes/js_client.AdminUsersResource.mdx#update) method:
<Tabs groupId="client-type" isCodeTabs={true}> <Tabs groupId="client-type" isCodeTabs={true}>
<TabItem value="js-client" label="JS Client" default> <TabItem value="js-client" label="JS Client" default>
@@ -26,13 +26,13 @@ A cart is represented by the `Cart` entity. Some of the `Cart` entity’s attrib
- `completed_at`: the date the cart was completed. A completed cart means that it has been used for its main purpose. For example, if the cart is used to place an order, then a completed cart means that the order was placed. - `completed_at`: the date the cart was completed. A completed cart means that it has been used for its main purpose. For example, if the cart is used to place an order, then a completed cart means that the order was placed.
- `payment_authorized_at`: the date a payment was authorized. - `payment_authorized_at`: the date a payment was authorized.
There are other important attributes discussed in later sections. Check out the [full Cart entity in the entities reference](../../references/entities/classes/Cart.mdx). There are other important attributes discussed in later sections. Check out the [full Cart entity in the entities reference](../../references/entities/classes/entities.Cart.mdx).
--- ---
## Cart Totals Calculation ## Cart Totals Calculation
By default, the `Cart` entity doesn’t hold any details regarding the totals. These are computed and added to the cart instance using the `CartService`'s [decorateTotals method](../../references/services/classes/CartService.mdx#decoratetotals). There's also a dedicated method in the `CartService`, [retrieveWithTotals](../../references/services/classes/CartService.mdx#retrieveWithTotals), attaching the totals automatically. It is recommended to use this method by default when you need to retrieve the cart. By default, the `Cart` entity doesn’t hold any details regarding the totals. These are computed and added to the cart instance using the `CartService`'s [decorateTotals method](../../references/services/classes/services.CartService.mdx#decoratetotals). There's also a dedicated method in the `CartService`, [retrieveWithTotals](../../references/services/classes/services.CartService.mdx#retrieveWithTotals), attaching the totals automatically. It is recommended to use this method by default when you need to retrieve the cart.
The cart’s totals are calculated based on the content and context of the cart. This includes the selected region, whether tax-inclusive pricing is enabled, the chosen shipping methods, and more. The cart’s totals are calculated based on the content and context of the cart. This includes the selected region, whether tax-inclusive pricing is enabled, the chosen shipping methods, and more.
@@ -83,11 +83,11 @@ You can learn how to override the cart completion strategy [here](./backend/cart
The process is implemented as follows: The process is implemented as follows:
1. When the idempotency key’s recovery point is set to `started`, the tax lines are created for the items in the cart. This is done using the `CartService`'s [createTaxLines method](../../references/services/classes/CartService.mdx#createtaxlines). If that is completed with no errors, the recovery point is set to `tax_lines_created` and the process continues. 1. When the idempotency key’s recovery point is set to `started`, the tax lines are created for the items in the cart. This is done using the `CartService`'s [createTaxLines method](../../references/services/classes/services.CartService.mdx#createtaxlines). If that is completed with no errors, the recovery point is set to `tax_lines_created` and the process continues.
2. When the idempotency key’s recovery point is set to `tax_lines_created`, the payment is authorized using the `CartService`'s method [authorizePayment](../../references/services/classes/CartService.mdx#authorizepayment). If the payment requires more action or is pending authorization, then the tax lines that were created in the previous steps are deleted and the cart completion process is terminated. Once the payment is authorized, the process can be restarted. 2. When the idempotency key’s recovery point is set to `tax_lines_created`, the payment is authorized using the `CartService`'s method [authorizePayment](../../references/services/classes/services.CartService.mdx#authorizepayment). If the payment requires more action or is pending authorization, then the tax lines that were created in the previous steps are deleted and the cart completion process is terminated. Once the payment is authorized, the process can be restarted.
3. When the idempotency key’s recovery point is set to `payment_authorized`, tax lines are created again the same way as the first step. Then, the inventory of each of the items in the cart is confirmed using the `ProductVariantInventoryService`'s method [confirmInventory](../../references/services/classes/ProductVariantInventoryService.mdx#confirminventory). If an item is in stock, the quantity is reserved using the `ProductVariantInventoryService`'s method [reserveQuantity](../../references/services/classes/ProductVariantInventoryService.mdx#reservequantity). If an item is out of stock, any item reservations that were created are deleted, the payment is canceled, and an error is thrown, terminating the cart completion process. If all item quantities are confirmed to be available: 3. When the idempotency key’s recovery point is set to `payment_authorized`, tax lines are created again the same way as the first step. Then, the inventory of each of the items in the cart is confirmed using the `ProductVariantInventoryService`'s method [confirmInventory](../../references/services/classes/services.ProductVariantInventoryService.mdx#confirminventory). If an item is in stock, the quantity is reserved using the `ProductVariantInventoryService`'s method [reserveQuantity](../../references/services/classes/services.ProductVariantInventoryService.mdx#reservequantity). If an item is out of stock, any item reservations that were created are deleted, the payment is canceled, and an error is thrown, terminating the cart completion process. If all item quantities are confirmed to be available:
1. If the cart belongs to a swap (the `type` attribute is set to `swap`), the swap is registered as completed using the `SwapService`'s [registerCartCompletion method](../../references/services/classes/SwapService.mdx#registercartcompletion) and the inventory item reservations are removed using the Inventory module. The process ends successfully here for a swap. 1. If the cart belongs to a swap (the `type` attribute is set to `swap`), the swap is registered as completed using the `SwapService`'s [registerCartCompletion method](../../references/services/classes/services.SwapService.mdx#registercartcompletion) and the inventory item reservations are removed using the Inventory module. The process ends successfully here for a swap.
2. If the cart belongs to an order, the order is created using the `OrderService`'s method [createFromCart](../../references/services/classes/OrderService.mdx#createfromcart). The order is then retrieved and sent in the response. 2. If the cart belongs to an order, the order is created using the `OrderService`'s method [createFromCart](../../references/services/classes/services.OrderService.mdx#createfromcart). The order is then retrieved and sent in the response.
4. Once the process detailed above is done, the idempotency key’s recovery point is set to `finished`. 4. Once the process detailed above is done, the idempotency key’s recovery point is set to `finished`.
--- ---
@@ -58,7 +58,7 @@ It’s important to enable a payment processor in a region, or else the payment
### PaymentProvider Entity Overview ### PaymentProvider Entity Overview
The [`PaymentProvider`](../../references/entities/classes/PaymentProvider.mdx) entity only has 2 attributes: `is_installed` which is a boolean value indicating whether the Payment Processor is installed; and `id` which is the unique identifier that you define in the Payment Processor service. The [`PaymentProvider`](../../references/entities/classes/entities.PaymentProvider.mdx) entity only has 2 attributes: `is_installed` which is a boolean value indicating whether the Payment Processor is installed; and `id` which is the unique identifier that you define in the Payment Processor service.
--- ---
@@ -82,7 +82,7 @@ Among the Payment Sessions available only one will be selected based on the cust
### PaymentSession Entity Overview ### PaymentSession Entity Overview
The [`PaymentSession`](../../references/entities/classes/PaymentSession.mdx) entity belongs to a `Cart`. This is the customer‘s cart that was used for checkout which lead to the creation of the Payment Session. The [`PaymentSession`](../../references/entities/classes/entities.PaymentSession.mdx) entity belongs to a `Cart`. This is the customer‘s cart that was used for checkout which lead to the creation of the Payment Session.
The `PaymentSession` instance also belongs to a `PaymentProvider` instance. This is the Payment Processor that was used to create the Payment Session and that controls it for further actions like authorizing the payment. The `PaymentSession` instance also belongs to a `PaymentProvider` instance. This is the Payment Processor that was used to create the Payment Session and that controls it for further actions like authorizing the payment.
@@ -116,7 +116,7 @@ When the store operator then chooses to capture the order from the Medusa Admin,
### Payment Entity Overview ### Payment Entity Overview
The [`Payment`](../../references/entities/classes/Payment.mdx) entity belongs to the `Cart` that it was originally created from when the customer’s payment was authorized. It also belongs to an `Order` once it’s placed. Additionally, it belongs to a `PaymentProvider` which is the payment processor that the customer chose on checkout. The [`Payment`](../../references/entities/classes/entities.Payment.mdx) entity belongs to the `Cart` that it was originally created from when the customer’s payment was authorized. It also belongs to an `Order` once it’s placed. Additionally, it belongs to a `PaymentProvider` which is the payment processor that the customer chose on checkout.
In case a `Swap` is created for an order, `Payment` will be associated with that swap to handle payment operations related to it. In case a `Swap` is created for an order, `Payment` will be associated with that swap to handle payment operations related to it.
@@ -49,7 +49,7 @@ Once the Fulfillment Provider is added to the backend, the store operator will b
### FulfillmentProvider Entity Overview ### FulfillmentProvider Entity Overview
The [`FulfillmentProvider`](../../references/entities/classes/FulfillmentProvider.mdx) entity only has 2 attributes: `is_installed` to indicate if the fulfillment provider is installed and its value is a boolean; and `id` which is the unique identifier that you define in the Fulfillment Provider Service. The [`FulfillmentProvider`](../../references/entities/classes/entities.FulfillmentProvider.mdx) entity only has 2 attributes: `is_installed` to indicate if the fulfillment provider is installed and its value is a boolean; and `id` which is the unique identifier that you define in the Fulfillment Provider Service.
--- ---
@@ -73,7 +73,7 @@ For example, shipping heavy items might be more expensive than others, which wou
### ShippingProfile Entity Overview ### ShippingProfile Entity Overview
The [`ShippingProfile`](../../references/entities/classes/ShippingProfile.mdx) entity can have a set of `Product` instances. These would be the products the shipping profile is providing shipping options for. The [`ShippingProfile`](../../references/entities/classes/entities.ShippingProfile.mdx) entity can have a set of `Product` instances. These would be the products the shipping profile is providing shipping options for.
The `ShippingProfile` has a `type` attribute that can be `default`, `gift_card`, or `custom`. The `ShippingProfile` has a `type` attribute that can be `default`, `gift_card`, or `custom`.
@@ -101,7 +101,7 @@ Think of a shipping option as a template defined by the admin that indicates wha
### ShippingOption Entity Overview ### ShippingOption Entity Overview
The [`ShippingOption`](../../references/entities/classes/ShippingOption.mdx) entity belongs to the `ShippingProfile` entity. The [`ShippingOption`](../../references/entities/classes/entities.ShippingOption.mdx) entity belongs to the `ShippingProfile` entity.
The `ShippingOption` entity also belongs to a `FulfillmentProvider`. This can be either a custom third-party provider or one of Medusa’s default fulfillment providers. The `ShippingOption` entity also belongs to a `FulfillmentProvider`. This can be either a custom third-party provider or one of Medusa’s default fulfillment providers.
@@ -139,7 +139,7 @@ This separation allows for developers to implement the custom integration with t
A lot of the shipping method’s attributes are similar to the shipping option’s attribute. A lot of the shipping method’s attributes are similar to the shipping option’s attribute.
The [`ShippingMethod`](../../references/entities/classes/ShippingMethod.mdx) entity belongs to a `ShippingOption`. The [`ShippingMethod`](../../references/entities/classes/entities.ShippingMethod.mdx) entity belongs to a `ShippingOption`.
Similar to the `data` attribute explained for the `ShippingOption` entity, a `ShippingMethod` has a similar `data` attribute that includes all the data to be sent to the fulfillment provider when fulfilling the order. Similar to the `data` attribute explained for the `ShippingOption` entity, a `ShippingMethod` has a similar `data` attribute that includes all the data to be sent to the fulfillment provider when fulfilling the order.
@@ -153,5 +153,5 @@ The `ShippingMethod` instance holds a `price` attribute, which will either b
## See Also ## See Also
- [Create a Fulfillment Provider](../../references/fulfillment/classes/AbstractFulfillmentService.mdx) - [Create a Fulfillment Provider](../../references/fulfillment/classes/fulfillment.AbstractFulfillmentService.mdx)
- [Available shipping plugins](https://github.com/medusajs/medusa/tree/master/packages) - [Available shipping plugins](https://github.com/medusajs/medusa/tree/master/packages)
@@ -24,7 +24,7 @@ The customer groups feature can be used in a variety of use cases including:
## CustomerGroup Entity Overview ## CustomerGroup Entity Overview
A customer group is stored in the database as a [CustomerGroup](../../references/entities/classes/CustomerGroup.mdx) entity. This entity has two attributes other than the `id`: `name` and `metadata`. A customer group is stored in the database as a [CustomerGroup](../../references/entities/classes/entities.CustomerGroup.mdx) entity. This entity has two attributes other than the `id`: `name` and `metadata`.
Similar to all entities in Medusa, you can use the `metadata` object attribute to store any custom data you want. For example, you can add some flag or tag to the customer group for a custom use case: Similar to all entities in Medusa, you can use the `metadata` object attribute to store any custom data you want. For example, you can add some flag or tag to the customer group for a custom use case:
@@ -191,9 +191,9 @@ This request accepts [many request-body parameters](https://docs.medusajs.com/ap
- `code`: This parameter is required. It is a unique code. The customer redeems the discount using this code. - `code`: This parameter is required. It is a unique code. The customer redeems the discount using this code.
- `rule`: This parameter is required. It is an object having at least the following fields: - `rule`: This parameter is required. It is an object having at least the following fields:
- `type`: A string indicating the type of discount. It can be `fixed`, `percentage`, or `free_shipping`. When using the Medusa JS Client, you must use the enum type [DiscountRuleType](../../../references/js-client/internal/enums/internal.internal.DiscountRuleType.mdx) for the value. - `type`: A string indicating the type of discount. It can be `fixed`, `percentage`, or `free_shipping`. When using the Medusa JS Client, you must use the enum type [DiscountRuleType](../../../references/entities/enums/entities.DiscountRuleType.mdx) for the value.
- `value`: A number indicating the value of the discount. If the discount type is `fixed`, then it will be the fixed amount to discount from the cart’s totals or its items. If the discount type is `percentage`, then it will be the percentage to discount from the items in the cart. If the type is `free_shipping`, it has no effect and can be set to `0`. - `value`: A number indicating the value of the discount. If the discount type is `fixed`, then it will be the fixed amount to discount from the cart’s totals or its items. If the discount type is `percentage`, then it will be the percentage to discount from the items in the cart. If the type is `free_shipping`, it has no effect and can be set to `0`.
- `allocation`: A string indicating how the discount should be applied. Can be `item` or `total`. If the type is not `fixed`, then this has no effect. When using the Medusa JS Client, you must use the enum type [AllocationType](../../../references/js-client/internal/enums/internal.internal.AllocationType.mdx) for the value. - `allocation`: A string indicating how the discount should be applied. Can be `item` or `total`. If the type is not `fixed`, then this has no effect. When using the Medusa JS Client, you must use the enum type [AllocationType](../../../references/entities/enums/entities.AllocationType.mdx) for the value.
- `regions`: An array of region IDs this discount can be used in. If the type of discount is `fixed`, only one region can be passed. - `regions`: An array of region IDs this discount can be used in. If the type of discount is `fixed`, only one region can be passed.
This request returns the full `discount` object. This request returns the full `discount` object.
@@ -32,7 +32,7 @@ Discounts can be used in many use cases including:
## Discount Entity Overview ## Discount Entity Overview
A discount is represented by the [`Discount`](../../references/entities/classes/Discount.mdx) entity. Some of its important attributes are: A discount is represented by the [`Discount`](../../references/entities/classes/entities.Discount.mdx) entity. Some of its important attributes are:
- `code` is a unique code that you specify when you create the discount. Customers use this code to apply the discount during checkout. The code can only include upper-case letters and numbers. - `code` is a unique code that you specify when you create the discount. Customers use this code to apply the discount during checkout. The code can only include upper-case letters and numbers.
- `rule_id` is the ID of the rule of this discount. The `rule` attribute is the expanded object of the `DiscountRule` entity. You can use the `rule` attribute to get details regarding the discount type. You can learn more about this in the [`DiscountRule` entity overview](#discountrule-entity-overview) later. - `rule_id` is the ID of the rule of this discount. The `rule` attribute is the expanded object of the `DiscountRule` entity. You can use the `rule` attribute to get details regarding the discount type. You can learn more about this in the [`DiscountRule` entity overview](#discountrule-entity-overview) later.
@@ -54,7 +54,7 @@ The `is_dynamic` attribute in the `Discount` entity is a boolean value that dete
## DiscountRule Entity Overview ## DiscountRule Entity Overview
Every `Discount` entity belongs to a [`DiscountRule`](../../references/entities/classes/DiscountRule.mdx) entity. `DiscountRule` includes details such as the type of discount, the amount to be discounted, and more. Every `Discount` entity belongs to a [`DiscountRule`](../../references/entities/classes/entities.DiscountRule.mdx) entity. `DiscountRule` includes details such as the type of discount, the amount to be discounted, and more.
Some of the `DiscountRule` entity’s important attributes are: Some of the `DiscountRule` entity’s important attributes are:
@@ -71,7 +71,7 @@ Some of the `DiscountRule` entity’s important attributes are:
A discount can optionally have discount conditions. Discount conditions are used to further add limitations on when the discount can be applied. A discount can optionally have discount conditions. Discount conditions are used to further add limitations on when the discount can be applied.
A [`DiscountCondition`](../../references/entities/classes/DiscountCondition.mdx) belongs to a `DiscountRule` entity. The `discount_rule_id` attribute indicates the ID of the `DiscountRule` it belongs to. A [`DiscountCondition`](../../references/entities/classes/entities.DiscountCondition.mdx) belongs to a `DiscountRule` entity. The `discount_rule_id` attribute indicates the ID of the `DiscountRule` it belongs to.
Discount conditions have an attribute `type` that indicates the condition’s type. Its value must be one of the following: Discount conditions have an attribute `type` that indicates the condition’s type. Its value must be one of the following:
@@ -92,11 +92,11 @@ Discount conditions also have an attribute `operator` that indicates how the con
Based on the value of `type`, one of the following relations can be used to retrieve the condition’s items: Based on the value of `type`, one of the following relations can be used to retrieve the condition’s items:
- `products` is an array of products that this condition applies to if the condition’s `type` is `products`. Each item of the array would be a [`DiscountConditionProduct`](../../references/entities/classes/DiscountConditionProduct.mdx). - `products` is an array of products that this condition applies to if the condition’s `type` is `products`. Each item of the array would be a [`DiscountConditionProduct`](../../references/entities/classes/entities.DiscountConditionProduct.mdx).
- `product_types` is an array of product types that this condition applies to if the condition’s `type` is `product_types`. Each item of the array would be a [`DiscountConditionProductType`](../../references/entities/classes/DiscountConditionProductType.mdx). - `product_types` is an array of product types that this condition applies to if the condition’s `type` is `product_types`. Each item of the array would be a [`DiscountConditionProductType`](../../references/entities/classes/entities.DiscountConditionProductType.mdx).
- `product_collections` is an array of product collections that this condition applies to if the condition’s `type` is `product_collections`. Each item of the array would be a [`DiscountConditionProductCollection`](../../references/entities/classes/DiscountConditionProductCollection.mdx). - `product_collections` is an array of product collections that this condition applies to if the condition’s `type` is `product_collections`. Each item of the array would be a [`DiscountConditionProductCollection`](../../references/entities/classes/entities.DiscountConditionProductCollection.mdx).
- `product_tags` is an array of product tags that this condition applies to if the condition’s `type` is `product_tags`. Each item of the array would be a [`DiscountConditionProductTag`](../../references/entities/classes/DiscountConditionProductTag.mdx). - `product_tags` is an array of product tags that this condition applies to if the condition’s `type` is `product_tags`. Each item of the array would be a [`DiscountConditionProductTag`](../../references/entities/classes/entities.DiscountConditionProductTag.mdx).
- `customer_groups` is an array of customer groups that this condition applies to if the condition’s `type` is `customer_groups`. Each item of the array would be a [`DiscountConditionCustomerGroup`](../../references/entities/classes/DiscountConditionCustomerGroup.mdx). - `customer_groups` is an array of customer groups that this condition applies to if the condition’s `type` is `customer_groups`. Each item of the array would be a [`DiscountConditionCustomerGroup`](../../references/entities/classes/entities.DiscountConditionCustomerGroup.mdx).
![Discounts Architecture](https://res.cloudinary.com/dza7lstvk/image/upload/v1678372360/Medusa%20Docs/Diagrams/discounts_ioivrl.png) ![Discounts Architecture](https://res.cloudinary.com/dza7lstvk/image/upload/v1678372360/Medusa%20Docs/Diagrams/discounts_ioivrl.png)
@@ -34,7 +34,7 @@ As custom gift cards can be used once they’re created, they’re also represen
## GiftCard Entity Overview ## GiftCard Entity Overview
Some of the [GiftCard](../../references/entities/classes/GiftCard.mdx) entity’s attributes are: Some of the [GiftCard](../../references/entities/classes/entities.GiftCard.mdx) entity’s attributes are:
- `code`: a unique string of random characters. This is the code that the customer can use during their checkout to redeem the gift card. - `code`: a unique string of random characters. This is the code that the customer can use during their checkout to redeem the gift card.
- `value`: The amount of the gift card. This is the amount the customer purchased, or was gifted in the case of custom gift cards. - `value`: The amount of the gift card. This is the amount the customer purchased, or was gifted in the case of custom gift cards.
@@ -208,7 +208,7 @@ For example, you can filter the orders by one or more status:
:::note :::note
You can check available order statuses [here](../../../references/entities/enums/OrderStatus.mdx). You can check available order statuses [here](../../../references/entities/enums/entities.OrderStatus.mdx).
::: :::
+17 -17
View File
@@ -19,12 +19,12 @@ The Medusa core provides the necessary implementation and functionalities that a
A claim is represented by the `ClaimOrder` entity. Some of its attributes include: A claim is represented by the `ClaimOrder` entity. Some of its attributes include:
- `type`: a string indicating the type of the claim. Its value can be either `refund` or `replace`. - `type`: a string indicating the type of the claim. Its value can be either `refund` or `replace`.
- `payment_status`: a string indicating the status of the claim’s payment. Its possible values are indicated by the [ClaimPaymentStatus enum](../../references/entities/enums/ClaimPaymentStatus.mdx). This attribute is useful to check the status of the payment if the claim’s type is `refund`. - `payment_status`: a string indicating the status of the claim’s payment. Its possible values are indicated by the [ClaimPaymentStatus enum](../../references/entities/enums/entities.ClaimPaymentStatus.mdx). This attribute is useful to check the status of the payment if the claim’s type is `refund`.
- `fulfillment_status`: a string indicating the status of the claim’s fulfillment. Its possible values are indicated by the [ClaimFulfillmentStatus enum](../../references/entities/enums/ClaimFulfillmentStatus.mdx). This attribute is useful to check the status of the fulfillment if the claim’s type is `replace`. - `fulfillment_status`: a string indicating the status of the claim’s fulfillment. Its possible values are indicated by the [ClaimFulfillmentStatus enum](../../references/entities/enums/entities.ClaimFulfillmentStatus.mdx). This attribute is useful to check the status of the fulfillment if the claim’s type is `replace`.
- `refund_amount`: an integer used to indicate the amount that should be refunded to the customer. This is only useful if the claim’s type is `refund`. - `refund_amount`: an integer used to indicate the amount that should be refunded to the customer. This is only useful if the claim’s type is `refund`.
- `canceled_at`: a date indicating when the claim was canceled. - `canceled_at`: a date indicating when the claim was canceled.
There are other important attributes discussed in later sections. Check out the [full ClaimOrder entity in the entities reference](../../references/entities/classes/ClaimOrder.mdx). There are other important attributes discussed in later sections. Check out the [full ClaimOrder entity in the entities reference](../../references/entities/classes/entities.ClaimOrder.mdx).
--- ---
@@ -32,7 +32,7 @@ There are other important attributes discussed in later sections. Check out the
Claims are created in Medusa by an admin (typically a merchant). They are created on an order, and depending on the claim’s type the admin can specify details like the amount to be refunded, or the items to be returned and the new items to replace them. Claims are created in Medusa by an admin (typically a merchant). They are created on an order, and depending on the claim’s type the admin can specify details like the amount to be refunded, or the items to be returned and the new items to replace them.
You can create a claim either using the [Create Claim API Route](https://docs.medusajs.com/api/admin#orders_postordersorderclaims) or using the `ClaimService`'s [create method](../../references/services/classes/ClaimService.mdx#create). This section explains the process within the Create Claim API Route, with a focus on the `create` method. You can create a claim either using the [Create Claim API Route](https://docs.medusajs.com/api/admin#orders_postordersorderclaims) or using the `ClaimService`'s [create method](../../references/services/classes/services.ClaimService.mdx#create). This section explains the process within the Create Claim API Route, with a focus on the `create` method.
### Idempotency Key ### Idempotency Key
@@ -46,16 +46,16 @@ The following flow is implemented within the Create Claim API Route:
![Create Claim API Route Overview](https://res.cloudinary.com/dza7lstvk/image/upload/v1682519207/Medusa%20Docs/Diagrams/create-claim-overview_iqek1f.jpg) ![Create Claim API Route Overview](https://res.cloudinary.com/dza7lstvk/image/upload/v1682519207/Medusa%20Docs/Diagrams/create-claim-overview_iqek1f.jpg)
1. When the idempotency key’s recovery point is `started`, the creation of the claim is started using the `ClaimService`'s [create method](../../references/services/classes/ClaimService.mdx#create). If the claim is created successfully, the idempotency key’s recovery point is changed to `claim_created`. In the `create` method: 1. When the idempotency key’s recovery point is `started`, the creation of the claim is started using the `ClaimService`'s [create method](../../references/services/classes/services.ClaimService.mdx#create). If the claim is created successfully, the idempotency key’s recovery point is changed to `claim_created`. In the `create` method:
1. If the type of the claim is `refund` and no refund amount is set, the refund amount is calculated based on the items in the claim using the `ClaimService`'s [getRefundTotalForClaimLinesOnOrder method](../../references/services/classes/ClaimService.mdx#getrefundtotalforclaimlinesonorder). 1. If the type of the claim is `refund` and no refund amount is set, the refund amount is calculated based on the items in the claim using the `ClaimService`'s [getRefundTotalForClaimLinesOnOrder method](../../references/services/classes/services.ClaimService.mdx#getrefundtotalforclaimlinesonorder).
2. If new items are specified to send to the customer, new line items, which are represented by the `LineItem` entity, are generated using the `LineItemService`'s [generate method](../../references/services/classes/LineItemService.mdx#generate). These line items are later attached to the claim when it’s created under the `additional_items` relation. Also, the quantity of these items are reserved from the product variant’s inventory using the `ProductVariantInventoryService`'s [reserveQuantity method](../../references/services/classes/ProductVariantInventoryService.mdx#reservequantity). 2. If new items are specified to send to the customer, new line items, which are represented by the `LineItem` entity, are generated using the `LineItemService`'s [generate method](../../references/services/classes/services.LineItemService.mdx#generate). These line items are later attached to the claim when it’s created under the `additional_items` relation. Also, the quantity of these items are reserved from the product variant’s inventory using the `ProductVariantInventoryService`'s [reserveQuantity method](../../references/services/classes/services.ProductVariantInventoryService.mdx#reservequantity).
3. The claim is created and saved. 3. The claim is created and saved.
4. If there were additional items attached to the claim, tax lines are created for these items using the `TaxProviderService`'s [createTaxLines method](../../references/services/classes/TaxProviderService.mdx#createtaxlines). 4. If there were additional items attached to the claim, tax lines are created for these items using the `TaxProviderService`'s [createTaxLines method](../../references/services/classes/services.TaxProviderService.mdx#createtaxlines).
5. If a shipping method was chosen to send the additional items to the customer, the shipping method is created using the `ShippingOptionService`'s [createShippingMethod method](../../references/services/classes/ShippingOptionService.mdx#createshippingmethod) or updated if it already exists using the `ShippingOptionService`'s [updateShippingMethod method](../../references/services/classes/ShippingOptionService.mdx#updateshippingmethod). 5. If a shipping method was chosen to send the additional items to the customer, the shipping method is created using the `ShippingOptionService`'s [createShippingMethod method](../../references/services/classes/services.ShippingOptionService.mdx#createshippingmethod) or updated if it already exists using the `ShippingOptionService`'s [updateShippingMethod method](../../references/services/classes/services.ShippingOptionService.mdx#updateshippingmethod).
6. A claim item is created for each of the items specified in the claim. These are the items that were originally in the order and that the claim was created for. The claim items are created using the `ClaimItemService`'s [create method](../../references/services/classes/ClaimItemService.mdx#create). 6. A claim item is created for each of the items specified in the claim. These are the items that were originally in the order and that the claim was created for. The claim items are created using the `ClaimItemService`'s [create method](../../references/services/classes/services.ClaimItemService.mdx#create).
7. If a return shipping method is specified, a return is created using the `ReturnService`'s [create method](../../references/services/classes/ReturnService.mdx#create). 7. If a return shipping method is specified, a return is created using the `ReturnService`'s [create method](../../references/services/classes/services.ReturnService.mdx#create).
2. When the idempotency key’s recovery point is `claim_created`, if the claim’s type is `refund`, the refund is processed using the `ClaimService`'s [processRefund method](../../references/services/classes/ClaimService.mdx#processrefund). If the method is refunded successfully, the `payment_status` attribute of the claim is set to `refunded`. The refund is created directly on the order the claim belongs to. The recovery point of the idempotency key is changed to `refund_handled` at the end of this process. 2. When the idempotency key’s recovery point is `claim_created`, if the claim’s type is `refund`, the refund is processed using the `ClaimService`'s [processRefund method](../../references/services/classes/services.ClaimService.mdx#processrefund). If the method is refunded successfully, the `payment_status` attribute of the claim is set to `refunded`. The refund is created directly on the order the claim belongs to. The recovery point of the idempotency key is changed to `refund_handled` at the end of this process.
3. When the idempotency key’s recovery point is `refund_handled`, if the claim is associated with a return, the return is automatically fulfilled using the `ReturnService`'s [fulfill method](../../references/services/classes/ReturnService.mdx#fulfill) as it will be handled by the customer. The order associated with the claim is then returned and the idempotency key is set to `finished`. 3. When the idempotency key’s recovery point is `refund_handled`, if the claim is associated with a return, the return is automatically fulfilled using the `ReturnService`'s [fulfill method](../../references/services/classes/services.ReturnService.mdx#fulfill) as it will be handled by the customer. The order associated with the claim is then returned and the idempotency key is set to `finished`.
--- ---
@@ -63,7 +63,7 @@ The following flow is implemented within the Create Claim API Route:
If a claim’s type is `replace`, an admin can create a [fulfillment](./fulfillments.md) for the additional items that should be sent to the customer. If a claim’s type is `replace`, an admin can create a [fulfillment](./fulfillments.md) for the additional items that should be sent to the customer.
A fulfillment can be created either using the [Create Claim Fulfillment API Route](https://docs.medusajs.com/api/admin#orders_postordersorderclaimsclaimfulfillments) or the `ClaimService`'s [createFulfillment method](../../references/services/classes/ClaimService.mdx#createfulfillment). A fulfillment can be created either using the [Create Claim Fulfillment API Route](https://docs.medusajs.com/api/admin#orders_postordersorderclaimsclaimfulfillments) or the `ClaimService`'s [createFulfillment method](../../references/services/classes/services.ClaimService.mdx#createfulfillment).
:::note :::note
@@ -73,9 +73,9 @@ The API Route handles updating the inventory and reservations. So, if you choose
By default, when a fulfillment is created, the claim’s `fulfillment_status` is set to `fulfilled`. However, if any of the item’s quantity isn’t fulfilled successfully, the `fulfillment_status` is set to `requires_action`. By default, when a fulfillment is created, the claim’s `fulfillment_status` is set to `fulfilled`. However, if any of the item’s quantity isn’t fulfilled successfully, the `fulfillment_status` is set to `requires_action`.
After creating a fulfillment, you can create a shipment for the fulfillment either using the [Create Claim Shipment API Route](https://docs.medusajs.com/api/admin#orders_postordersorderclaimsclaimshipments) or the `ClaimService`'s [createShipment method](../../references/services/classes/ClaimService.mdx#createshipment). If only some of the items and their quantities are shipped, the `fulfillment_status` of the claim is set to `partially_shipped`. Otherwise, if all items and quantities are shipped, the `fulfillment_status` of the claim is set to `shipped`. After creating a fulfillment, you can create a shipment for the fulfillment either using the [Create Claim Shipment API Route](https://docs.medusajs.com/api/admin#orders_postordersorderclaimsclaimshipments) or the `ClaimService`'s [createShipment method](../../references/services/classes/services.ClaimService.mdx#createshipment). If only some of the items and their quantities are shipped, the `fulfillment_status` of the claim is set to `partially_shipped`. Otherwise, if all items and quantities are shipped, the `fulfillment_status` of the claim is set to `shipped`.
You can alternatively cancel a fulfillment either using the [Cancel Claim Fulfillment API Route](https://docs.medusajs.com/api/admin#tag/Orders/operation/PostOrdersClaimFulfillmentsCancel) or the `ClaimService`'s [cancelFulfillment method](../../references/services/classes/ClaimService.mdx#cancelfulfillment). This would change the `fulfillment_status` of the claim to `canceled`. You can alternatively cancel a fulfillment either using the [Cancel Claim Fulfillment API Route](https://docs.medusajs.com/api/admin#tag/Orders/operation/PostOrdersClaimFulfillmentsCancel) or the `ClaimService`'s [cancelFulfillment method](../../references/services/classes/services.ClaimService.mdx#cancelfulfillment). This would change the `fulfillment_status` of the claim to `canceled`.
--- ---
@@ -87,7 +87,7 @@ A claim's return can be marked as received, which would adjust the inventory and
## Cancel a Claim ## Cancel a Claim
An admin can cancel a claim if it hasn’t been refunded either using the [Cancel Claim API Route](https://docs.medusajs.com/api/admin#orders_postordersclaimcancel) or the `ClaimService`'s [cancel method](../../references/services/classes/ClaimService.mdx#cancel). An admin can cancel a claim if it hasn’t been refunded either using the [Cancel Claim API Route](https://docs.medusajs.com/api/admin#orders_postordersclaimcancel) or the `ClaimService`'s [cancel method](../../references/services/classes/services.ClaimService.mdx#cancel).
If any fulfillments were created, they must be canceled first. Similarly, if the claim is associated with a return, the return must be canceled first. If any fulfillments were created, they must be canceled first. Similarly, if the claim is associated with a return, the return must be canceled first.
@@ -26,7 +26,7 @@ Some of the `DraftOrder`'s attributes include:
- `completed_at`: a date indicating when the draft order was completed. - `completed_at`: a date indicating when the draft order was completed.
- `no_notification_order`: a boolean indicating whether the customer should receive notifications when the order is updated. - `no_notification_order`: a boolean indicating whether the customer should receive notifications when the order is updated.
There are other important attributes discussed in later sections. Check out the [full DraftOrder entity in the entities reference](../../references/entities/classes/DraftOrder.mdx). There are other important attributes discussed in later sections. Check out the [full DraftOrder entity in the entities reference](../../references/entities/classes/entities.DraftOrder.mdx).
--- ---
@@ -34,11 +34,11 @@ There are other important attributes discussed in later sections. Check out the
You have full freedom in how you choose to implement creating draft orders. This section explains how it’s created in the Medusa backend using the [Create Draft Order](https://docs.medusajs.com/api/admin#draft-orders_postdraftorders) and [Register Payment](https://docs.medusajs.com/api/admin#draft-orders_postdraftordersdraftorderregisterpayment) API Routes. You have full freedom in how you choose to implement creating draft orders. This section explains how it’s created in the Medusa backend using the [Create Draft Order](https://docs.medusajs.com/api/admin#draft-orders_postdraftorders) and [Register Payment](https://docs.medusajs.com/api/admin#draft-orders_postdraftordersdraftorderregisterpayment) API Routes.
A draft order is created using the `DraftOrderService`'s [create method](../../references/services/classes/DraftOrderService.mdx#create). Within that method, a cart is created along with it. The cart is used to store the order’s details, such as the draft order’s items, shipping options, and more. The cart has the type `draft_order`. A draft order is created using the `DraftOrderService`'s [create method](../../references/services/classes/services.DraftOrderService.mdx#create). Within that method, a cart is created along with it. The cart is used to store the order’s details, such as the draft order’s items, shipping options, and more. The cart has the type `draft_order`.
Since the draft order is associated with a cart, the process implemented in the Medusa backend around completing the draft order is pretty similar to that of completing a cart. Since the draft order is associated with a cart, the process implemented in the Medusa backend around completing the draft order is pretty similar to that of completing a cart.
The payment must be authorized before the cart can be completed, which can be done using the `CartService`'s [authorizePayment method](../../references/services/classes/CartService.mdx#authorizepayment). Once the payment is authorized, the order can be created using the `OrderService`'s [createFromCart method](../../references/services/classes/OrderService.mdx#createfromcart). The payment must be authorized before the cart can be completed, which can be done using the `CartService`'s [authorizePayment method](../../references/services/classes/services.CartService.mdx#authorizepayment). Once the payment is authorized, the order can be created using the `OrderService`'s [createFromCart method](../../references/services/classes/services.OrderService.mdx#createfromcart).
:::note :::note
@@ -46,7 +46,7 @@ In the Register Payment API Route, the `system` payment method is used by defaul
::: :::
The draft order can then be completed using the `DraftOrderService`'s [registerCartCompletion method](../../references/services/classes/DraftOrderService.mdx#registercartcompletion). This would update its status to `completed` and would set the `order_id` attribute of the draft order. Finally, you can capture the payment of the order that was created using the `OrderService`'s [capturePayment method](../../references/services/classes/OrderService.mdx#capturepayment). The draft order can then be completed using the `DraftOrderService`'s [registerCartCompletion method](../../references/services/classes/services.DraftOrderService.mdx#registercartcompletion). This would update its status to `completed` and would set the `order_id` attribute of the draft order. Finally, you can capture the payment of the order that was created using the `OrderService`'s [capturePayment method](../../references/services/classes/services.OrderService.mdx#capturepayment).
Once the order is created and the draft order is completed, the created order can be processed and handled the same as orders created by customers. Once the order is created and the draft order is completed, the created order can be processed and handled the same as orders created by customers.
@@ -10,7 +10,7 @@ In this document, you’ll learn about Fulfillments, how they’re used in your
Fulfillments are used to ship items, typically to a customer. Fulfillments can be used in orders, returns, swaps, and more. Fulfillments are used to ship items, typically to a customer. Fulfillments can be used in orders, returns, swaps, and more.
Fulfillments are processed within Medusa by a [fulfillment provider](../../references/fulfillment/classes/AbstractFulfillmentService.mdx). The fulfillment provider handles creating, validating, and processing the fulfillment, among other functionalities. Typically, a fulfillment provider would be integrated with a third-party service that handles the actual shipping of the items. Fulfillments are processed within Medusa by a [fulfillment provider](../../references/fulfillment/classes/fulfillment.AbstractFulfillmentService.mdx). The fulfillment provider handles creating, validating, and processing the fulfillment, among other functionalities. Typically, a fulfillment provider would be integrated with a third-party service that handles the actual shipping of the items.
When a fulfillment is created for one or more item, shipments can then be created for that fulfillment. These shipments can then be tracked using tracking numbers, providing customers and merchants accurate details about a shipment. When a fulfillment is created for one or more item, shipments can then be created for that fulfillment. These shipments can then be tracked using tracking numbers, providing customers and merchants accurate details about a shipment.
@@ -27,7 +27,7 @@ Some of the `Fulfillment` entity’s attributes include:
- `shipped_at`: a date indicating when the fulfillment was shipped. - `shipped_at`: a date indicating when the fulfillment was shipped.
- `canceled_at`: a date indicating when the fulfillment was canceled. - `canceled_at`: a date indicating when the fulfillment was canceled.
There are other important attributes discussed in later sections. Check out the [full Fulfillment entity in the entities reference](../../references/entities/classes/Fulfillment.mdx). There are other important attributes discussed in later sections. Check out the [full Fulfillment entity in the entities reference](../../references/entities/classes/entities.Fulfillment.mdx).
--- ---
@@ -37,7 +37,7 @@ Some of the attributes of the `Order` entity include:
- `no_notification`: a boolean value indicating whether the customer should receive notifications when the order is updated. - `no_notification`: a boolean value indicating whether the customer should receive notifications when the order is updated.
- `external_id`: a string indicating an ID of the order in an external system. This can be useful if you’re migrating your orders from another commerce system or you’re linking your order to a third-party service. - `external_id`: a string indicating an ID of the order in an external system. This can be useful if you’re migrating your orders from another commerce system or you’re linking your order to a third-party service.
There are other important attributes discussed in later sections. Check out the full [Order entity in the entities reference](../../references/entities/classes/Order.mdx). There are other important attributes discussed in later sections. Check out the full [Order entity in the entities reference](../../references/entities/classes/entities.Order.mdx).
--- ---
@@ -52,15 +52,15 @@ You have full freedom in how you create your orders. Within the Medusa backend,
## Payments in Orders ## Payments in Orders
In the cart completion process, or when you use the `OrderService`'s method [createFromCart](../../references/services/classes/OrderService.mdx#createfromcart), the cart’s payment is also associated with the order by setting the `order_id` of the payment to the newly created order’s ID. In the cart completion process, or when you use the `OrderService`'s method [createFromCart](../../references/services/classes/services.OrderService.mdx#createfromcart), the cart’s payment is also associated with the order by setting the `order_id` of the payment to the newly created order’s ID.
An order can have more than one payment. You can access the order’s payments by expanding the `payments` relation and accessing `order.payments`. An order can have more than one payment. You can access the order’s payments by expanding the `payments` relation and accessing `order.payments`.
By default, the payment will be authorized but not captured. Some payment processor plugins, such as the Stripe plugin, allow changing this behavior to automatically capture the payment. You can also do that within your custom payment processor. By default, the payment will be authorized but not captured. Some payment processor plugins, such as the Stripe plugin, allow changing this behavior to automatically capture the payment. You can also do that within your custom payment processor.
In the default scenario, the merchant would have to capture that payment manually, which would change the `payment_status` of the order. The payment can be captured using the `PaymentService`'s [capture method](../../references/services/classes/PaymentService.mdx#capture). In the default scenario, the merchant would have to capture that payment manually, which would change the `payment_status` of the order. The payment can be captured using the `PaymentService`'s [capture method](../../references/services/classes/services.PaymentService.mdx#capture).
After a payment has been captured, it can be refunded either fully or a specific amount of it. This is useful if items of an order has been returned or swapped, or if an order has been edited. The payment can be refunded using the `PaymentService`'s [refund method](../../references/services/classes/PaymentService.mdx#refund). After a payment has been captured, it can be refunded either fully or a specific amount of it. This is useful if items of an order has been returned or swapped, or if an order has been edited. The payment can be refunded using the `PaymentService`'s [refund method](../../references/services/classes/services.PaymentService.mdx#refund).
The Medusa backend also provides payment admin APIs that you can use to retrieve, capture, and refund the payment. The Medusa backend also provides payment admin APIs that you can use to retrieve, capture, and refund the payment.
@@ -80,13 +80,13 @@ A fulfillment can instead be canceled, changing the `fulfillment_status` to `can
If one or some items in an order are returned, the `fulfillment_status` is set to `partially_returned`. If all items were returned, the `fulfillment_status` is set to `returned`. If one or some items in an order are returned, the `fulfillment_status` is set to `partially_returned`. If all items were returned, the `fulfillment_status` is set to `returned`.
The Medusa backend provides these functionalities through the admin APIs. You can also use the `OrderService`'s methods to perform these functionalities in a custom flow, such as the [createFulfillment](../../references/services/classes/OrderService.mdx#createfulfillment) or [createShipment](../../references/services/classes/OrderService.mdx#createshipment) methods. The Medusa backend provides these functionalities through the admin APIs. You can also use the `OrderService`'s methods to perform these functionalities in a custom flow, such as the [createFulfillment](../../references/services/classes/services.OrderService.mdx#createfulfillment) or [createShipment](../../references/services/classes/services.OrderService.mdx#createshipment) methods.
--- ---
## Order Totals Calculations ## Order Totals Calculations
By default, the `Order` entity doesn’t hold any details regarding the totals. These are computed and added to the order instance using the `OrderService`'s [decorateTotals method](../../references/services/classes/OrderService.mdx#decoratetotals). There's also a dedicated method in the `OrderService`, [retrieveWithTotals](../../references/services/classes/OrderService.mdx#retrievewithtotals), attaching the totals to the order instance automatically. It is recommended to use this method by default when you need to retrieve the order. By default, the `Order` entity doesn’t hold any details regarding the totals. These are computed and added to the order instance using the `OrderService`'s [decorateTotals method](../../references/services/classes/services.OrderService.mdx#decoratetotals). There's also a dedicated method in the `OrderService`, [retrieveWithTotals](../../references/services/classes/services.OrderService.mdx#retrievewithtotals), attaching the totals to the order instance automatically. It is recommended to use this method by default when you need to retrieve the order.
The order’s totals are calculated based on the content and context of the order. This includes the order’s region, whether tax-inclusive pricing is enabled, the chosen shipping methods, and more. The order’s totals are calculated based on the content and context of the order. This includes the order’s region, whether tax-inclusive pricing is enabled, the chosen shipping methods, and more.
@@ -133,7 +133,7 @@ A merchant may also choose to force the edit on the order, by-passing the custom
Although this process is implemented in this flow within the Medusa backend, there is no requirement for you to actually follow it. For example, you can allow the customer or a third-party service to create and manage the order edit. Although this process is implemented in this flow within the Medusa backend, there is no requirement for you to actually follow it. For example, you can allow the customer or a third-party service to create and manage the order edit.
The Medusa backend provides the [order edit admin APIs](https://docs.medusajs.com/api/admin#order-edits), but you can also use the [OrderEditService](../../references/services/classes/OrderEditService.mdx) to perform the same functionalities in a custom flow. The Medusa backend provides the [order edit admin APIs](https://docs.medusajs.com/api/admin#order-edits), but you can also use the [OrderEditService](../../references/services/classes/services.OrderEditService.mdx) to perform the same functionalities in a custom flow.
Order edits are represented by the `OrderEdit` entity. This entity is linked to the order through the `order_id` attribute. You can access an order’s edits by expanding the `edits` relation and accessing `order.edits`. Notice that an order can have multiple edits during its lifecycle, but it can’t have more than one ongoing edit. Order edits are represented by the `OrderEdit` entity. This entity is linked to the order through the `order_id` attribute. You can access an order’s edits by expanding the `edits` relation and accessing `order.edits`. Notice that an order can have multiple edits during its lifecycle, but it can’t have more than one ongoing edit.
@@ -145,7 +145,7 @@ Some of the `OrderEdit`'s other attributes include:
- `confirmed_by`: a string that typically should hold the ID of who confirmed the order edit. Similar to the `created_by` attribute, there are no restrictions on what value this attribute can actually hold. - `confirmed_by`: a string that typically should hold the ID of who confirmed the order edit. Similar to the `created_by` attribute, there are no restrictions on what value this attribute can actually hold.
- `declined_by`: a string that typically should hold the ID of who declined the order edit. Similar to the `created_by` attribute, there are no restrictions on what value this attribute can actually hold. - `declined_by`: a string that typically should hold the ID of who declined the order edit. Similar to the `created_by` attribute, there are no restrictions on what value this attribute can actually hold.
There are other attributes explained in other sections. You can also check out the full [OrderEdit entity in the entities reference](../../references/entities/classes/OrderEdit.mdx). There are other attributes explained in other sections. You can also check out the full [OrderEdit entity in the entities reference](../../references/entities/classes/entities.OrderEdit.mdx).
### Item Changes ### Item Changes
@@ -28,7 +28,7 @@ Some of the `Return` entity’s attributes include:
- `no_notification`: a boolean value indicating whether the customer should receive notification updates when there are any changes in the return. - `no_notification`: a boolean value indicating whether the customer should receive notification updates when there are any changes in the return.
- `shipping_data`: this is a JSONB object that can hold any data related to the fulfillment associated with the return. - `shipping_data`: this is a JSONB object that can hold any data related to the fulfillment associated with the return.
There are other important attributes discussed in later sections. Check out the [full Return entity in the entities reference](../../references/entities/classes/Return.mdx). There are other important attributes discussed in later sections. Check out the [full Return entity in the entities reference](../../references/entities/classes/entities.Return.mdx).
--- ---
@@ -54,8 +54,8 @@ The following process occurs within the Create Return storefront API Route:
![Return Client Process Flowchart](https://res.cloudinary.com/dza7lstvk/image/upload/v1681994516/Medusa%20Docs/Diagrams/return-client-process_evbjf5.jpg) ![Return Client Process Flowchart](https://res.cloudinary.com/dza7lstvk/image/upload/v1681994516/Medusa%20Docs/Diagrams/return-client-process_evbjf5.jpg)
1. The customer creates a return, specifying the items they want to return and optionally the shipping option they want to use to return the items. This is done using the `ReturnService`'s [create method](../../references/services/classes/ReturnService.mdx#create). 1. The customer creates a return, specifying the items they want to return and optionally the shipping option they want to use to return the items. This is done using the `ReturnService`'s [create method](../../references/services/classes/services.ReturnService.mdx#create).
2. If they specify the return shipping option they want to use, a shipping method is created from the chosen shipping option and the return is automatically fulfilled in the backend using the `ReturnService`'s [fulfill method](../../references/services/classes/ReturnService.mdx#fulfill). 2. If they specify the return shipping option they want to use, a shipping method is created from the chosen shipping option and the return is automatically fulfilled in the backend using the `ReturnService`'s [fulfill method](../../references/services/classes/services.ReturnService.mdx#fulfill).
After this process, the return will be available for the merchant or the admin to view and handle it. The merchant can either mark the return as received or cancel the return. After this process, the return will be available for the merchant or the admin to view and handle it. The merchant can either mark the return as received or cancel the return.
@@ -71,15 +71,15 @@ The following process occurs within the [Receive Return admin API Route](https:/
1. The return’s status is checked to ensure it’s not canceled or received. If so, the process is terminated with an error. 1. The return’s status is checked to ensure it’s not canceled or received. If so, the process is terminated with an error.
2. The received items are validated to ensure they match the items that were previously requested to be returned. If there’s a mismatch, the return’s status is set to `requires_more`. This is useful in situations where a custom refund amount is requested, but the returned items don’t match the requested items. 2. The received items are validated to ensure they match the items that were previously requested to be returned. If there’s a mismatch, the return’s status is set to `requires_more`. This is useful in situations where a custom refund amount is requested, but the returned items don’t match the requested items.
3. If there’s no mismatch issue, the return’s status is set to `received`. 3. If there’s no mismatch issue, the return’s status is set to `received`.
4. The inventory of the returned items is adjusted using the `ProductVariantInventoryService`'s [method adjustInventory](../../references/services/classes/ProductVariantInventoryService.mdx#adjustinventory) 4. The inventory of the returned items is adjusted using the `ProductVariantInventoryService`'s [method adjustInventory](../../references/services/classes/services.ProductVariantInventoryService.mdx#adjustinventory)
2. After the return is marked as received, if the return is associated with a swap, the `SwapService`'s [registerReceived method](../../references/services/classes/SwapService.mdx#registerreceived) is used to validate the return, emit the swap event `received`, and return the swap. 2. After the return is marked as received, if the return is associated with a swap, the `SwapService`'s [registerReceived method](../../references/services/classes/services.SwapService.mdx#registerreceived) is used to validate the return, emit the swap event `received`, and return the swap.
3. On the other hand, after the return is marked as received, if the return is associated with an order, the `OrderService`'s [registerReturnReceived method](../../references/services/classes/OrderService.mdx#registerreturnreceived). In this method: 3. On the other hand, after the return is marked as received, if the return is associated with an order, the `OrderService`'s [registerReturnReceived method](../../references/services/classes/services.OrderService.mdx#registerreturnreceived). In this method:
1. If the amount that is expected to be refunded is greater than the amount that can be refunded, the `fulfillment_status` of the order is set to `requires_action`. And the process is terminated. 1. If the amount that is expected to be refunded is greater than the amount that can be refunded, the `fulfillment_status` of the order is set to `requires_action`. And the process is terminated.
2. If there are no validation issues, the payment is refunded and the fulfillment status is set to `returned` if all items of the order were returned, or `partially_returned` if only some items were returned. 2. If there are no validation issues, the payment is refunded and the fulfillment status is set to `returned` if all items of the order were returned, or `partially_returned` if only some items were returned.
### Cancel a Return ### Cancel a Return
The merchant can cancel a return if it hasn’t be marked as `received` before. This can be done either using the `ReturnService`'s [cancel method](../../references/services/classes/ReturnService.mdx#cancel) or using the [Cancel Return API Route](https://docs.medusajs.com/api/admin#returns_postreturnsreturncancel). The merchant can cancel a return if it hasn’t be marked as `received` before. This can be done either using the `ReturnService`'s [cancel method](../../references/services/classes/services.ReturnService.mdx#cancel) or using the [Cancel Return API Route](https://docs.medusajs.com/api/admin#returns_postreturnsreturncancel).
Canceling a return would change its status to canceled. Canceling a return would change its status to canceled.
+10 -10
View File
@@ -18,8 +18,8 @@ The Medusa core provides the necessary implementation and functionalities that a
Some of the attributes of the `Swap` entity include: Some of the attributes of the `Swap` entity include:
- `fulfillment_status`: a string indicating the status of the swap’s fulfillment. Its possible values indicated by the [SwapFulfillmentStatus enum](../../references/entities/enums/SwapFulfillmentStatus.mdx) can determine whether all items have been fulfilled, shipped, or canceled. - `fulfillment_status`: a string indicating the status of the swap’s fulfillment. Its possible values indicated by the [SwapFulfillmentStatus enum](../../references/entities/enums/entities.SwapFulfillmentStatus.mdx) can determine whether all items have been fulfilled, shipped, or canceled.
- `payment_status`: a string indicating the status of the swap’s payment. Its possible values indicated by the [SwapPaymentStatus enum](../../references/entities/enums/SwapFulfillmentStatus.mdx) can determine whether the payment of the swap has been captured or refunded. - `payment_status`: a string indicating the status of the swap’s payment. Its possible values indicated by the [SwapPaymentStatus enum](../../references/entities/enums/entities.SwapFulfillmentStatus.mdx) can determine whether the payment of the swap has been captured or refunded.
- `difference_due`: An integer indicating the difference amount between the order’s original total and the new total imposed by the swap. - `difference_due`: An integer indicating the difference amount between the order’s original total and the new total imposed by the swap.
- If the value of `difference_due` is negative, that means the customer should be refunded. - If the value of `difference_due` is negative, that means the customer should be refunded.
- If it’s positive, that means the customer must authorize additional payment. - If it’s positive, that means the customer must authorize additional payment.
@@ -29,7 +29,7 @@ Some of the attributes of the `Swap` entity include:
- `no_notification`: a boolean value indicating whether the customer should receive notifications when the order is updated. - `no_notification`: a boolean value indicating whether the customer should receive notifications when the order is updated.
- `allow_backorder`: a boolean value indicating whether a swap can be created and completed with items that are out of stock. - `allow_backorder`: a boolean value indicating whether a swap can be created and completed with items that are out of stock.
There are other important attributes discussed in later sections. Check out the full [Swap entity in the entities reference](../../references/entities/classes/Swap.mdx). There are other important attributes discussed in later sections. Check out the full [Swap entity in the entities reference](../../references/entities/classes/entities.Swap.mdx).
--- ---
@@ -51,12 +51,12 @@ The customer starts by creating their swap, which can be done through the Create
![Swap Creation Flowchart](https://res.cloudinary.com/dza7lstvk/image/upload/v1681983755/Medusa%20Docs/Diagrams/swap-process_kylqq0.jpg) ![Swap Creation Flowchart](https://res.cloudinary.com/dza7lstvk/image/upload/v1681983755/Medusa%20Docs/Diagrams/swap-process_kylqq0.jpg)
1. The swap’s creation is initiated with the `SwapService`'s [create method](../../references/services/classes/SwapService.mdx#create): 1. The swap’s creation is initiated with the `SwapService`'s [create method](../../references/services/classes/services.SwapService.mdx#create):
1. The order is first validated to see if a swap can be created. This includes checking the `payment_status` of the order to ensure the payment has already been captured, and the `fulfillment_status` of the order to ensure the status isn’t `not_fulfilled`. If any of these conditions aren’t met, the process is terminated with an error. 1. The order is first validated to see if a swap can be created. This includes checking the `payment_status` of the order to ensure the payment has already been captured, and the `fulfillment_status` of the order to ensure the status isn’t `not_fulfilled`. If any of these conditions aren’t met, the process is terminated with an error.
2. The items that the customer chose to return are then validated. If any item has been previously canceled, meaning that its order, swap, or claim have been previously canceled, the process is terminated with an error. 2. The items that the customer chose to return are then validated. If any item has been previously canceled, meaning that its order, swap, or claim have been previously canceled, the process is terminated with an error.
3. If all the conditions above are met, the swap is then created and associated with the order using the `order_id` attribute. 3. If all the conditions above are met, the swap is then created and associated with the order using the `order_id` attribute.
4. A return is created and linked to the swap. The return’s items are set to the items that the customer chose to return. 4. A return is created and linked to the swap. The return’s items are set to the items that the customer chose to return.
2. After the swap has been created, a cart is then created for the swap using the `SwapService`'s [createCart method](../../references/services/classes/SwapService.mdx#createcart). The cart is used to finalize the process of the swap creation process, but more on that later. The swap is associated with the cart using the `cart_id` attribute. 2. After the swap has been created, a cart is then created for the swap using the `SwapService`'s [createCart method](../../references/services/classes/services.SwapService.mdx#createcart). The cart is used to finalize the process of the swap creation process, but more on that later. The swap is associated with the cart using the `cart_id` attribute.
3. The return associated with the swap is marked as fulfilled, as this is taken care of by the customer. 3. The return associated with the swap is marked as fulfilled, as this is taken care of by the customer.
After the swap has been created, the customer should undergo a swap-completion process similar to the checkout process where they provide shipping and billing addresses, choose shipping and payment methods, authorize any additional payment required, then finally completing the cart. After the swap has been created, the customer should undergo a swap-completion process similar to the checkout process where they provide shipping and billing addresses, choose shipping and payment methods, authorize any additional payment required, then finally completing the cart.
@@ -69,7 +69,7 @@ This is all made possible since the swap is linked to a cart, so the same checko
After the swap has been created and completed by the customer, the merchant can then process the payment of the swap. This includes either refunding or capturing an additional payment, which is decided by the value of the `difference_due` attribute as explained in the [Swap Entity section](#swap-entity-overview). After the swap has been created and completed by the customer, the merchant can then process the payment of the swap. This includes either refunding or capturing an additional payment, which is decided by the value of the `difference_due` attribute as explained in the [Swap Entity section](#swap-entity-overview).
The processing of the swap’s payment can be done either using the `SwapService`'s [processDifference method](../../references/services/classes/SwapService.mdx#processdifference), or using the [Process Swap Payment API Route](https://docs.medusajs.com/api/admin#orders_postordersorderswapsswapprocesspayment). The processing of the swap’s payment can be done either using the `SwapService`'s [processDifference method](../../references/services/classes/services.SwapService.mdx#processdifference), or using the [Process Swap Payment API Route](https://docs.medusajs.com/api/admin#orders_postordersorderswapsswapprocesspayment).
If the swap requires any additional payment, the customer is expected to have authorized the payment during the [swap and cart completion flow explained earlier](#how-are-swaps-created). The merchant can then capture the payment and the `payment_status` of the swap is set to `captured`. If the swap requires any additional payment, the customer is expected to have authorized the payment during the [swap and cart completion flow explained earlier](#how-are-swaps-created). The merchant can then capture the payment and the `payment_status` of the swap is set to `captured`.
@@ -89,9 +89,9 @@ Although you have freedom in how you implement the process, the recommended proc
![Swap Fulfillment Flowchart](https://res.cloudinary.com/dza7lstvk/image/upload/v1681984933/Medusa%20Docs/Diagrams/swap-fulfillment-process_xfurko.jpg) ![Swap Fulfillment Flowchart](https://res.cloudinary.com/dza7lstvk/image/upload/v1681984933/Medusa%20Docs/Diagrams/swap-fulfillment-process_xfurko.jpg)
1. The fulfillment is created either using the `SwapService`'s [createFulfillment method](../../references/services/classes/SwapService.mdx#createfulfillment) or using the [Create a Swap Fulfillment API Route](https://docs.medusajs.com/api/admin#orders_postordersorderswapsswapfulfillments). This would set the `fulfillment_status` of the swap either to `fulfilled` if all items have been fulfilled, or `partially_fulfilled` if only some items were fulfilled. 1. The fulfillment is created either using the `SwapService`'s [createFulfillment method](../../references/services/classes/services.SwapService.mdx#createfulfillment) or using the [Create a Swap Fulfillment API Route](https://docs.medusajs.com/api/admin#orders_postordersorderswapsswapfulfillments). This would set the `fulfillment_status` of the swap either to `fulfilled` if all items have been fulfilled, or `partially_fulfilled` if only some items were fulfilled.
2. The shipment can then be created using the `SwapService`'s [createShipment method](../../references/services/classes/SwapService.mdx#createshipment) or using the [Create Swap Shipment API Route](https://docs.medusajs.com/api/admin#orders_postordersorderswapsswapshipments). This would set the `fulfillment_status` of the swap either to `shipped` if all items have been shipped, or `partially_shipped` if only some items were shipped. 2. The shipment can then be created using the `SwapService`'s [createShipment method](../../references/services/classes/services.SwapService.mdx#createshipment) or using the [Create Swap Shipment API Route](https://docs.medusajs.com/api/admin#orders_postordersorderswapsswapshipments). This would set the `fulfillment_status` of the swap either to `shipped` if all items have been shipped, or `partially_shipped` if only some items were shipped.
3. Alternatively, a fulfillment can be canceled after it has been created using the `SwapService`'s [cancelFulfillment method](../../references/services/classes/SwapService.mdx#cancelfulfillment) or using the [Cancel Swap’s Fulfillment API Route](https://docs.medusajs.com/api/admin#orders_postordersswapfulfillmentscancel). This would set the `fulfillment_status` of the swap to `canceled`. 3. Alternatively, a fulfillment can be canceled after it has been created using the `SwapService`'s [cancelFulfillment method](../../references/services/classes/services.SwapService.mdx#cancelfulfillment) or using the [Cancel Swap’s Fulfillment API Route](https://docs.medusajs.com/api/admin#orders_postordersswapfulfillmentscancel). This would set the `fulfillment_status` of the swap to `canceled`.
A swap’s fulfillments can be accessed by expanding the `fulfillments` relation and accessing `swap.fulfillments`. A fulfillment is represented by the `Fulfillment` entity. A swap’s fulfillments can be accessed by expanding the `fulfillments` relation and accessing `swap.fulfillments`. A fulfillment is represented by the `Fulfillment` entity.
@@ -105,7 +105,7 @@ A swap's return can be marked as received, which would adjust the inventory and
## Canceling a Swap ## Canceling a Swap
A swap can be canceled by the merchant if necessary. It can be done either through the `SwapService`'s [cancel method](../../references/services/classes/SwapService.mdx#cancel) or the [Cancel Swap API Route](https://docs.medusajs.com/api/admin#orders_postordersswapcancel). A swap can be canceled by the merchant if necessary. It can be done either through the `SwapService`'s [cancel method](../../references/services/classes/services.SwapService.mdx#cancel) or the [Cancel Swap API Route](https://docs.medusajs.com/api/admin#orders_postordersswapcancel).
A swap can’t be canceled if: A swap can’t be canceled if:
@@ -262,7 +262,7 @@ You can learn more about optional properties and the meaning behind every proper
}, },
{ {
name: "prices", name: "prices",
type: "[MoneyAmount](../../../references/entities/classes/MoneyAmount.mdx)[]", type: "[MoneyAmount](../../../references/entities/classes/entities.MoneyAmount.mdx)[]",
description: "The prices of the variant retrieved using the `context` object. It can include its original price and its price lists if there are any.", description: "The prices of the variant retrieved using the `context` object. It can include its original price and its price lists if there are any.",
optional: false optional: false
} }
@@ -20,7 +20,7 @@ Price lists can be used for a variety of use cases including:
### Price List Entity Overview ### Price List Entity Overview
A price list is stored in the database as a [PriceList](../../references/entities/classes/PriceList.mdx) entity. Some of its important attributes are: A price list is stored in the database as a [PriceList](../../references/entities/classes/entities.PriceList.mdx) entity. Some of its important attributes are:
- `type`: The price list's type. Can be either a `sale` or an `override`. - `type`: The price list's type. Can be either a `sale` or an `override`.
- `status`: The status of the price list. Can be `active` or `draft`. If a price list is a `draft`, its prices won't be applied even if its conditions are met. - `status`: The status of the price list. Can be `active` or `draft`. If a price list is a `draft`, its prices won't be applied even if its conditions are met.
@@ -43,7 +43,7 @@ There is no limit on how many regions you can create, and regions can share simi
## Region Entity Overview ## Region Entity Overview
A region is stored in the database as a [Region](../../references/entities/classes/Region.mdx) entity. Some of its important attributes are: A region is stored in the database as a [Region](../../references/entities/classes/entities.Region.mdx) entity. Some of its important attributes are:
- `name`: The name of the region. Customers will see this name on the storefront. - `name`: The name of the region. Customers will see this name on the storefront.
- `tax_rate`: A number that indicates the tax rate. The tax rate is a percentage. - `tax_rate`: A number that indicates the tax rate. The tax rate is a percentage.
@@ -24,7 +24,7 @@ The sales channel feature can be used in a variety of use cases including:
## SalesChannel Entity Overview ## SalesChannel Entity Overview
A sales channel is stored in the database as a [SalesChannel](../../references/entities/classes/SalesChannel.mdx) entity. Some of its important attributes are: A sales channel is stored in the database as a [SalesChannel](../../references/entities/classes/entities.SalesChannel.mdx) entity. Some of its important attributes are:
- `name`: The name of the sales channel. - `name`: The name of the sales channel.
- `is_disabled`: A boolean value indicating of the Sales Channel is disabled or not. - `is_disabled`: A boolean value indicating of the Sales Channel is disabled or not.
@@ -37,13 +37,13 @@ A sales channel is stored in the database as a [SalesChannel](../../references/e
A store has a default sales channel. When you first run your Medusa backend or seed your database, a default sales channel is created, if it doesn’t exist, and associated with the store. A store has a default sales channel. When you first run your Medusa backend or seed your database, a default sales channel is created, if it doesn’t exist, and associated with the store.
The relation is implemented in the [Store](../../references/entities/classes/Store.mdx) entity. You can access the default sales channel of a store by expanding the `default_sales_channel` relation and using `store.default_sales_channel`. You can also access the ID of the default sales channel using `store.default_sales_channel_id`. The relation is implemented in the [Store](../../references/entities/classes/entities.Store.mdx) entity. You can access the default sales channel of a store by expanding the `default_sales_channel` relation and using `store.default_sales_channel`. You can also access the ID of the default sales channel using `store.default_sales_channel_id`.
### Product ### Product
Products can be available in more than one sales channel. You can then filter products by a sales channel using the Storefront and Admin APIs. Products can be available in more than one sales channel. You can then filter products by a sales channel using the Storefront and Admin APIs.
The relation is implemented in the [Product](../../references/entities/classes/Product.mdx) entity. You can access the sales channels a product is available in by expanding the `sales_channels` relation and using `product.sales_channels`. The relation is implemented in the [Product](../../references/entities/classes/entities.Product.mdx) entity. You can access the sales channels a product is available in by expanding the `sales_channels` relation and using `product.sales_channels`.
### Cart ### Cart
@@ -51,13 +51,13 @@ When you create a cart, you can optionally specify the sales channel it belongs
A cart can belong to only one sales channel. Only products that belong to the same sales channel as the cart can be added to it. A cart can belong to only one sales channel. Only products that belong to the same sales channel as the cart can be added to it.
The relation is implemented in the [Cart](../../references/entities/classes/Cart.mdx) entity. You can access the sales channel a cart is associated with by expanding the `sales_channel` relation and using `cart.sales_channel`. You can also access the ID of the sales channel using `cart.sales_channel_id`. The relation is implemented in the [Cart](../../references/entities/classes/entities.Cart.mdx) entity. You can access the sales channel a cart is associated with by expanding the `sales_channel` relation and using `cart.sales_channel`. You can also access the ID of the sales channel using `cart.sales_channel_id`.
### Order ### Order
Orders can optionally be associated with a sales channel. You can filter orders by a sales channel using the Storefront and Admin APIs. Orders can optionally be associated with a sales channel. You can filter orders by a sales channel using the Storefront and Admin APIs.
The relation is implemented in the [Order](../../references/entities/classes/Order.mdx) entity. You can access the sales channel an order is associated with by expanding the `sales_channel` relation and using `order.sales_channel`. You can also access the ID of the sales channel using `order.sales_channel_id`. The relation is implemented in the [Order](../../references/entities/classes/entities.Order.mdx) entity. You can access the sales channel an order is associated with by expanding the `sales_channel` relation and using `order.sales_channel`. You can also access the ID of the sales channel using `order.sales_channel_id`.
--- ---
@@ -89,8 +89,8 @@ If automatic tax calculation is disabled, then the tax calculation strategy will
The `calculate` method expects three parameters: The `calculate` method expects three parameters:
- `items`: the first parameter is an array of [line item](../../../references/entities/classes/LineItem.mdx) objects. - `items`: the first parameter is an array of [line item](../../../references/entities/classes/entities.LineItem.mdx) objects.
- `taxLines`: the second parameter is an array of either [shipping method tax line](../../../references/entities/classes/ShippingMethodTaxLine.mdx) or [line item tax line](../../../references/entities/classes/LineItemTaxLine.mdx) objects. - `taxLines`: the second parameter is an array of either [shipping method tax line](../../../references/entities/classes/entities.ShippingMethodTaxLine.mdx) or [line item tax line](../../../references/entities/classes/entities.LineItemTaxLine.mdx) objects.
- `calculationContext`: an object holding the context of the tax calculation. The object has the following properties: - `calculationContext`: an object holding the context of the tax calculation. The object has the following properties:
- `shipping_address`: an optional address object used for shipping. - `shipping_address`: an optional address object used for shipping.
- `customer`: an optional customer object. - `customer`: an optional customer object.
+1 -1
View File
@@ -63,7 +63,7 @@ The invitation process typically follows these steps in the Medusa backend:
1. A user creates an invite either using the [Create Invite API Route](https://docs.medusajs.com/api/admin#invites_postinvites) or the `InviteService`'s `create` method. Part of creating an invite includes generating the token and setting the expiry date. By default, the expiry date is set to a week after the date of invitation creation. 1. A user creates an invite either using the [Create Invite API Route](https://docs.medusajs.com/api/admin#invites_postinvites) or the `InviteService`'s `create` method. Part of creating an invite includes generating the token and setting the expiry date. By default, the expiry date is set to a week after the date of invitation creation.
2. The new user receives the invite, typically through their email (although this is not implemented by default within the Medusa backend). The new user has to provide their details and password. The invite can be accepted either using the [Accept Invite API Route](https://docs.medusajs.com/api/admin#invites_postinvitesinviteaccept) or using the `InviteService`'s `accept` method. 2. The new user receives the invite, typically through their email (although this is not implemented by default within the Medusa backend). The new user has to provide their details and password. The invite can be accepted either using the [Accept Invite API Route](https://docs.medusajs.com/api/admin#invites_postinvitesinviteaccept) or using the `InviteService`'s `accept` method.
3. When the new user accepts the invite, the invitation is validated first to ensure it’s not expired. If it’s not expired, a new user is created using the `UserService`'s [create method](../../references/services/classes/UserService.mdx#create). 3. When the new user accepts the invite, the invitation is validated first to ensure it’s not expired. If it’s not expired, a new user is created using the `UserService`'s [create method](../../references/services/classes/services.UserService.mdx#create).
If an invitation is expired, an existing user can resend the invite either using the Resend Invite API Route or using the `InviteService`'s resend method. This would generate a new token and reset the expiry date. If an invitation is expired, an existing user can resend the invite either using the Resend Invite API Route or using the `InviteService`'s resend method. This would generate a new token and reset the expiry date.
@@ -2,6 +2,6 @@ import DocCardList from '@theme/DocCardList';
# Fulfillment Plugins # Fulfillment Plugins
If you can't find your fulfillment provider, try checking the [Community Plugins Library](https://medusajs.com/plugins/?filters=Shipping&categories=Shipping). You can also [create your own fulfillment provider](../../references/fulfillment/classes/AbstractFulfillmentService.mdx). If you can't find your fulfillment provider, try checking the [Community Plugins Library](https://medusajs.com/plugins/?filters=Shipping&categories=Shipping). You can also [create your own fulfillment provider](../../references/fulfillment/classes/fulfillment.AbstractFulfillmentService.mdx).
<DocCardList /> <DocCardList />
@@ -157,6 +157,6 @@ export const config: SubscriberConfig = {
The handler function receives in the `data` property of the first parameter the following properties: The handler function receives in the `data` property of the first parameter the following properties:
- `variant_id`: The ID of the variant that has been restocked. - `variant_id`: The ID of the variant that has been restocked.
- `emails`: An array of strings indicating the email addresses subscribed to the restocked variant. Here, you pass it along to the SendGrid plugin directly to send the email to everyone subscribed. If necessary, you can also retrieve the customer of that email using the `CustomerService`'s [retrieveByEmail](../../references/services/classes/CustomerService.mdx#retrievebyemail) method. - `emails`: An array of strings indicating the email addresses subscribed to the restocked variant. Here, you pass it along to the SendGrid plugin directly to send the email to everyone subscribed. If necessary, you can also retrieve the customer of that email using the `CustomerService`'s [retrieveByEmail](../../references/services/classes/services.CustomerService.mdx#retrievebyemail) method.
In the handler function, you retrieve the variant by its ID using the `ProductVariantService`, then send the email using the SendGrid plugins' `SendGridService`. In the handler function, you retrieve the variant by its ID using the `ProductVariantService`, then send the email using the SendGrid plugins' `SendGridService`.
+1 -1
View File
@@ -67,7 +67,7 @@ Medusa's modular architecture removes any restrictions you may have while making
POS systems make the checkout process smoother by integrating a barcode scanner. Merchants can scan a product by its barcode to check its details or add it to the customer's purchase. POS systems make the checkout process smoother by integrating a barcode scanner. Merchants can scan a product by its barcode to check its details or add it to the customer's purchase.
Medusa’s [Product Variant entity](../references/entities/classes/ProductVariant.mdx) includes the necessary attributes to implement this integration, mainly the `barcode` attribute. Other notable attributes include `ean`, `upc`, and `hs_code`, among others. Medusa’s [Product Variant entity](../references/entities/classes/entities.ProductVariant.mdx) includes the necessary attributes to implement this integration, mainly the `barcode` attribute. Other notable attributes include `ean`, `upc`, and `hs_code`, among others.
To search through product variants by their barcode, you can create a custom API Route and call it within your POS. To search through product variants by their barcode, you can create a custom API Route and call it within your POS.
@@ -0,0 +1,141 @@
import ParameterTypes from "@site/src/components/ParameterTypes"
# ICacheService
## Methods
### get
#### Type Parameters
<ParameterTypes parameters={[
{
"name": "T",
"type": "`object`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
#### Parameters
<ParameterTypes parameters={[
{
"name": "key",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
#### Returns
<ParameterTypes parameters={[
{
"name": "Promise",
"type": "Promise&#60;null \\| T&#62;",
"optional": false,
"defaultValue": "",
"description": "",
"expandable": false,
"children": [
{
"name": "null \\| T",
"type": "`null` \\| `T`",
"optional": true,
"defaultValue": "",
"description": "",
"expandable": false,
"children": []
}
]
}
]} />
___
### invalidate
#### Parameters
<ParameterTypes parameters={[
{
"name": "key",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
#### Returns
<ParameterTypes parameters={[
{
"name": "Promise",
"type": "Promise&#60;void&#62;",
"optional": false,
"defaultValue": "",
"description": "",
"expandable": false,
"children": []
}
]} />
___
### set
#### Parameters
<ParameterTypes parameters={[
{
"name": "key",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "data",
"type": "`unknown`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "ttl",
"type": "`number`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
#### Returns
<ParameterTypes parameters={[
{
"name": "Promise",
"type": "Promise&#60;void&#62;",
"optional": false,
"defaultValue": "",
"description": "",
"expandable": false,
"children": []
}
]} />
@@ -0,0 +1,362 @@
import ParameterTypes from "@site/src/components/ParameterTypes"
# CreateCartWorkflowInputDTO
## Properties
<ParameterTypes parameters={[
{
"name": "billing_address",
"type": "[AddressDTO](../../types/types/types.AddressDTO.mdx)",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": [
{
"name": "address_1",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "address_2",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "city",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "company",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "country_code",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "created_at",
"type": "`string` \\| `Date`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "deleted_at",
"type": "`string` \\| `Date` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "id",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "metadata",
"type": "`Record<string, unknown>` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "phone",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "postal_code",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "province",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "updated_at",
"type": "`string` \\| `Date`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
}
]
},
{
"name": "billing_address_id",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "context",
"type": "`object`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "country_code",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "customer_id",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "email",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "items",
"type": "[CreateLineItemInputDTO](types.WorkflowTypes.CartWorkflow.CreateLineItemInputDTO.mdx)[]",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": [
{
"name": "quantity",
"type": "`number`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "variant_id",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
}
]
},
{
"name": "region_id",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "sales_channel_id",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "shipping_address",
"type": "[AddressDTO](../../types/types/types.AddressDTO.mdx)",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": [
{
"name": "address_1",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "address_2",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "city",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "company",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "country_code",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "created_at",
"type": "`string` \\| `Date`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "deleted_at",
"type": "`string` \\| `Date` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "id",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "metadata",
"type": "`Record<string, unknown>` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "phone",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "postal_code",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "province",
"type": "`string` \\| `null`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "updated_at",
"type": "`string` \\| `Date`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
}
]
},
{
"name": "shipping_address_id",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
@@ -0,0 +1,26 @@
import ParameterTypes from "@site/src/components/ParameterTypes"
# CreateLineItemInputDTO
## Properties
<ParameterTypes parameters={[
{
"name": "quantity",
"type": "`number`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "variant_id",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
@@ -0,0 +1,107 @@
import ParameterTypes from "@site/src/components/ParameterTypes"
# AddressCreatePayload
## Properties
<ParameterTypes parameters={[
{
"name": "address_1",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "address_2",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "city",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "company",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "country_code",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "first_name",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "last_name",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "metadata",
"type": "`object`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "phone",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "postal_code",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "province",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
@@ -0,0 +1,107 @@
import ParameterTypes from "@site/src/components/ParameterTypes"
# AddressPayload
## Properties
<ParameterTypes parameters={[
{
"name": "address_1",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "address_2",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "city",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "company",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "country_code",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "first_name",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "last_name",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "metadata",
"type": "`Record<string, unknown>`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "phone",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "postal_code",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "province",
"type": "`string`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
@@ -0,0 +1,35 @@
import ParameterTypes from "@site/src/components/ParameterTypes"
# BaseEntity
## Properties
<ParameterTypes parameters={[
{
"name": "created_at",
"type": "`Date`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "id",
"type": "`string`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "updated_at",
"type": "`Date`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
@@ -0,0 +1,76 @@
import ParameterTypes from "@site/src/components/ParameterTypes"
# CustomFindOptions
## Type parameters
<ParameterTypes parameters={[
{
"name": "TModel",
"type": "`object`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "InKeys",
"type": "keyof `TModel`",
"description": "",
"optional": false,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
## Properties
<ParameterTypes parameters={[
{
"name": "order",
"type": "`OrderByCondition`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "select",
"type": "FindOptionsSelect&#60;TModel&#62; \\| FindOptionsSelectByString&#60;TModel&#62;",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "skip",
"type": "`number`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "take",
"type": "`number`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "where",
"type": "FindOptionsWhere&#60;TModel&#62; & &#123; [P in string \\| number \\| symbol]?: TModel[P][] &#125; \\| FindOptionsWhere&#60;TModel&#62;[] & &#123; [P in string \\| number \\| symbol]?: TModel[P][] &#125;",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
@@ -0,0 +1,44 @@
import ParameterTypes from "@site/src/components/ParameterTypes"
# DateComparisonOperator
## Properties
<ParameterTypes parameters={[
{
"name": "gt",
"type": "`Date`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "gte",
"type": "`Date`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "lt",
"type": "`Date`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
},
{
"name": "lte",
"type": "`Date`",
"description": "",
"optional": true,
"defaultValue": "",
"expandable": false,
"children": []
}
]} />
Loaded 100 of 4358 files, more files were not shown because too many files have changed in this diff. Show more