Skip to content

Commit

Permalink
init: Create action
Browse files Browse the repository at this point in the history
  • Loading branch information
TheChristophe committed Jul 23, 2023
0 parents commit 74a4333
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea/
node_modules/
80 changes: 80 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: 'Generate OpenAPI api client'
description: 'Generate typescript OpenAPI esm client using openapi-generator published to Github'
inputs:
author:
description: 'Package author'
required: true
default: 'User'
package_name:
description: 'Package name'
required: true
default: 'api-client'
spec_file:
description: "OpenAPI specification"
required: false
default: 'api-spec.json'
repo_url:
description: 'Repository url'
required: false
archive_client:
description: "Upload archive of client source"
required: false
default: "false"
license:
description: "Package license"
required: false
default: "UNLICENSED"
snapshot:
description: "Add snapshot timestamp to versions"
required: false
default: "false"
npm_registry:
description: "NPM registry"
required: false
default: "https://npm.pkg.github.com"
npm_token:
description: "NPM token (enables publishing)"
required: false
default: "false"

runs:
using: "composite"
steps:
- name: Generate client source
env:
GIT_REPO_URL: ${{ inputs.repo_url }}
AUTHOR: ${{ inputs.author }}
LICENSE: ${{ inputs.license }}
run: |
npx --yes @openapitools/openapi-generator-cli generate -i ${{ inputs.spec_file }} -g typescript-axios -o ./client --additional-properties=npmName=${{ inputs.package_name }} --additional-properties=npmRepository=${{ inputs.npm_registry }} --additional-properties=withSeparateModelsAndApi=true --additional-properties=modelPackage=models --additional-properties=apiPackage=apis ${{ inputs.snapshot == 'true' && '--additional-properties=snapshot=true' || '' }}
node ${{ github.action_path }}/sanitizeGeneratedClient.mjs
shell: bash

- name: Archive client source
if: ${{ inputs.archive_client == 'true' }}
uses: actions/[email protected]
with:
name: client
path: client

- name: Cache client dependencies
if: ${{ inputs.npm_token != 'false' }}
uses: actions/setup-node@v3
with:
cache-dependency-path: ./client/package-lock.json
registry-url: ${{ inputs.npm_registry }}
node-version: '18.x'

- name: Install build dependencies
if: ${{ inputs.npm_token != 'false' }}
working-directory: ./client
run: npm install
shell: bash

- name: Publish client
if: ${{ inputs.npm_token != 'false' }}
working-directory: ./client
run: npm publish
shell: bash
env:
NODE_AUTH_TOKEN: ${{ inputs.npm_token }}
7 changes: 7 additions & 0 deletions openapitools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
"spaces": 2,
"generator-cli": {
"version": "6.6.0"
}
}
106 changes: 106 additions & 0 deletions sanitizeGeneratedClient.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import fs from 'node:fs';
import process from 'node:process';
import path from 'node:path';

const WORK_DIR = './client';

const ifProvided = (value) => {
return value && value.length > 0 ? value : undefined
}

const GIT_REPO_URL = ifProvided(process.env.GIT_REPO_URL);
const AUTHOR = process.env.AUTHOR ?? "User";
const LICENSE = process.env.LICENSE ?? "UNLICENSED";

const sanitizePackageJson = async () => {
const dirtyPackageJson = JSON.parse(fs.readFileSync(`${WORK_DIR}/package.json`, 'utf8'));

delete dirtyPackageJson.main;
dirtyPackageJson.module = './dist/index.js';
dirtyPackageJson.sideEffects = false;

dirtyPackageJson.dependencies.axios = '^1.4.0';
// cloudflare pages configured to node 18, don't use higher versions
dirtyPackageJson.devDependencies['@types/node'] = '^18.16.17';
dirtyPackageJson.devDependencies['typescript'] = '^5.1.6';

if (GIT_REPO_URL === undefined) {
delete dirtyPackageJson.repository;
}
else {
dirtyPackageJson.repository = {
type: 'git',
url: GIT_REPO_URL,
};
}

dirtyPackageJson.license = LICENSE;
dirtyPackageJson.author = AUTHOR;

dirtyPackageJson.type = "module";
dirtyPackageJson.exports = {
".": {
types: "./dist/index.d.ts",
import: "./dist/index.js",
default: "./dist/index.js",
}
};

dirtyPackageJson.files = [
"/dist",
"/package.json",
"/README.md",
];

fs.writeFileSync(`${WORK_DIR}/package.json`, JSON.stringify(dirtyPackageJson, null, 2), 'utf8');
};

const sanitizeTsConfig = async () => {
const dirtyTsConfig = JSON.parse(fs.readFileSync(`${WORK_DIR}/tsconfig.json`, 'utf8'));

dirtyTsConfig.compilerOptions.target = 'ES6';
dirtyTsConfig.compilerOptions.module = 'NodeNext';
dirtyTsConfig.compilerOptions.moduleResolution = 'NodeNext';
dirtyTsConfig.compilerOptions.allowSyntheticDefaultImports = true;
delete dirtyTsConfig.compilerOptions.lib;

fs.writeFileSync(`${WORK_DIR}/tsconfig.json`, JSON.stringify(dirtyTsConfig, null, 2), 'utf8');
};

const sanitizeTsImports = async () => {
// https://gist.github.com/lovasoa/8691344?permalink_comment_id=3299089#gistcomment-3299089
async function* walk(dir) {
for await (const d of await fs.promises.opendir(dir)) {
const entry = path.join(dir, d.name);
if (d.isDirectory()) {
yield* await walk(entry);
}
else if (d.isFile()) {
yield entry;
}
}
}

for await (const p of walk(`${WORK_DIR}/`)) {
if (p.endsWith('.ts')) {
fs.writeFileSync(
p,
fs.readFileSync(p, 'utf8')
// replace imports of files with *.js
.replaceAll(
/(from\s+)(["'])(?!.*\.js)(\.?\.\/(?!(apis|models)["']).*)(["'])/g,
'$1$2$3.js$5')
// replace imports of api/models folders with */index.js
.replaceAll(
/(from\s+)(["'])(?!.*\.js)(\.?\.\/(apis|models))(["'])/g,
'$1$2$3/index.js$5'),
'utf8');
}
}
}

await Promise.all([
sanitizePackageJson(),
sanitizeTsConfig(),
sanitizeTsImports(),
]);

0 comments on commit 74a4333

Please sign in to comment.