diff --git a/packages/cli/cli/package.json b/packages/cli/cli/package.json index cd4ef2dc7d93..bd1dd74416d9 100644 --- a/packages/cli/cli/package.json +++ b/packages/cli/cli/package.json @@ -40,8 +40,8 @@ "format:check": "prettier --check --ignore-unknown --ignore-path ../../../shared/.prettierignore \"**\"", "lint:eslint": "eslint --max-warnings 0 . --ignore-pattern=../../../.eslintignore", "lint:eslint:fix": "pnpm lint:eslint --fix", - "publish:cli:dev": "npm publish ./dist/dev", - "publish:cli:prod": "npm publish ./dist/prod", + "publish:cli:dev": "pnpm publish ./dist/dev --no-git-checks", + "publish:cli:prod": "pnpm publish ./dist/prod --no-git-checks", "test": "vitest --passWithNoTests --run", "test:debug": "pnpm run test --inspect --no-file-parallelism", "test:update": "vitest --passWithNoTests --run -u" diff --git a/packages/cli/ete-tests/src/tests/docs-dev/docsDev.test.ts b/packages/cli/ete-tests/src/tests/docs-dev/docsDev.test.ts index 7d35f773b98a..e3146a061710 100644 --- a/packages/cli/ete-tests/src/tests/docs-dev/docsDev.test.ts +++ b/packages/cli/ete-tests/src/tests/docs-dev/docsDev.test.ts @@ -18,9 +18,7 @@ describe.sequential("fern docs dev --legacy", () => { cwd: join(fixturesDir, RelativeFilePath.of("simple")) }); - await sleep(20_000); - - const response = await fetch("http://localhost:3000/v2/registry/docs/load-with-url", { + const response = await waitForServer("http://localhost:3000/v2/registry/docs/load-with-url", { method: "POST" }); @@ -36,7 +34,7 @@ describe.sequential("fern docs dev --legacy", () => { // kill the process const finishProcess = process.kill(); expect(finishProcess).toBeTruthy(); - }, 30_000); + }, 90_000); }); describe.sequential("fern docs dev --beta", () => { @@ -53,9 +51,7 @@ describe.sequential("fern docs dev --beta", () => { reject: true }); - await sleep(40_000); - - const response = await fetch("http://localhost:3001/v2/registry/docs/load-with-url", { + const response = await waitForServer("http://localhost:3001/v2/registry/docs/load-with-url", { method: "POST" }); @@ -70,7 +66,7 @@ describe.sequential("fern docs dev --beta", () => { const finishProcess = process.kill(); expect(finishProcess).toBeTruthy(); - }, 50_000); + }, 90_000); }); describe.sequential("fern docs dev", () => { @@ -85,9 +81,7 @@ describe.sequential("fern docs dev", () => { cwd: join(fixturesDir, RelativeFilePath.of("simple")) }); - await sleep(40_000); - - const response = await fetch("http://localhost:3002/v2/registry/docs/load-with-url", { + const response = await waitForServer("http://localhost:3002/v2/registry/docs/load-with-url", { method: "POST" }); @@ -99,9 +93,22 @@ describe.sequential("fern docs dev", () => { expect(typeof responseBody === "object").toEqual(true); // biome-ignore lint/suspicious/noExplicitAny: allow explicit any expect(Object.keys(responseBody as any)).toEqual(["baseUrl", "definition", "lightModeEnabled", "orgId"]); - }, 50_000); + }, 90_000); }); -function sleep(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); +async function waitForServer( + url: string, + init: Parameters[1], + { interval = 1_000, timeout = 60_000 }: { interval?: number; timeout?: number } = {} +): Promise>> { + const deadline = Date.now() + timeout; + while (Date.now() < deadline) { + try { + return await fetch(url, init); + } catch { + await new Promise((resolve) => setTimeout(resolve, interval)); + } + } + // Final attempt – let it throw if the server is still unreachable + return await fetch(url, init); } diff --git a/packages/cli/ete-tests/src/tests/generate/fernignore.test.ts b/packages/cli/ete-tests/src/tests/generate/fernignore.test.ts index b1e03f1ad2d9..729f05eb1be9 100644 --- a/packages/cli/ete-tests/src/tests/generate/fernignore.test.ts +++ b/packages/cli/ete-tests/src/tests/generate/fernignore.test.ts @@ -28,7 +28,7 @@ Practice schema-first API design with Fern describe("fern generate --local", () => { // eslint-disable-next-line jest/expect-expect - it("Keep files listed in .fernignore from unmodified", async () => { + it.concurrent("Keep files listed in .fernignore from unmodified", async () => { const pathOfDirectory = await init(); await runFernCli(["generate", "--local", "--keepDocker"], { cwd: pathOfDirectory @@ -61,7 +61,7 @@ describe("fern generate --local", () => { }, 360_000); // eslint-disable-next-line jest/expect-expect - it("Prevent initial generation of files listed in .fernignore", async () => { + it.concurrent("Prevent initial generation of files listed in .fernignore", async () => { const pathOfDirectory = await init(); // Create output directory with .fernignore BEFORE first generation diff --git a/packages/cli/ete-tests/src/tests/generate/generate-with-settings.test.ts b/packages/cli/ete-tests/src/tests/generate/generate-with-settings.test.ts index 1adf2a33b1e6..06e5c68c009d 100644 --- a/packages/cli/ete-tests/src/tests/generate/generate-with-settings.test.ts +++ b/packages/cli/ete-tests/src/tests/generate/generate-with-settings.test.ts @@ -5,7 +5,7 @@ import tmp from "tmp-promise"; import { runFernCli } from "../../utils/runFernCli.js"; describe("fern generate with settings", () => { - it("single api", async () => { + it.concurrent("single api", async ({ expect }) => { const fixturesDir = join(AbsoluteFilePath.of(__dirname), RelativeFilePath.of("fixtures/api-settings")); const tmpDir = await tmp.dir(); @@ -22,7 +22,7 @@ describe("fern generate with settings", () => { ).toMatchSnapshot(); }, 180_000); - it("dependencies-based api", async () => { + it.concurrent("dependencies-based api", async ({ expect }) => { const fixturesDir = join(AbsoluteFilePath.of(__dirname), RelativeFilePath.of("fixtures/api-settings-unioned")); const tmpDir = await tmp.dir(); const directory = AbsoluteFilePath.of(tmpDir.path); diff --git a/packages/cli/ete-tests/src/tests/generate/generate.test.ts b/packages/cli/ete-tests/src/tests/generate/generate.test.ts index e6c03ae74218..5e9fa542b7a9 100644 --- a/packages/cli/ete-tests/src/tests/generate/generate.test.ts +++ b/packages/cli/ete-tests/src/tests/generate/generate.test.ts @@ -1,7 +1,6 @@ import { AbsoluteFilePath, doesPathExist, join, RelativeFilePath } from "@fern-api/fs-utils"; import { exec } from "child_process"; import stripAnsi from "strip-ansi"; -import { vi } from "vitest"; import { runFernCli, runFernCliWithoutAuthToken } from "../../utils/runFernCli.js"; import { init } from "../init/init.js"; @@ -9,7 +8,7 @@ import { init } from "../init/init.js"; const fixturesDir = join(AbsoluteFilePath.of(__dirname), RelativeFilePath.of("fixtures")); describe("fern generate", () => { - it("default api (fern init)", async () => { + it.concurrent("default api (fern init)", async () => { const pathOfDirectory = await init(); await runFernCli(["generate", "--local", "--keepDocker"], { @@ -19,7 +18,7 @@ describe("fern generate", () => { expect(await doesPathExist(join(pathOfDirectory, RelativeFilePath.of("sdks/typescript")))).toBe(true); }, 180_000); - it("ir contains fdr definitionid", async () => { + it.concurrent("ir contains fdr definitionid", async () => { const { stdout, stderr } = await runFernCli(["generate", "--log-level", "debug"], { cwd: join(fixturesDir, RelativeFilePath.of("basic")), reject: false @@ -67,11 +66,13 @@ describe("fern generate", () => { ).toMatchSnapshot(); }, 180_000); - it("generate docs with no auth requires login", async () => { - vi.stubEnv("FERN_TOKEN", undefined); + it.concurrent("generate docs with no auth requires login", async () => { const { stdout, stderr } = await runFernCliWithoutAuthToken(["generate", "--docs"], { cwd: join(fixturesDir, RelativeFilePath.of("docs")), - reject: false + reject: false, + env: { + FERN_TOKEN: "" + } }); const output = stdout + stderr; expect(output).toContain( @@ -79,21 +80,19 @@ describe("fern generate", () => { ); }, 180_000); - it("generate docs with auth bypass fails", async () => { - vi.stubEnv("FERN_TOKEN", undefined); + it.concurrent("generate docs with auth bypass fails", async () => { const { stdout } = await runFernCliWithoutAuthToken(["generate", "--docs"], { cwd: join(fixturesDir, RelativeFilePath.of("docs")), reject: false, env: { - FERN_SELF_HOSTED: "true" + FERN_SELF_HOSTED: "true", + FERN_TOKEN: "" } }); expect(stdout).toContain("No token found. Please set the FERN_TOKEN environment variable."); }, 180_000); - it("generate docs with auth bypass succeeds", async () => { - vi.stubEnv("FERN_TOKEN", "dummy"); - + it.concurrent("generate docs with auth bypass succeeds", async () => { const { stdout } = await runFernCliWithoutAuthToken(["generate", "--docs"], { cwd: join(fixturesDir, RelativeFilePath.of("docs")), reject: false, @@ -105,7 +104,7 @@ describe("fern generate", () => { expect(stdout).toContain("ferndevtest.docs.dev.buildwithfern.com Started."); }, 180_000); - it("generate docs with no docs.yml file fails", async () => { + it.concurrent("generate docs with no docs.yml file fails", async () => { const { stdout } = await runFernCli(["generate", "--docs"], { cwd: join(fixturesDir, RelativeFilePath.of("basic")), reject: false diff --git a/packages/cli/ete-tests/src/tests/init/init.test.ts b/packages/cli/ete-tests/src/tests/init/init.test.ts index d6b9154cee65..7f11fe79e92f 100644 --- a/packages/cli/ete-tests/src/tests/init/init.test.ts +++ b/packages/cli/ete-tests/src/tests/init/init.test.ts @@ -15,14 +15,14 @@ import { init } from "./init.js"; const FIXTURES_DIR = join(AbsoluteFilePath.of(__dirname), RelativeFilePath.of("fixtures")); describe("fern init", () => { - it("no existing fern directory", async () => { + it.concurrent("no existing fern directory", async ({ expect }) => { const pathOfDirectory = await init(); expect( await getDirectoryContentsForSnapshot(join(pathOfDirectory, RelativeFilePath.of(FERN_DIRECTORY))) ).toMatchSnapshot(); }, 60_000); - it("no existing fern directory with fern definition", async () => { + it.concurrent("no existing fern directory with fern definition", async ({ expect }) => { const pathOfDirectory = await init({ additionalArgs: [{ name: "--fern-definition" }] }); @@ -34,7 +34,7 @@ describe("fern init", () => { ).toMatchSnapshot(); }, 60_000); - it("existing fern directory", async () => { + it.concurrent("existing fern directory", async ({ expect }) => { // add existing directory const pathOfDirectory = await init({ additionalArgs: [{ name: "--fern-definition" }] @@ -57,7 +57,7 @@ describe("fern init", () => { ).toBe(true); }, 60_000); - it("init openapi", async () => { + it.concurrent("init openapi", async ({ expect }) => { // Create a temporary directory for the OpenAPI test const tmpDir = await tmp.dir(); const sourceOpenAPI = join( @@ -78,7 +78,7 @@ describe("fern init", () => { expect(await getDirectoryContentsForSnapshot(pathOfDirectory)).toMatchSnapshot(); }, 60_000); - it("existing openapi fern directory", async () => { + it.concurrent("existing openapi fern directory", async ({ expect }) => { const pathOfDirectory = await init(); await init({ @@ -128,7 +128,7 @@ describe("fern init", () => { ).toBe(true); }, 60_000); - it("existing openapi then fern-definition", async () => { + it.concurrent("existing openapi then fern-definition", async ({ expect }) => { const pathOfDirectory = await init(); await init({ @@ -159,7 +159,7 @@ describe("fern init", () => { ).toBe(true); }, 60_000); - it("conflicting --openapi and --fern-definition flags", async () => { + it.concurrent("conflicting --openapi and --fern-definition flags", async ({ expect }) => { const tmpDir = await tmp.dir(); const sourceOpenAPI = join( FIXTURES_DIR, @@ -179,7 +179,7 @@ describe("fern init", () => { expect(result.exitCode).not.toBe(0); }, 60_000); - it("init docs", async () => { + it.concurrent("init docs", async ({ expect }) => { const pathOfDirectory = await init({ additionalArgs: [{ name: "--fern-definition" }] }); @@ -191,7 +191,7 @@ describe("fern init", () => { expect(await getDirectoryContentsForSnapshot(pathOfDirectory)).toMatchSnapshot(); }, 60_000); - it("init mintlify", async () => { + it.concurrent("init mintlify", async ({ expect }) => { const mintJsonPath = join(FIXTURES_DIR, RelativeFilePath.of("mintlify"), RelativeFilePath.of("mint.json")); const pathOfDirectory = await init({ diff --git a/packages/cli/ete-tests/src/tests/ir/generateIrAsString.ts b/packages/cli/ete-tests/src/tests/ir/generateIrAsString.ts index 0b418ca3ac85..c421f9fe8380 100644 --- a/packages/cli/ete-tests/src/tests/ir/generateIrAsString.ts +++ b/packages/cli/ete-tests/src/tests/ir/generateIrAsString.ts @@ -1,6 +1,7 @@ import { generatorsYml } from "@fern-api/configuration"; -import { AbsoluteFilePath, join, RelativeFilePath } from "@fern-api/fs-utils"; -import { readFile, rm } from "fs/promises"; +import { AbsoluteFilePath } from "@fern-api/fs-utils"; +import { readFile } from "fs/promises"; +import tmp from "tmp-promise"; import { runFernCli } from "../../utils/runFernCli.js"; @@ -17,8 +18,8 @@ export async function generateIrAsString({ apiName?: string; version?: string; }): Promise { - const irOutputPath = join(fixturePath, RelativeFilePath.of("ir.json")); - await rm(irOutputPath, { force: true, recursive: true }); + const tmpFile = await tmp.file({ postfix: ".json" }); + const irOutputPath = AbsoluteFilePath.of(tmpFile.path); const command = ["ir", irOutputPath]; if (language != null) { @@ -42,5 +43,6 @@ export async function generateIrAsString({ }); const irContents = await readFile(irOutputPath); + await tmpFile.cleanup(); return irContents.toString(); } diff --git a/packages/cli/ete-tests/src/tests/ir/ir.test.ts b/packages/cli/ete-tests/src/tests/ir/ir.test.ts index 1ac22432ef0a..ee67ddb3a365 100644 --- a/packages/cli/ete-tests/src/tests/ir/ir.test.ts +++ b/packages/cli/ete-tests/src/tests/ir/ir.test.ts @@ -2,6 +2,7 @@ import { generatorsYml } from "@fern-api/configuration"; import { AbsoluteFilePath, join, RelativeFilePath } from "@fern-api/fs-utils"; import { readFile } from "fs/promises"; import path from "path"; +import tmp from "tmp-promise"; import { runFernCli } from "../../utils/runFernCli.js"; import { generateIrAsString } from "./generateIrAsString.js"; @@ -69,9 +70,9 @@ interface Fixture { describe("ir", () => { for (const fixture of FIXTURES) { const { only = false } = fixture; - (only ? it.only : it)( + (only ? it.only : it.concurrent)( `${JSON.stringify(fixture)}`, - async () => { + async ({ expect }) => { const fixturePath = join(FIXTURES_DIR, RelativeFilePath.of(fixture.name)); const irContents = await generateIrAsString({ fixturePath, @@ -86,19 +87,23 @@ describe("ir", () => { ); } - it("works with latest version", async () => { - const { stdout } = await runFernCli(["ir", "ir.json", "--version", "v27"], { + it.concurrent("works with latest version", async ({ expect }) => { + const tmpFile = await tmp.file({ postfix: ".json" }); + const { stdout } = await runFernCli(["ir", tmpFile.path, "--version", "v27"], { cwd: join(FIXTURES_DIR, RelativeFilePath.of("migration")), reject: false }); + await tmpFile.cleanup(); expect(stdout).toContain("Wrote IR to"); }, 10_000); - it("fails with invalid version", async () => { - const { stdout } = await runFernCli(["ir", "ir.json", "--version", "v100"], { + it.concurrent("fails with invalid version", async ({ expect }) => { + const tmpFile = await tmp.file({ postfix: ".json" }); + const { stdout } = await runFernCli(["ir", tmpFile.path, "--version", "v100"], { cwd: join(FIXTURES_DIR, RelativeFilePath.of("migration")), reject: false }); + await tmpFile.cleanup(); expect(stdout).toContain("IR v100 does not exist"); }, 10_000); }); diff --git a/packages/cli/ete-tests/src/tests/upgrade-generator/upgrade-generator.test.ts b/packages/cli/ete-tests/src/tests/upgrade-generator/upgrade-generator.test.ts index 4c926de0da66..cd0f9579ab55 100644 --- a/packages/cli/ete-tests/src/tests/upgrade-generator/upgrade-generator.test.ts +++ b/packages/cli/ete-tests/src/tests/upgrade-generator/upgrade-generator.test.ts @@ -10,7 +10,7 @@ import { runFernCli } from "../../utils/runFernCli.js"; const FIXTURES_DIR = path.join(__dirname, "fixtures"); describe("fern generator upgrade", () => { - it("fern generator upgrade", async () => { + it.concurrent("fern generator upgrade", async () => { // Create tmpdir and copy contents const tmpDir = await tmp.dir(); const directory = AbsoluteFilePath.of(tmpDir.path); @@ -42,7 +42,7 @@ describe("fern generator upgrade", () => { expect(JSON.parse((await readFile(outputFile)).toString()).version).not.toEqual("3.0.0"); }, 60_000); - it("fern generator upgrade with filters", async () => { + it.concurrent("fern generator upgrade with filters", async () => { // Create tmpdir and copy contents const tmpDir = await tmp.dir(); const directory = AbsoluteFilePath.of(tmpDir.path); @@ -111,7 +111,7 @@ describe("fern generator upgrade", () => { ).toMatchSnapshot(); }, 60_000); - it("fern generator upgrade majors", async () => { + it.concurrent("fern generator upgrade majors", async () => { // Create tmpdir and copy contents const tmpDir = await tmp.dir(); const directory = AbsoluteFilePath.of(tmpDir.path); @@ -211,7 +211,7 @@ describe("fern generator upgrade", () => { ).toMatchSnapshot(); }, 60_000); - it("fern generator upgrade --skip-autorelease-disabled skips autorelease false generators", async () => { + it.concurrent("fern generator upgrade --skip-autorelease-disabled skips autorelease false generators", async () => { const tmpDir = await tmp.dir(); const directory = AbsoluteFilePath.of(tmpDir.path); @@ -277,7 +277,7 @@ describe("fern generator upgrade", () => { expect(JSON.parse((await readFile(outputFileJava)).toString()).version).not.toEqual("0.0.1"); }, 60_000); - it("fern generator upgrade without --skip-autorelease-disabled upgrades all generators", async () => { + it.concurrent("fern generator upgrade without --skip-autorelease-disabled upgrades all generators", async () => { const tmpDir = await tmp.dir(); const directory = AbsoluteFilePath.of(tmpDir.path); @@ -308,7 +308,7 @@ describe("fern generator upgrade", () => { expect(JSON.parse((await readFile(outputFile)).toString()).version).not.toEqual("3.0.0"); }, 60_000); - it("fern generator upgrade shows major version message", async () => { + it.concurrent("fern generator upgrade shows major version message", async () => { const tmpDir = await tmp.dir(); const directory = AbsoluteFilePath.of(tmpDir.path); diff --git a/packages/cli/ete-tests/src/tests/write-definition/__snapshots__/writeDefinition.test.ts.snap b/packages/cli/ete-tests/src/tests/write-definition/__snapshots__/writeDefinition.test.ts.snap index 7b245d406b34..fb178e07a880 100644 --- a/packages/cli/ete-tests/src/tests/write-definition/__snapshots__/writeDefinition.test.ts.snap +++ b/packages/cli/ete-tests/src/tests/write-definition/__snapshots__/writeDefinition.test.ts.snap @@ -1,112 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`validate > petstore 1`] = ` -[ - { - "contents": "types: - Error: - properties: - code: integer - message: string - source: - openapi: openapi/openapi.yml - Pet: - properties: - id: long - name: string - tag: optional - source: - openapi: openapi/openapi.yml - Pets: list -", - "name": "__package__.yml", - "type": "file", - }, - { - "contents": "default-environment: Default -display-name: Swagger Petstore -environments: - Default: http://petstore.swagger.io/v1 -error-discrimination: - strategy: status-code -name: api -", - "name": "api.yml", - "type": "file", - }, - { - "contents": "imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - createPets: - display-name: Create a pet - examples: - - {} - method: POST - path: /pets - source: - openapi: openapi/openapi.yml - listPets: - display-name: List all pets - examples: - - response: - body: - - id: 1000000 - name: name - tag: tag - method: GET - path: /pets - request: - name: ListPetsRequest - query-parameters: - limit: - docs: How many items to return at one time (max 100) - type: optional - validation: - max: 100 - response: - docs: A paged array of pets - status-code: 200 - type: root.Pets - source: - openapi: openapi/openapi.yml - showPetById: - display-name: Info for a specific pet - examples: - - path-parameters: - petId: petId - response: - body: - id: 1000000 - name: name - tag: tag - method: GET - path: /pets/{petId} - request: - name: ShowPetByIdRequest - path-parameters: - petId: - docs: The id of the pet to retrieve - type: string - response: - docs: Expected response to a valid request - status-code: 200 - type: root.Pet - source: - openapi: openapi/openapi.yml - source: - openapi: openapi/openapi.yml -", - "name": "pets.yml", - "type": "file", - }, -] -`; - -exports[`validate header overrides > header-overrides 1`] = ` +exports[`write-definition > header-overrides 1`] = ` [ { "contents": "types: @@ -219,7 +113,7 @@ service: ] `; -exports[`validate multi no endpoint > multiple-no-endpoint 1`] = ` +exports[`write-definition > multiple-no-endpoint 1`] = ` [ { "contents": "service: @@ -260,7 +154,7 @@ name: api ] `; -exports[`validate multi no endpoint asyncapi > multiple-no-endpoint-async 1`] = ` +exports[`write-definition > multiple-no-endpoint-async 1`] = ` [ { "contents": "service: @@ -344,7 +238,7 @@ name: api ] `; -exports[`validate multi with endpoint > multiple-with-endpoint 1`] = ` +exports[`write-definition > multiple-with-endpoint 1`] = ` [ { "contents": "service: @@ -393,7 +287,7 @@ name: api ] `; -exports[`validate multi with endpoint async > multiple-with-endpoint-async 1`] = ` +exports[`write-definition > multiple-with-endpoint-async 1`] = ` [ { "contents": "service: @@ -480,7 +374,7 @@ name: api ] `; -exports[`validate namespaced API > namespaced 1`] = ` +exports[`write-definition > namespaced 1`] = ` [ { "contents": "types: @@ -1879,7 +1773,167 @@ service: ] `; -exports[`validate namespaced API from Cohere > namespaced-fleshedout 1`] = ` +exports[`write-definition > namespaced-asyncapi 1`] = ` +[ + { + "contents": "{} +", + "name": "__package__.yml", + "type": "file", + }, + { + "contents": [ + { + "contents": "types: + Error: + properties: + code: integer + message: string + source: + openapi: alpha_one.yml + Pet: + properties: + id: long + name: string + tag: optional + source: + openapi: alpha_one.yml + Pets: list +", + "name": "__package__.yml", + "type": "file", + }, + { + "contents": "imports: + alphaRoot: __package__.yml +service: + auth: false + base-path: '' + endpoints: + createPets: + display-name: Create a pet + examples: + - {} + method: POST + path: /pets + source: + openapi: alpha_one.yml + listPets: + display-name: List all pets + examples: + - response: + body: [] + method: GET + path: /list-all + request: + name: ListPetsRequest + query-parameters: + limit: + docs: How many items to return at one time (max 100) + type: optional + validation: + max: 100 + response: + docs: A paged array of pets + status-code: 200 + type: alphaRoot.Pets + source: + openapi: alpha_two.yml + showPetById: + display-name: Info for a specific pet + examples: + - path-parameters: + petId: petId + response: + body: + id: 1000000 + name: name + tag: tag + method: GET + path: /pets/{petId} + request: + name: ShowPetByIdRequest + path-parameters: + petId: + docs: The id of the pet to retrieve + type: string + response: + docs: Expected response to a valid request + status-code: 200 + type: alphaRoot.Pet + source: + openapi: alpha_one.yml + source: + openapi: alpha_two.yml +", + "name": "pets.yml", + "type": "file", + }, + ], + "name": "alpha", + "type": "directory", + }, + { + "contents": "default-environment: Default +default-url: Base +display-name: Alpha One +environments: + Default: + urls: + Base: http://petstore.swagger.io/v1 + websocket: wss://api.async.com + websocket2: wss://api2.async.com +error-discrimination: + strategy: status-code +name: api +", + "name": "api.yml", + "type": "file", + }, + { + "contents": [ + { + "contents": "channel: + auth: false + examples: + - messages: + - body: string + type: testChannel_sendMessage + messages: + testChannel_sendMessage: + body: string + origin: client + path: /test + url: websocket +", + "name": "betaOne.yml", + "type": "file", + }, + { + "contents": "channel: + auth: false + examples: + - messages: + - body: string + type: testChannel2_sendMessage + messages: + testChannel2_sendMessage: + body: string + origin: client + path: /test2 + url: websocket2 +", + "name": "betaTwo.yml", + "type": "file", + }, + ], + "name": "beta", + "type": "directory", + }, +] +`; + +exports[`write-definition > namespaced-fleshedout 1`] = ` [ { "contents": "{} @@ -2700,39 +2754,43 @@ service: ] `; -exports[`validate namespaced API with multiple namespaces > namespaced-asyncapi 1`] = ` +exports[`write-definition > petstore 1`] = ` [ { - "contents": "{} -", - "name": "__package__.yml", - "type": "file", - }, - { - "contents": [ - { - "contents": "types: + "contents": "types: Error: properties: code: integer message: string source: - openapi: alpha_one.yml + openapi: openapi/openapi.yml Pet: properties: id: long name: string tag: optional source: - openapi: alpha_one.yml - Pets: list + openapi: openapi/openapi.yml + Pets: list ", - "name": "__package__.yml", - "type": "file", - }, - { - "contents": "imports: - alphaRoot: __package__.yml + "name": "__package__.yml", + "type": "file", + }, + { + "contents": "default-environment: Default +display-name: Swagger Petstore +environments: + Default: http://petstore.swagger.io/v1 +error-discrimination: + strategy: status-code +name: api +", + "name": "api.yml", + "type": "file", + }, + { + "contents": "imports: + root: __package__.yml service: auth: false base-path: '' @@ -2744,14 +2802,17 @@ service: method: POST path: /pets source: - openapi: alpha_one.yml + openapi: openapi/openapi.yml listPets: display-name: List all pets examples: - response: - body: [] + body: + - id: 1000000 + name: name + tag: tag method: GET - path: /list-all + path: /pets request: name: ListPetsRequest query-parameters: @@ -2763,9 +2824,9 @@ service: response: docs: A paged array of pets status-code: 200 - type: alphaRoot.Pets + type: root.Pets source: - openapi: alpha_two.yml + openapi: openapi/openapi.yml showPetById: display-name: Info for a specific pet examples: @@ -2787,80 +2848,19 @@ service: response: docs: Expected response to a valid request status-code: 200 - type: alphaRoot.Pet + type: root.Pet source: - openapi: alpha_one.yml + openapi: openapi/openapi.yml source: - openapi: alpha_two.yml -", - "name": "pets.yml", - "type": "file", - }, - ], - "name": "alpha", - "type": "directory", - }, - { - "contents": "default-environment: Default -default-url: Base -display-name: Alpha One -environments: - Default: - urls: - Base: http://petstore.swagger.io/v1 - websocket: wss://api.async.com - websocket2: wss://api2.async.com -error-discrimination: - strategy: status-code -name: api + openapi: openapi/openapi.yml ", - "name": "api.yml", + "name": "pets.yml", "type": "file", }, - { - "contents": [ - { - "contents": "channel: - auth: false - examples: - - messages: - - body: string - type: testChannel_sendMessage - messages: - testChannel_sendMessage: - body: string - origin: client - path: /test - url: websocket -", - "name": "betaOne.yml", - "type": "file", - }, - { - "contents": "channel: - auth: false - examples: - - messages: - - body: string - type: testChannel2_sendMessage - messages: - testChannel2_sendMessage: - body: string - origin: client - path: /test2 - url: websocket2 -", - "name": "betaTwo.yml", - "type": "file", - }, - ], - "name": "beta", - "type": "directory", - }, ] `; -exports[`validate single no endpoint > single-no-endpoint 1`] = ` +exports[`write-definition > single-no-endpoint 1`] = ` [ { "contents": "service: @@ -2900,7 +2900,7 @@ name: api ] `; -exports[`validate single no endpoint async > single-no-endpoint-async 1`] = ` +exports[`write-definition > single-no-endpoint-async 1`] = ` [ { "contents": "service: @@ -2979,7 +2979,7 @@ name: api ] `; -exports[`validate single with endpoint > single-with-endpoint 1`] = ` +exports[`write-definition > single-with-endpoint 1`] = ` [ { "contents": "service: @@ -3024,7 +3024,7 @@ name: api ] `; -exports[`validate single with endpoint async > single-with-endpoint-async 1`] = ` +exports[`write-definition > single-with-endpoint-async 1`] = ` [ { "contents": "service: diff --git a/packages/cli/ete-tests/src/tests/write-definition/writeDefinition.test.ts b/packages/cli/ete-tests/src/tests/write-definition/writeDefinition.test.ts index 69b6ef023d0f..ae7470e9165e 100644 --- a/packages/cli/ete-tests/src/tests/write-definition/writeDefinition.test.ts +++ b/packages/cli/ete-tests/src/tests/write-definition/writeDefinition.test.ts @@ -6,61 +6,25 @@ import { runFernCli } from "../../utils/runFernCli.js"; const FIXTURES_DIR = path.join(__dirname, "fixtures"); -describe("validate", () => { +describe("write-definition", () => { itFixture("petstore"); -}); - -describe("validate namespaced API", () => { itFixture("namespaced"); -}); - -describe("validate namespaced API with multiple namespaces", () => { itFixture("namespaced-asyncapi"); -}); - -describe("validate namespaced API from Cohere", () => { itFixture("namespaced-fleshedout"); -}); - -describe("validate header overrides", () => { itFixture("header-overrides"); -}); - -describe("validate multi no endpoint", () => { itFixture("multiple-no-endpoint"); -}); - -describe("validate multi no endpoint asyncapi", () => { itFixture("multiple-no-endpoint-async"); -}); - -describe("validate multi with endpoint", () => { itFixture("multiple-with-endpoint"); -}); - -describe("validate multi with endpoint async", () => { itFixture("multiple-with-endpoint-async"); -}); - -describe("validate single no endpoint", () => { itFixture("single-no-endpoint"); -}); - -describe("validate single no endpoint async", () => { itFixture("single-no-endpoint-async"); -}); - -describe("validate single with endpoint", () => { itFixture("single-with-endpoint"); -}); - -describe("validate single with endpoint async", () => { itFixture("single-with-endpoint-async"); }); function itFixture(fixtureName: string) { - it(// eslint-disable-next-line jest/valid-title - fixtureName, async () => { + it.concurrent(// eslint-disable-next-line jest/valid-title + fixtureName, async ({ expect }) => { const fixturePath = path.join(FIXTURES_DIR, fixtureName); const definitionOutputPath = path.join(fixturePath, "fern", ".definition"); if (await doesPathExist(AbsoluteFilePath.of(definitionOutputPath))) { diff --git a/packages/cli/generation/ir-generator-tests/src/dynamic-snippets/__test__/DynamicSnippetsConverter.test.ts b/packages/cli/generation/ir-generator-tests/src/dynamic-snippets/__test__/DynamicSnippetsConverter.test.ts index 625738698eb9..c4dcff5a0dd3 100644 --- a/packages/cli/generation/ir-generator-tests/src/dynamic-snippets/__test__/DynamicSnippetsConverter.test.ts +++ b/packages/cli/generation/ir-generator-tests/src/dynamic-snippets/__test__/DynamicSnippetsConverter.test.ts @@ -1,29 +1,43 @@ import { AbsoluteFilePath, join, RelativeFilePath } from "@fern-api/fs-utils"; import { createMockTaskContext } from "@fern-api/task-context"; +import { AbstractAPIWorkspace } from "@fern-api/workspace-loader"; +import { readdirSync } from "fs"; import path from "path"; import { loadApisOrThrow } from "../../loadApisOrThrow.js"; import { generateAndSnapshotDynamicIR } from "./generateAndSnapshotDynamicIR.js"; -// eslint-disable-next-line @typescript-eslint/no-misused-promises -describe("test definitions", async () => { +describe("test definitions", () => { const TEST_DEFINITIONS_DIR = path.join(__dirname, "../../../../../../../test-definitions"); - const apiWorkspaces = await loadApisOrThrow({ - fernDirectory: join(AbsoluteFilePath.of(TEST_DEFINITIONS_DIR), RelativeFilePath.of("fern")), - context: createMockTaskContext(), - cliVersion: "0.0.0", - cliName: "fern", - commandLineApiWorkspace: undefined, - defaultToAllApiWorkspaces: true - }); + const apiNames = readdirSync(path.join(TEST_DEFINITIONS_DIR, "fern/apis"), { withFileTypes: true }) + .filter((d) => d.isDirectory()) + .map((d) => d.name); + + let workspaceMap: Map>; + + beforeAll(async () => { + const apiWorkspaces = await loadApisOrThrow({ + fernDirectory: join(AbsoluteFilePath.of(TEST_DEFINITIONS_DIR), RelativeFilePath.of("fern")), + context: createMockTaskContext(), + cliVersion: "0.0.0", + cliName: "fern", + commandLineApiWorkspace: undefined, + defaultToAllApiWorkspaces: true + }); + workspaceMap = new Map(apiWorkspaces.map((w) => [w.workspaceName ?? "", w])); + }, 200_000); - apiWorkspaces.map(async (workspace) => { - it(`${workspace.workspaceName}`, async () => { + apiNames.forEach((name) => { + it.concurrent(name, async () => { + const workspace = workspaceMap.get(name); + if (!workspace) { + throw new Error(`Workspace ${name} not found`); + } await generateAndSnapshotDynamicIR({ absolutePathToIr: AbsoluteFilePath.of(path.join(__dirname, "test-definitions")), workspace, audiences: { type: "all" }, - workspaceName: workspace.workspaceName ?? "" + workspaceName: name }); }, 30_000); }); diff --git a/packages/cli/generation/ir-generator-tests/src/ir/__test__/generateIntermediateRepresentation.test.ts b/packages/cli/generation/ir-generator-tests/src/ir/__test__/generateIntermediateRepresentation.test.ts index a04278e54c27..4f205f547229 100644 --- a/packages/cli/generation/ir-generator-tests/src/ir/__test__/generateIntermediateRepresentation.test.ts +++ b/packages/cli/generation/ir-generator-tests/src/ir/__test__/generateIntermediateRepresentation.test.ts @@ -4,6 +4,8 @@ import { AbsoluteFilePath, join, RelativeFilePath } from "@fern-api/fs-utils"; import { createMockTaskContext } from "@fern-api/task-context"; +import { AbstractAPIWorkspace } from "@fern-api/workspace-loader"; +import { readdirSync } from "fs"; import path from "path"; import { loadApisOrThrow } from "../../loadApisOrThrow.js"; @@ -61,54 +63,77 @@ it.skip("fhir", async () => { }); }, 200_000); -describe("test definitions", async () => { +describe("test definitions", () => { const TEST_DEFINITIONS_DIR = path.join(__dirname, "../../../../../../../test-definitions"); - const apiWorkspaces = await loadApisOrThrow({ - fernDirectory: join(AbsoluteFilePath.of(TEST_DEFINITIONS_DIR), RelativeFilePath.of("fern")), - context: createMockTaskContext(), - cliVersion: "0.0.0", - cliName: "fern", - commandLineApiWorkspace: undefined, - defaultToAllApiWorkspaces: true - }); - - apiWorkspaces.forEach((workspace) => { - it(`${workspace.workspaceName}`, async () => { + const apiNames = readdirSync(path.join(TEST_DEFINITIONS_DIR, "fern/apis"), { withFileTypes: true }) + .filter((d) => d.isDirectory()) + .map((d) => d.name); + + let workspaceMap: Map>; + + beforeAll(async () => { + const apiWorkspaces = await loadApisOrThrow({ + fernDirectory: join(AbsoluteFilePath.of(TEST_DEFINITIONS_DIR), RelativeFilePath.of("fern")), + context: createMockTaskContext(), + cliVersion: "0.0.0", + cliName: "fern", + commandLineApiWorkspace: undefined, + defaultToAllApiWorkspaces: true + }); + workspaceMap = new Map(apiWorkspaces.map((w) => [w.workspaceName ?? "", w])); + }, 200_000); + + apiNames.forEach((name) => { + it.concurrent(name, async () => { + const workspace = workspaceMap.get(name); + if (!workspace) { + throw new Error(`Workspace ${name} not found`); + } await generateAndSnapshotIR({ absolutePathToIr: AbsoluteFilePath.of(path.join(__dirname, "test-definitions")), workspace, audiences: { type: "all" }, - workspaceName: workspace.workspaceName ?? "" + workspaceName: name }); }, 30_000); }); -}, 200_000); +}); -describe("test definitions openapi", async () => { +describe("test definitions openapi", () => { const TEST_DEFINITIONS_DIR = path.join(__dirname, "../../../../../../../test-definitions-openapi"); - const apiWorkspaces = await loadApisOrThrow({ - fernDirectory: join(AbsoluteFilePath.of(TEST_DEFINITIONS_DIR), RelativeFilePath.of("fern")), - context: createMockTaskContext(), - cliVersion: "0.0.0", - cliName: "fern", - commandLineApiWorkspace: undefined, - defaultToAllApiWorkspaces: true - }); - - apiWorkspaces.forEach((workspace) => { - it(`${workspace.workspaceName}`, async () => { + const apiNames = readdirSync(path.join(TEST_DEFINITIONS_DIR, "fern/apis"), { withFileTypes: true }) + .filter((d) => d.isDirectory()) + .map((d) => d.name); + + let workspaceMap: Map>; + + beforeAll(async () => { + const apiWorkspaces = await loadApisOrThrow({ + fernDirectory: join(AbsoluteFilePath.of(TEST_DEFINITIONS_DIR), RelativeFilePath.of("fern")), + context: createMockTaskContext(), + cliVersion: "0.0.0", + cliName: "fern", + commandLineApiWorkspace: undefined, + defaultToAllApiWorkspaces: true + }); + workspaceMap = new Map(apiWorkspaces.map((w) => [w.workspaceName ?? "", w])); + }, 200_000); + + apiNames.forEach((name) => { + it.concurrent(name, async () => { + const workspace = workspaceMap.get(name); + if (!workspace) { + throw new Error(`Workspace ${name} not found`); + } await generateAndSnapshotIR({ absolutePathToIr: AbsoluteFilePath.of(path.join(__dirname, "test-definitions-openapi")), workspace, - audiences: - workspace.workspaceName === "audiences" - ? { type: "select", audiences: ["public"] } - : { type: "all" }, - workspaceName: workspace.workspaceName ?? "" + audiences: name === "audiences" ? { type: "select", audiences: ["public"] } : { type: "all" }, + workspaceName: name }); }, 10_000); }); -}, 200_000); +}); it("generics", async () => { const GENERICS_DIR = path.join(__dirname, "fixtures/generics/fern"); diff --git a/packages/commons/ir-utils/src/__test__/hashJSON.test.ts b/packages/commons/ir-utils/src/__test__/hashJSON.test.ts index 119d4c10ea95..bb21df19fda4 100644 --- a/packages/commons/ir-utils/src/__test__/hashJSON.test.ts +++ b/packages/commons/ir-utils/src/__test__/hashJSON.test.ts @@ -24,11 +24,11 @@ describe("hashJSON Function", () => { }); it("should hash a very large object without errors", () => { - const largeObj = generateLargeObject(8, 10); + const largeObj = generateLargeObject(5, 10); expect(() => { const hash = hashJSON(largeObj); expect(typeof hash).toBe("string"); }).not.toThrow(); - }, 120_000); + }, 30_000); }); diff --git a/packages/commons/ir-utils/src/hashJSON.ts b/packages/commons/ir-utils/src/hashJSON.ts index 2c51986e670d..03e9c372d0ea 100644 --- a/packages/commons/ir-utils/src/hashJSON.ts +++ b/packages/commons/ir-utils/src/hashJSON.ts @@ -1,49 +1,61 @@ const MAX_DEPTH = 64; +/** + * Produces a deterministic hash of a JSON-serializable value. + * Keys of objects are sorted to ensure consistent ordering. + * + * Uses an optimized variant of FNV-1a with direct numeric accumulation. + * No intermediate canonical string is built, keeping memory pressure + * minimal even for large object graphs. + */ export function hashJSON(obj: unknown): string { let hash = 0x811c9dc5; + function feedChar(char: number): void { + hash ^= char; + hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24); + hash >>>= 0; + } + + function feedString(str: string): void { + for (let i = 0, len = str.length; i < len; i++) { + feedChar(str.charCodeAt(i)); + } + } + // biome-ignore lint/suspicious/noExplicitAny: allow explicit any - function traverse(value: any, currentDepth: number) { + function traverse(value: any, currentDepth: number): void { if (typeof value === "object" && value != null) { if (currentDepth > MAX_DEPTH) { - updateHash("[MaxDepthExceeded]"); + feedString("[MaxDepthExceeded]"); return; } if (Array.isArray(value)) { - updateHash("["); + feedChar(91); // '[' for (let i = 0; i < value.length; i++) { if (i > 0) { - updateHash(","); + feedChar(44); // ',' } traverse(value[i], currentDepth + 1); } - updateHash("]"); + feedChar(93); // ']' } else { - updateHash("{"); + feedChar(123); // '{' const keys = Object.keys(value).sort(); - keys.forEach((key, index) => { - if (index > 0) { - updateHash(","); + const klen = keys.length; + for (let i = 0; i < klen; i++) { + if (i > 0) { + feedChar(44); // ',' } - updateHash(key); - updateHash(":"); - traverse(value[key], currentDepth + 1); - }); - updateHash("}"); + feedString(keys[i] ?? ""); + feedChar(58); // ':' + traverse(value[keys[i] ?? ""], currentDepth + 1); + } + feedChar(125); // '}' } } else { - updateHash(String(value)); - } - } - - function updateHash(str: string) { - for (let i = 0; i < str.length; i++) { - const char = str.charCodeAt(i); - hash ^= char; - hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24); - hash >>>= 0; + feedString(String(value)); } } diff --git a/seed/postman/examples/collection.json b/seed/postman/examples/collection.json index da7b2e9dc9f2..67e23ab5c647 100644 --- a/seed/postman/examples/collection.json +++ b/seed/postman/examples/collection.json @@ -868,12 +868,14 @@ { "key": "shallow", "description": null, - "value": "false" + "value": "false", + "disabled": true }, { "key": "tag", "description": null, - "value": "development" + "value": "development", + "disabled": true } ], "variable": [] @@ -914,12 +916,14 @@ { "key": "shallow", "description": null, - "value": "false" + "value": "false", + "disabled": true }, { "key": "tag", "description": null, - "value": "development" + "value": "development", + "disabled": true } ], "variable": [] @@ -963,12 +967,14 @@ { "key": "shallow", "description": null, - "value": "true" + "value": "true", + "disabled": true }, { "key": "tag", "description": null, - "value": "tag" + "value": "tag", + "disabled": true } ], "variable": [] diff --git a/seed/postman/exhaustive/collection.json b/seed/postman/exhaustive/collection.json index 3e4b4aa5c494..a18c80360ac1 100644 --- a/seed/postman/exhaustive/collection.json +++ b/seed/postman/exhaustive/collection.json @@ -1996,12 +1996,14 @@ { "key": "cursor", "description": "The cursor for pagination", - "value": "cursor" + "value": "cursor", + "disabled": true }, { "key": "limit", "description": "Maximum number of items to return", - "value": "1" + "value": "1", + "disabled": true } ], "variable": [] @@ -2036,12 +2038,14 @@ { "key": "cursor", "description": "The cursor for pagination", - "value": "cursor" + "value": "cursor", + "disabled": true }, { "key": "limit", "description": "Maximum number of items to return", - "value": "1" + "value": "1", + "disabled": true } ], "variable": [] diff --git a/seed/postman/literal/collection.json b/seed/postman/literal/collection.json index 7356c241e1a9..3ebda8a08cab 100644 --- a/seed/postman/literal/collection.json +++ b/seed/postman/literal/collection.json @@ -448,8 +448,7 @@ { "key": "optional_prompt", "description": null, - "value": "You are a helpful assistant", - "disabled": true + "value": "You are a helpful assistant" }, { "key": "alias_prompt", @@ -459,8 +458,7 @@ { "key": "alias_optional_prompt", "description": null, - "value": "You are a helpful assistant", - "disabled": true + "value": "You are a helpful assistant" }, { "key": "stream", @@ -470,8 +468,7 @@ { "key": "optional_stream", "description": null, - "value": "false", - "disabled": true + "value": "false" }, { "key": "alias_stream", @@ -481,8 +478,7 @@ { "key": "alias_optional_stream", "description": null, - "value": "false", - "disabled": true + "value": "false" }, { "key": "query", @@ -527,8 +523,7 @@ { "key": "optional_prompt", "description": null, - "value": "You are a helpful assistant", - "disabled": true + "value": "You are a helpful assistant" }, { "key": "alias_prompt", @@ -538,8 +533,7 @@ { "key": "alias_optional_prompt", "description": null, - "value": "You are a helpful assistant", - "disabled": true + "value": "You are a helpful assistant" }, { "key": "stream", @@ -549,8 +543,7 @@ { "key": "optional_stream", "description": null, - "value": "false", - "disabled": true + "value": "false" }, { "key": "alias_stream", @@ -560,8 +553,7 @@ { "key": "alias_optional_stream", "description": null, - "value": "false", - "disabled": true + "value": "false" }, { "key": "query", @@ -609,8 +601,7 @@ { "key": "optional_prompt", "description": null, - "value": "You are a helpful assistant", - "disabled": true + "value": "You are a helpful assistant" }, { "key": "alias_prompt", @@ -620,8 +611,7 @@ { "key": "alias_optional_prompt", "description": null, - "value": "You are a helpful assistant", - "disabled": true + "value": "You are a helpful assistant" }, { "key": "query", @@ -636,8 +626,7 @@ { "key": "optional_stream", "description": null, - "value": "false", - "disabled": true + "value": "false" }, { "key": "alias_stream", @@ -647,8 +636,7 @@ { "key": "alias_optional_stream", "description": null, - "value": "false", - "disabled": true + "value": "false" } ], "variable": [] diff --git a/seed/postman/mixed-file-directory/collection.json b/seed/postman/mixed-file-directory/collection.json index a5367928ff53..b7674646a780 100644 --- a/seed/postman/mixed-file-directory/collection.json +++ b/seed/postman/mixed-file-directory/collection.json @@ -211,8 +211,7 @@ { "key": "limit", "description": "The maximum number of results to return.", - "value": "1", - "disabled": true + "value": "1" } ], "variable": [] @@ -248,8 +247,7 @@ { "key": "limit", "description": "The maximum number of results to return.", - "value": "1", - "disabled": true + "value": "1" } ], "variable": [] @@ -290,8 +288,7 @@ { "key": "limit", "description": "The maximum number of results to return.", - "value": "1", - "disabled": true + "value": "1" } ], "variable": [] @@ -326,8 +323,7 @@ { "key": "limit", "description": "The maximum number of results to return.", - "value": "1", - "disabled": true + "value": "1" } ], "variable": [] diff --git a/seed/postman/nullable-optional/collection.json b/seed/postman/nullable-optional/collection.json index 30f84598f996..557cd4664bf2 100644 --- a/seed/postman/nullable-optional/collection.json +++ b/seed/postman/nullable-optional/collection.json @@ -288,22 +288,26 @@ { "key": "limit", "description": null, - "value": "1" + "value": "1", + "disabled": true }, { "key": "offset", "description": null, - "value": "1" + "value": "1", + "disabled": true }, { "key": "includeDeleted", "description": null, - "value": "true" + "value": "true", + "disabled": true }, { "key": "sortBy", "description": null, - "value": "sortBy" + "value": "sortBy", + "disabled": true } ], "variable": [] @@ -339,22 +343,26 @@ { "key": "limit", "description": null, - "value": "1" + "value": "1", + "disabled": true }, { "key": "offset", "description": null, - "value": "1" + "value": "1", + "disabled": true }, { "key": "includeDeleted", "description": null, - "value": "true" + "value": "true", + "disabled": true }, { "key": "sortBy", "description": null, - "value": "sortBy" + "value": "sortBy", + "disabled": true } ], "variable": [] @@ -400,17 +408,20 @@ { "key": "department", "description": null, - "value": "department" + "value": "department", + "disabled": true }, { "key": "role", "description": null, - "value": "role" + "value": "role", + "disabled": true }, { "key": "isActive", "description": null, - "value": "true" + "value": "true", + "disabled": true } ], "variable": [] @@ -452,17 +463,20 @@ { "key": "department", "description": null, - "value": "department" + "value": "department", + "disabled": true }, { "key": "role", "description": null, - "value": "role" + "value": "role", + "disabled": true }, { "key": "isActive", "description": null, - "value": "true" + "value": "true", + "disabled": true } ], "variable": [] @@ -843,17 +857,20 @@ { "key": "role", "description": null, - "value": "ADMIN" + "value": "ADMIN", + "disabled": true }, { "key": "status", "description": null, - "value": "active" + "value": "active", + "disabled": true }, { "key": "secondaryRole", "description": null, - "value": "ADMIN" + "value": "ADMIN", + "disabled": true } ], "variable": [] @@ -890,17 +907,20 @@ { "key": "role", "description": null, - "value": "ADMIN" + "value": "ADMIN", + "disabled": true }, { "key": "status", "description": null, - "value": "active" + "value": "active", + "disabled": true }, { "key": "secondaryRole", "description": null, - "value": "ADMIN" + "value": "ADMIN", + "disabled": true } ], "variable": [] diff --git a/seed/postman/nullable-request-body/collection.json b/seed/postman/nullable-request-body/collection.json index 48143bd155ff..6d69a3d2131a 100644 --- a/seed/postman/nullable-request-body/collection.json +++ b/seed/postman/nullable-request-body/collection.json @@ -127,12 +127,14 @@ { "key": "query_param_object", "description": null, - "value": "{\"id\":\"id\",\"name\":\"name\"}" + "value": "{\"id\":\"id\",\"name\":\"name\"}", + "disabled": true }, { "key": "query_param_integer", "description": null, - "value": "1" + "value": "1", + "disabled": true } ], "variable": [ @@ -185,12 +187,14 @@ { "key": "query_param_object", "description": null, - "value": "{\"id\":\"id\",\"name\":\"name\"}" + "value": "{\"id\":\"id\",\"name\":\"name\"}", + "disabled": true }, { "key": "query_param_integer", "description": null, - "value": "1" + "value": "1", + "disabled": true } ], "variable": [ diff --git a/seed/postman/nullable/collection.json b/seed/postman/nullable/collection.json index ef3debcf021c..fbcd92f04162 100644 --- a/seed/postman/nullable/collection.json +++ b/seed/postman/nullable/collection.json @@ -35,27 +35,32 @@ { "key": "usernames", "description": null, - "value": "usernames" + "value": "usernames", + "disabled": true }, { "key": "avatar", "description": null, - "value": "avatar" + "value": "avatar", + "disabled": true }, { "key": "activated", "description": null, - "value": "true" + "value": "true", + "disabled": true }, { "key": "tags", "description": null, - "value": "tags" + "value": "tags", + "disabled": true }, { "key": "extra", "description": null, - "value": "true" + "value": "true", + "disabled": true } ], "variable": [] @@ -90,27 +95,32 @@ { "key": "usernames", "description": null, - "value": "usernames" + "value": "usernames", + "disabled": true }, { "key": "avatar", "description": null, - "value": "avatar" + "value": "avatar", + "disabled": true }, { "key": "activated", "description": null, - "value": "true" + "value": "true", + "disabled": true }, { "key": "tags", "description": null, - "value": "tags" + "value": "tags", + "disabled": true }, { "key": "extra", "description": null, - "value": "true" + "value": "true", + "disabled": true } ], "variable": []