Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions scripts/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,23 @@ import { exists } from './common.ts';
export class Cache {
folder: string;
generatedFiles: string[];
filesToCache: string[];
dependencies: string[];
cacheFile: string;

constructor({
folder,
generatedFiles,
filesToCache,
dependencies,
cacheFile,
}: {
folder: string;
generatedFiles: string[];
filesToCache: string[];
dependencies: string[];
cacheFile: string;
}) {
this.folder = folder;
this.generatedFiles = generatedFiles;
this.filesToCache = filesToCache;
this.dependencies = dependencies;
this.cacheFile = cacheFile;
}

Expand All @@ -34,14 +34,14 @@ export class Cache {
hash += (await hashElement(`${this.folder}/${generatedFile}`)).hash;
}

for (const fileToCache of this.filesToCache) {
hash += (await hashElement(`${this.folder}/${fileToCache}`)).hash;
for (const dependency of this.dependencies) {
hash += (await hashElement(`${this.folder}/${dependency}`)).hash;
}

return hash;
}

async isValid(): Promise<boolean> {
async hit(): Promise<boolean> {
if (!(await exists(this.cacheFile))) {
return false;
}
Expand Down
8 changes: 4 additions & 4 deletions scripts/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const ROOT_DIR = path.resolve(process.cwd(), '..');
export const GENERATORS = Object.entries(clientsConfig).reduce(
(current, [language, opts]) => {
if (typeof opts === 'string') {
// skip $schema
return current;
}

Expand All @@ -51,7 +52,6 @@ export const GENERATORS = Object.entries(clientsConfig).reduce(
}

current[key] = {
additionalProperties: {},
...opts,
output,
client: clientName,
Expand All @@ -61,7 +61,7 @@ export const GENERATORS = Object.entries(clientsConfig).reduce(

// guess the package name for js from the output folder variable
if (language === 'javascript') {
current[key].additionalProperties.packageName = output.substring(output.lastIndexOf('/') + 1);
current[key].packageName = output.substring(output.lastIndexOf('/') + 1);
}
}

Expand Down Expand Up @@ -153,11 +153,11 @@ async function buildCustomGenerators(): Promise<void> {
const cache = new Cache({
folder: toAbsolutePath('generators/'),
generatedFiles: ['build/classes'],
filesToCache: ['src', 'build.gradle', 'settings.gradle', '../config/.java-version'],
dependencies: ['src', 'build.gradle', 'settings.gradle', '../config/.java-version'],
cacheFile: toAbsolutePath('generators/.cache'),
});

const cacheExists = await cache.isValid();
const cacheExists = await cache.hit();

if (cacheExists) {
spinner.succeed('job skipped, cache found for custom generators');
Expand Down
8 changes: 6 additions & 2 deletions scripts/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import clientsConfig from '../config/clients.config.json' with { type: 'json' };

import { CI } from './common.ts';
import type { Language, LanguageConfig } from './types.ts';
import { CI, createClientName } from './common.ts';
import type { Generator, Language, LanguageConfig } from './types.ts';

export function getClientsConfigField(
language: Language,
Expand Down Expand Up @@ -45,6 +45,10 @@ export function getTestOutputFolder(language: Language): string {
return getClientsConfigField(language, ['tests', 'outputFolder']);
}

export function getSnippetFile(gen: Generator): string {
return `docs/snippets/${gen.language}/${gen.snippets.outputFolder}/${createClientName(gen.client, gen.language)}${gen.snippets.extension}`;
}

export function getDockerImage(language?: Language): string | undefined {
if (CI || !language) {
return undefined;
Expand Down
2 changes: 1 addition & 1 deletion scripts/release/dart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export async function updateDartPackages(changelog: string, nextVersion: string)
}

if (!nextVersion) {
throw new Error(`Failed to bump '${gen.packageName}'.`);
throw new Error(`Failed to bump '${gen.client}'.`);
}

let currentVersion = await getPubspecField(gen.output, 'version');
Expand Down
4 changes: 2 additions & 2 deletions scripts/specs/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ export async function lintCommon(useCache: boolean): Promise<void> {
const cache = new Cache({
folder: toAbsolutePath('specs/'),
generatedFiles: [],
filesToCache: ['common'],
dependencies: ['common'],
cacheFile: toAbsolutePath('specs/dist/common.cache'),
});

if (useCache && (await cache.isValid())) {
if (useCache && (await cache.hit())) {
spinner.succeed("job skipped, cache found for 'common' spec");
return;
}
Expand Down
44 changes: 29 additions & 15 deletions scripts/specs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import fsp from 'fs/promises';
import yaml from 'js-yaml';

import { Cache } from '../cache.ts';
import { exists, run, toAbsolutePath } from '../common.ts';
import { exists, GENERATORS, run, toAbsolutePath } from '../common.ts';
import { createSpinner } from '../spinners.ts';
import type { Spec } from '../types.ts';

import { getSnippetFile } from '../config.ts';
import { bundleSpecsForClient, bundleSpecsForDoc, lintCommon } from './format.ts';
import type { BaseBuildSpecsOptions } from './types.ts';

Expand Down Expand Up @@ -73,51 +74,64 @@ async function buildSpec({
// In case of lite we use a the `search` spec as a base because only its bundled form exists.
const specBase = isLiteSpec ? 'search' : spec;
const logSuffix = `${outputFormat} ${docs ? 'doc spec' : 'spec'}`;
const basePath = docs ? 'docs/' : 'specs/';
const deps = isLiteSpec ? ['search', 'recommend'] : [spec];
const basePath = docs ? 'docs' : 'specs';
const deps = isLiteSpec ? ['specs/search', 'specs/recommend'] : [`specs/${spec}`];
const generatedFile = `${basePath}/bundled/${spec}.${outputFormat}`;

const generatedFiles = [generatedFile];
if (docs && outputFormat === 'yml') {
for (const gen of Object.values(GENERATORS)) {
if (gen.client === spec) {
deps.push(getSnippetFile(gen));
}
}

generatedFiles.push(`docs/bundled/${spec}-snippets.json`);
}

const cache = new Cache({
folder: toAbsolutePath('specs/'),
generatedFiles: [`bundled/${spec}.yml`],
filesToCache: [...deps, 'common'],
cacheFile: toAbsolutePath(`specs/dist/${spec}.cache`),
folder: toAbsolutePath('.'),
generatedFiles,
dependencies: [...deps, 'specs/common'],
cacheFile: toAbsolutePath(`specs/dist/${spec}-${basePath}-${outputFormat}.cache`),
});

const spinner = createSpinner(`starting '${spec}' ${logSuffix}`);

if (useCache) {
spinner.text = `checking cache for '${specBase}'`;
spinner.text = `checking cache for '${specBase}' ${logSuffix}`;

if (await cache.isValid()) {
spinner.succeed(`job skipped, cache found for '${specBase}'`);
if (await cache.hit()) {
spinner.succeed(`job skipped, cache found for '${specBase}' ${logSuffix}`);
return;
}

spinner.text = `cache not found for '${specBase}'`;
spinner.text = `cache not found for '${specBase}' ${logSuffix}`;
}

// First linting the base
spinner.text = `linting '${spec}' ${logSuffix}`;
await run(`yarn specs:fix specs/${specBase}`);

// Then bundle the file
const bundledPath = toAbsolutePath(`${basePath}/bundled/${spec}.${outputFormat}`);
const bundledPath = toAbsolutePath(generatedFile);
await run(`yarn redocly bundle specs/${specBase}/spec.yml -o ${bundledPath} --ext ${outputFormat} `);

if (!(await exists(bundledPath))) {
throw new Error(`Bundled file not found ${bundledPath}.`);
}

// Add the correct tags to be able to generate the proper client
if (!isLiteSpec) {
docs ? await bundleSpecsForDoc(bundledPath, spec) : await bundleSpecsForClient(bundledPath, spec);
} else {
if (isLiteSpec) {
await buildLiteSpec({
spec,
bundledPath: toAbsolutePath(bundledPath),
outputFormat,
docs,
useCache,
});
} else if (outputFormat === 'yml') {
docs ? await bundleSpecsForDoc(bundledPath, spec) : await bundleSpecsForClient(bundledPath, spec);
}

spinner.text = `validating '${spec}' ${logSuffix}`;
Expand Down
11 changes: 5 additions & 6 deletions scripts/specs/snippets.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import fsp from 'fs/promises';

import { GENERATORS, capitalize, createClientName, exists, toAbsolutePath } from '../common.ts';
import { GENERATORS, capitalize, exists, toAbsolutePath } from '../common.ts';
import type { Language } from '../types.ts';

import { getSnippetFile } from '../config.ts';
import type { CodeSamples, OpenAPICodeSample, SampleForOperation } from './types.ts';

export function getCodeSampleLabel(language: Language): OpenAPICodeSample['label'] {
Expand Down Expand Up @@ -63,16 +64,14 @@
continue;
}

const ppath = toAbsolutePath(
`docs/snippets/${gen.language}/${gen.snippets.outputFolder}/${createClientName(clientName, gen.language)}${gen.snippets.extension}`,
);
const snippetPath = toAbsolutePath(getSnippetFile(gen));

if (!(await exists(ppath))) {
if (!(await exists(snippetPath))) {
continue;
}

// find snippets for each operationId in the current gen.language + clientName combo
const snippetFileContent = await fsp.readFile(ppath, 'utf8');
const snippetFileContent = await fsp.readFile(snippetPath, 'utf8');

Check failure on line 74 in scripts/specs/snippets.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

scripts/specs/snippets.ts#L74

The application dynamically constructs file or path information.

const importMatch = snippetFileContent.match(/>IMPORT\n([\s\S]*?)\n.*IMPORT</);
if (importMatch) {
Expand Down
21 changes: 10 additions & 11 deletions scripts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import config from '../config/clients.config.json' with { type: 'json' };

import type { CodeSamples } from './specs/types.ts';

type GeneratedFile = {
extension: string;
outputFolder: string;
};

/**
* Config.
*/
Expand All @@ -11,23 +16,17 @@ export type LanguageConfig = {
modelFolder: string;
apiFolder: string;
packageVersion?: string;
tests: {
extension: string;
outputFolder: string;
};
tests: GeneratedFile;
snippets: GeneratedFile;
};

type AdditionalProperties = Partial<{
packageName: string;
}> &
Record<string, any>;

export type Generator = Record<string, any> & {
export type Generator = {
language: Language;
client: string;
key: string;
output: string;
additionalProperties: AdditionalProperties;
snippets: GeneratedFile;
packageName?: string;
};

export type GeneratorMode = 'client' | 'guides' | 'snippets' | 'tests';
Expand Down
Loading