breaking: move shared HTTP utils to the framework (#9402)
Fixes: FRMW-2728, FRMW-2729 After this PR gets merged the following middleware will be exported from the `@medusajs/framework/http` import path. - applyParamsAsFilters - clearFiltersByKey - applyDefaultFilters - setContext - getQueryConfig - httpCompression - maybeApplyLinkFilter - refetchEntities - unlessPath - validateBody - validateQuery Co-authored-by: Adrien de Peretti <25098370+adrien2p@users.noreply.github.com>
This commit is contained in:
@@ -25,7 +25,10 @@ import {
|
||||
installNextjsStarter,
|
||||
startNextjsStarter,
|
||||
} from "../utils/nextjs-utils.js"
|
||||
import { getNodeVersion, MIN_SUPPORTED_NODE_VERSION } from "../utils/node-version.js"
|
||||
import {
|
||||
getNodeVersion,
|
||||
MIN_SUPPORTED_NODE_VERSION,
|
||||
} from "../utils/node-version.js"
|
||||
|
||||
const slugify = slugifyType.default
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { EOL } from "os"
|
||||
import pg from "pg"
|
||||
import postgresClient, { DEFAULT_HOST, DEFAULT_PORT } from "./postgres-client.js"
|
||||
import postgresClient, {
|
||||
DEFAULT_HOST,
|
||||
DEFAULT_PORT,
|
||||
} from "./postgres-client.js"
|
||||
import inquirer from "inquirer"
|
||||
import logMessage from "./log-message.js"
|
||||
import formatConnectionString from "./format-connection-string.js"
|
||||
@@ -16,8 +19,13 @@ export default async function createDb({ client, db }: CreateDbOptions) {
|
||||
await client.query(`CREATE DATABASE "${db}"`)
|
||||
}
|
||||
|
||||
async function doesDbExist (client: pg.Client, dbName: string): Promise<boolean> {
|
||||
const result = await client.query(`SELECT datname FROM pg_catalog.pg_database WHERE datname='${dbName}';`)
|
||||
async function doesDbExist(
|
||||
client: pg.Client,
|
||||
dbName: string
|
||||
): Promise<boolean> {
|
||||
const result = await client.query(
|
||||
`SELECT datname FROM pg_catalog.pg_database WHERE datname='${dbName}';`
|
||||
)
|
||||
|
||||
return !!result.rowCount
|
||||
}
|
||||
@@ -75,14 +83,14 @@ async function getForDbName({
|
||||
|
||||
const defaultConnectionOptions = {
|
||||
host: DEFAULT_HOST,
|
||||
port: DEFAULT_PORT
|
||||
port: DEFAULT_PORT,
|
||||
}
|
||||
|
||||
try {
|
||||
client = await postgresClient({
|
||||
user: postgresUsername,
|
||||
password: postgresPassword,
|
||||
...defaultConnectionOptions
|
||||
...defaultConnectionOptions,
|
||||
})
|
||||
} catch (e) {
|
||||
if (verbose) {
|
||||
@@ -129,7 +137,7 @@ async function getForDbName({
|
||||
user: postgresUsername,
|
||||
password: postgresPassword,
|
||||
database: userDbName,
|
||||
...defaultConnectionOptions
|
||||
...defaultConnectionOptions,
|
||||
})
|
||||
} catch (e) {
|
||||
logMessage({
|
||||
@@ -148,7 +156,9 @@ async function getForDbName({
|
||||
message: `A database already exists with the name ${dbName}, please enter a name for the database:`,
|
||||
default: dbName,
|
||||
validate: (input) => {
|
||||
return typeof input === "string" && input.length > 0 && input !== dbName
|
||||
return (
|
||||
typeof input === "string" && input.length > 0 && input !== dbName
|
||||
)
|
||||
},
|
||||
},
|
||||
])
|
||||
@@ -167,7 +177,7 @@ async function getForDbName({
|
||||
return {
|
||||
client,
|
||||
dbConnectionString,
|
||||
dbName
|
||||
dbName,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ const facts = [
|
||||
"The event bus module is responsible for triggering events and relaying them to subscribers.",
|
||||
"The cache module is responsible for caching data that requires heavy computation.",
|
||||
"A workflow is a series of steps that are defined once and executed anywhere. Workflows are created under the src/workflows directory.",
|
||||
"A workflow's steps can be retried or rolled back in case of an error."
|
||||
"A workflow's steps can be retried or rolled back in case of an error.",
|
||||
]
|
||||
|
||||
export const getFact = () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import inquirer from "inquirer"
|
||||
import { exec } from "child_process"
|
||||
import execute from "./execute.js"
|
||||
import { FactBoxOptions, displayFactBox } from "./facts.js"
|
||||
import { displayFactBox, FactBoxOptions } from "./facts.js"
|
||||
import fs from "fs"
|
||||
import path from "path"
|
||||
import { customAlphabet } from "nanoid"
|
||||
@@ -37,7 +37,7 @@ export async function installNextjsStarter({
|
||||
abortController,
|
||||
factBoxOptions,
|
||||
verbose = false,
|
||||
processManager
|
||||
processManager,
|
||||
}: InstallOptions): Promise<string> {
|
||||
factBoxOptions.interval = displayFactBox({
|
||||
...factBoxOptions,
|
||||
@@ -72,7 +72,7 @@ export async function installNextjsStarter({
|
||||
)
|
||||
const execOptions = {
|
||||
signal: abortController?.signal,
|
||||
cwd: nextjsDirectory
|
||||
cwd: nextjsDirectory,
|
||||
}
|
||||
await processManager.runProcess({
|
||||
process: async () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export function getNodeVersion(): number {
|
||||
const [major] = process.versions.node.split('.').map(Number)
|
||||
const [major] = process.versions.node.split(".").map(Number)
|
||||
|
||||
return major
|
||||
}
|
||||
|
||||
export const MIN_SUPPORTED_NODE_VERSION = 20
|
||||
export const MIN_SUPPORTED_NODE_VERSION = 20
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import pg from "pg"
|
||||
|
||||
const { Client } = pg
|
||||
|
||||
export const DEFAULT_HOST = "localhost"
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@medusajs/utils": "1.11.9",
|
||||
"@types/express": "^4.17.17",
|
||||
"chalk": "^4.0.0",
|
||||
"configstore": "5.0.1",
|
||||
"dotenv": "^16.4.5",
|
||||
|
||||
@@ -22,10 +22,7 @@ import reporter from "../reporter"
|
||||
import { getPackageManager, setPackageManager } from "../util/package-manager"
|
||||
import { PanicId } from "../reporter/panic-handler"
|
||||
import { clearProject } from "../util/clear-project"
|
||||
import {
|
||||
getNodeVersion,
|
||||
MIN_SUPPORTED_NODE_VERSION,
|
||||
} from "@medusajs/utils"
|
||||
import { getNodeVersion, MIN_SUPPORTED_NODE_VERSION } from "@medusajs/utils"
|
||||
|
||||
const removeUndefined = (obj) => {
|
||||
return Object.fromEntries(
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
const signalExit = require(`signal-exit`);
|
||||
const signalExit = require(`signal-exit`)
|
||||
|
||||
const cleanupTasks = new Set();
|
||||
const cleanupTasks = new Set()
|
||||
|
||||
exports.registerCleanupTask = (taskFn) => {
|
||||
cleanupTasks.add(taskFn);
|
||||
cleanupTasks.add(taskFn)
|
||||
return () => {
|
||||
const result = taskFn();
|
||||
cleanupTasks.delete(taskFn);
|
||||
return result;
|
||||
};
|
||||
};
|
||||
const result = taskFn()
|
||||
cleanupTasks.delete(taskFn)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
signalExit(() => {
|
||||
if (cleanupTasks.size) {
|
||||
console.log(`Process exitted in middle of publishing - cleaning up`);
|
||||
cleanupTasks.forEach((taskFn) => taskFn());
|
||||
console.log(`Process exitted in middle of publishing - cleaning up`)
|
||||
cleanupTasks.forEach((taskFn) => taskFn())
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
@@ -15,7 +15,7 @@ const getDependantPackages = ({
|
||||
packagesToPublish.add(packageName)
|
||||
const dependants = depTree[packageName]
|
||||
if (dependants) {
|
||||
dependants.forEach(dependant =>
|
||||
dependants.forEach((dependant) =>
|
||||
getDependantPackages({
|
||||
packageName: dependant,
|
||||
depTree,
|
||||
|
||||
@@ -5,7 +5,7 @@ const defaultSpawnArgs = {
|
||||
stdio: `inherit`,
|
||||
}
|
||||
|
||||
exports.setDefaultSpawnStdio = stdio => {
|
||||
exports.setDefaultSpawnStdio = (stdio) => {
|
||||
defaultSpawnArgs.stdio = stdio
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
exports.getVersionInfo = () => {
|
||||
const { version: devCliVersion } = require(`../../package.json`);
|
||||
return `Medusa Dev CLI version: ${devCliVersion}`;
|
||||
};
|
||||
const { version: devCliVersion } = require(`../../package.json`)
|
||||
return `Medusa Dev CLI version: ${devCliVersion}`
|
||||
}
|
||||
|
||||
@@ -10,13 +10,23 @@ import execa from "execa"
|
||||
|
||||
/**
|
||||
* OAS output directory
|
||||
*
|
||||
*
|
||||
* @privateRemarks
|
||||
* This should be the only directory OAS is loaded from for Medusa V2.
|
||||
* For now, we only use it if the --v2 flag it passed to the CLI tool.
|
||||
*/
|
||||
const oasOutputPath = path.resolve(
|
||||
__dirname, "..", "..", "..", "..", "..", "..", "www", "utils", "generated", "oas-output"
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"www",
|
||||
"utils",
|
||||
"generated",
|
||||
"oas-output"
|
||||
)
|
||||
const basePath = path.resolve(__dirname, `../../`)
|
||||
|
||||
@@ -128,7 +138,13 @@ describe("command oas", () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
const outDir = path.resolve(tmpDir, uid())
|
||||
await runCLI("oas", ["--type", "combined", "--out-dir", outDir, "--local"])
|
||||
await runCLI("oas", [
|
||||
"--type",
|
||||
"combined",
|
||||
"--out-dir",
|
||||
outDir,
|
||||
"--local",
|
||||
])
|
||||
const generatedFilePath = path.resolve(outDir, "combined.oas.json")
|
||||
oas = (await readJson(generatedFilePath)) as OpenAPIObject
|
||||
})
|
||||
@@ -227,7 +243,7 @@ describe("command oas", () => {
|
||||
outDir,
|
||||
"--paths",
|
||||
additionalPath,
|
||||
"--local"
|
||||
"--local",
|
||||
])
|
||||
const generatedFilePath = path.resolve(outDir, "store.oas.json")
|
||||
oas = (await readJson(generatedFilePath)) as OpenAPIObject
|
||||
@@ -363,7 +379,7 @@ components:
|
||||
outDir,
|
||||
"--base",
|
||||
filePath,
|
||||
"--local"
|
||||
"--local",
|
||||
])
|
||||
const generatedFilePath = path.resolve(outDir, "store.oas.json")
|
||||
oas = (await readJson(generatedFilePath)) as OpenAPIObject
|
||||
@@ -473,7 +489,7 @@ components:
|
||||
const routes = Object.keys(oas.paths)
|
||||
expect(routes.includes("/admin/products")).toBeTruthy()
|
||||
expect(routes.includes("/store/products")).toBeFalsy()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("public OAS with base", () => {
|
||||
@@ -579,7 +595,7 @@ components:
|
||||
])
|
||||
const generatedFilePath = path.resolve(outDir, "store.oas.json")
|
||||
oas = (await readJson(generatedFilePath)) as OpenAPIObject
|
||||
})
|
||||
})
|
||||
|
||||
it("should add new path to existing paths", async () => {
|
||||
const routes = Object.keys(oas.paths)
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { PreviewDocsOptions, previewDocs } from "@redocly/cli/lib/commands/preview-docs"
|
||||
import {
|
||||
previewDocs,
|
||||
PreviewDocsOptions,
|
||||
} from "@redocly/cli/lib/commands/preview-docs"
|
||||
import { commandWrapper } from "@redocly/cli/lib/wrapper"
|
||||
import { Command, Option, OptionValues } from "commander"
|
||||
import execa from "execa"
|
||||
@@ -12,7 +15,12 @@ import {
|
||||
} from "./utils/circular-patch-utils"
|
||||
import { getTmpDirectory, isFile } from "./utils/fs-utils"
|
||||
import { readJson } from "./utils/json-utils"
|
||||
import { jsonObjectToYamlString, readYaml, writeYaml, writeYamlFromJson } from "./utils/yaml-utils"
|
||||
import {
|
||||
jsonObjectToYamlString,
|
||||
readYaml,
|
||||
writeYaml,
|
||||
writeYamlFromJson,
|
||||
} from "./utils/yaml-utils"
|
||||
import yargs from "yargs"
|
||||
|
||||
/**
|
||||
@@ -64,7 +72,7 @@ export const commandOptions: Option[] = [
|
||||
new Option(
|
||||
"--main-file-name <mainFileName>",
|
||||
"The name of the main YAML file."
|
||||
).default("openapi.yaml")
|
||||
).default("openapi.yaml"),
|
||||
]
|
||||
|
||||
export function getCommand(): Command {
|
||||
@@ -140,7 +148,10 @@ export async function execute(cliParams: OptionValues): Promise<void> {
|
||||
if (dryRun) {
|
||||
console.log(`⚫️ Dry run - no files generated`)
|
||||
// check out possible changes in redocly config
|
||||
await execa("git", ["checkout", path.join(basePath, "redocly", "redocly-config.yaml")])
|
||||
await execa("git", [
|
||||
"checkout",
|
||||
path.join(basePath, "redocly", "redocly-config.yaml"),
|
||||
])
|
||||
return
|
||||
}
|
||||
if (shouldPreview) {
|
||||
@@ -150,7 +161,10 @@ export async function execute(cliParams: OptionValues): Promise<void> {
|
||||
if (shouldSplit) {
|
||||
await generateReference(srcFileSanitized, outDir)
|
||||
} else {
|
||||
await writeYaml(path.join(outDir, finalOASFile), await fs.readFile(srcFileSanitized, "utf8"))
|
||||
await writeYaml(
|
||||
path.join(outDir, finalOASFile),
|
||||
await fs.readFile(srcFileSanitized, "utf8")
|
||||
)
|
||||
}
|
||||
if (shouldBuildHTML) {
|
||||
const outHTMLFile = path.resolve(outDir, "index.html")
|
||||
@@ -236,17 +250,31 @@ const fixCirclularReferences = async (srcFile: string): Promise<void> => {
|
||||
${hint}
|
||||
###
|
||||
`
|
||||
const redoclyConfigPath = path.join(basePath, "redocly", "redocly-config.yaml")
|
||||
const originalContent = await readYaml(redoclyConfigPath) as CircularReferenceConfig
|
||||
const redoclyConfigPath = path.join(
|
||||
basePath,
|
||||
"redocly",
|
||||
"redocly-config.yaml"
|
||||
)
|
||||
const originalContent = (await readYaml(
|
||||
redoclyConfigPath
|
||||
)) as CircularReferenceConfig
|
||||
Object.keys(recommendation).forEach((recKey) => {
|
||||
originalContent.decorators["medusa/circular-patch"].schemas[recKey] = [
|
||||
...(originalContent.decorators["medusa/circular-patch"].schemas[recKey] || []),
|
||||
...recommendation[recKey]
|
||||
...(originalContent.decorators["medusa/circular-patch"].schemas[
|
||||
recKey
|
||||
] || []),
|
||||
...recommendation[recKey],
|
||||
]
|
||||
})
|
||||
|
||||
await writeYaml(redoclyConfigPath, jsonObjectToYamlString(originalContent))
|
||||
console.log(`🟡 Added the following unhandled circular references to redocly-config.ts:` + hintMessage)
|
||||
await writeYaml(
|
||||
redoclyConfigPath,
|
||||
jsonObjectToYamlString(originalContent)
|
||||
)
|
||||
console.log(
|
||||
`🟡 Added the following unhandled circular references to redocly-config.ts:` +
|
||||
hintMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
console.log(`🟢 All circular references are handled`)
|
||||
|
||||
@@ -15,9 +15,7 @@ import { isFile } from "./utils/fs-utils"
|
||||
* Constants
|
||||
*/
|
||||
// Medusa core package directory
|
||||
const medusaPackagePath = path.dirname(
|
||||
require.resolve("@medusajs/medusa")
|
||||
)
|
||||
const medusaPackagePath = path.dirname(require.resolve("@medusajs/medusa"))
|
||||
const basePath = path.resolve(__dirname, "../")
|
||||
|
||||
/**
|
||||
@@ -48,7 +46,7 @@ export const commandOptions: Option[] = [
|
||||
new Option(
|
||||
"--local",
|
||||
"Generate OAS from local files rather than public OAS. This is useful for generating references in the Medusa monorepo."
|
||||
)
|
||||
),
|
||||
]
|
||||
|
||||
export function getCommand() {
|
||||
@@ -105,11 +103,17 @@ export async function execute(cliParams: OptionValues) {
|
||||
console.log(`🟣 Generating OAS - ${apiType}`)
|
||||
|
||||
if (apiType === "combined") {
|
||||
const adminOAS = !local ? await getPublicOas("admin") : await getOASFromCodebase("admin")
|
||||
const storeOAS = !local ? await getPublicOas("store") : await getOASFromCodebase("store")
|
||||
const adminOAS = !local
|
||||
? await getPublicOas("admin")
|
||||
: await getOASFromCodebase("admin")
|
||||
const storeOAS = !local
|
||||
? await getPublicOas("store")
|
||||
: await getOASFromCodebase("store")
|
||||
oas = await combineOAS(adminOAS, storeOAS)
|
||||
} else {
|
||||
oas = !local ? await getPublicOas(apiType) : await getOASFromCodebase(apiType)
|
||||
oas = !local
|
||||
? await getPublicOas(apiType)
|
||||
: await getOASFromCodebase(apiType)
|
||||
}
|
||||
|
||||
if (additionalPaths.length || baseFile) {
|
||||
@@ -133,14 +137,21 @@ export async function execute(cliParams: OptionValues) {
|
||||
/**
|
||||
* Methods
|
||||
*/
|
||||
async function getOASFromCodebase(
|
||||
apiType: ApiType
|
||||
): Promise<OpenAPIObject> {
|
||||
async function getOASFromCodebase(apiType: ApiType): Promise<OpenAPIObject> {
|
||||
/**
|
||||
* OAS output directory
|
||||
*/
|
||||
const oasOutputPath = path.resolve(
|
||||
__dirname, "..", "..", "..", "..", "..", "www", "utils", "generated", "oas-output"
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"www",
|
||||
"utils",
|
||||
"generated",
|
||||
"oas-output"
|
||||
)
|
||||
const gen = await swaggerInline(
|
||||
[
|
||||
@@ -158,11 +169,9 @@ async function getOASFromCodebase(
|
||||
return (await OpenAPIParser.parse(JSON.parse(gen))) as OpenAPIObject
|
||||
}
|
||||
|
||||
async function getPublicOas(
|
||||
apiType: ApiType,
|
||||
) {
|
||||
async function getPublicOas(apiType: ApiType) {
|
||||
const url = `https://docs.medusajs.com/v2/api/api/download/${apiType}`
|
||||
return await OpenAPIParser.parse(url) as OpenAPIObject
|
||||
return (await OpenAPIParser.parse(url)) as OpenAPIObject
|
||||
}
|
||||
|
||||
async function getOASFromPaths(
|
||||
|
||||
@@ -8,4 +8,4 @@ type CircularReferenceConfig = {
|
||||
schemas: CircularReferenceSchema
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { access, lstat, mkdtemp } from "fs/promises"
|
||||
import path from "path"
|
||||
import { sep } from "path"
|
||||
import path, { sep } from "path"
|
||||
import { tmpdir } from "os"
|
||||
|
||||
export async function isFile(filePath: string): Promise<boolean> {
|
||||
|
||||
@@ -6,11 +6,17 @@ export const readYaml = async (filePath): Promise<unknown> => {
|
||||
return yaml.load(yamlString)
|
||||
}
|
||||
|
||||
export const writeYaml = async (filePath: string, yamlContent: string): Promise<void> => {
|
||||
export const writeYaml = async (
|
||||
filePath: string,
|
||||
yamlContent: string
|
||||
): Promise<void> => {
|
||||
await fs.writeFile(filePath, yamlContent, "utf8")
|
||||
}
|
||||
|
||||
export const writeYamlFromJson = async (filePath, jsonObject): Promise<void> => {
|
||||
export const writeYamlFromJson = async (
|
||||
filePath,
|
||||
jsonObject
|
||||
): Promise<void> => {
|
||||
const yamlString = yaml.dump(jsonObject)
|
||||
await fs.writeFile(filePath, yamlString, "utf8")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user