Skip to content

Commit

Permalink
swaps and code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesvillarrubia committed Jan 7, 2024
1 parent 238d4aa commit 5ff128e
Show file tree
Hide file tree
Showing 36 changed files with 57,094 additions and 16,436 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/line_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ jobs:
strategy:
matrix:
node:
- 14
- 16
- 18
- 20
steps:
- uses: actions/setup-node@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ jobs:
strategy:
matrix:
node:
- 14
- 16
- 18
- 20
steps:
- uses: actions/setup-node@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/update_dependencies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18
node-version: 20
- run: npm ci
- run: |
git config user.name github-actions
Expand Down
68 changes: 66 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ This tool assumes that you are using feathers_v5 and that your services live in

In the `example` folder, you find multiple feathers projects with the code already in place.

## Installation
## Generating

Once your feathers app and core services are installed, you can run

Expand All @@ -36,11 +36,75 @@ You will also see a new folder called `specifications` at root. This is where t
If you open one of the `{name}.spec.yml` files, you'll see that some basic feathers defaults have been setup for you, based on the methods


## Adding Standard Scripts

```bash
npx foas init
```
This command will add serveral npm scripts to your package.json file.
- "spec:build": "npm run spec:generate; npm run spec:merge; npm run spec:validate; npm run spec:swagger",
- "spec:merge": "npx foas merge",
- "spec:generate": "npx foas generate",
- "spec:validate": "npx swagger-cli validate ./specifications/openapi/_merged.yml",
- "spec:mock": "npx @stoplight/prism-cli mock ./specifications/openapi/_merged.yml",
- "spec:swagger'": "node ./node_modules/swagger-to-static/index.js ./specifications/openapi/_merged.yml ./specifications/build"



## Merging into one Spec

```bash
npm install --save feathers-oas
npx foas merge
```
This command will merge all of your spec files into one _merged.yml file at `./specifications/_merged.yml`.

## Adding a SwaggerUI to your site

Once the specifications have been merged, you can build a swagger UI for the _merged.yml file. First, run `npm run spec:swagger` which will build a self-contained `index.html` and `spec.json` inside the `/specifications` folder. To expose this at root, replace the following line in `app.js`.

```javascript
// OLD LINE
// app.use(serveStatic(app.get('public')))

// NEW LINE
app.use(serveStatic('specifications/build'))
```

Now when you visit the root `/` it will serve the index.html file.


## Adding Better examples

The spec that you will build make some basic assumptions around the format of FeathersJS APIs. But the standard information pulled out of your code is not enough to provide good examples. To add examples, you should add an `examples` object to the service options like so

```javascript
app.use(toolPath, new MyService(getOptions(app)), {
// A list of all methods this service exposes externally
methods: toolMethods,
// You can add additional custom events to be sent to clients here
events: [],
examples:{
tools_post_default: { text:"this is my example" },
tools_post_array: [{ text:"this is my example" },{ text:"this is the other example" },],
tools_id_patch_default: { text:"yo I'm patched" },
tools_id_put_default: { text:"yo I'm overwritten" },
tools_id_delete_default: { }
}
})
```

## Serving a mock version





## Contributing
Please see https://github.com/jamesvillarrubia/feathers-oas/blob/main/.github/contributing.md



## Config Options

- mergedPath: location of the final merged api specification yml file
-
124 changes: 66 additions & 58 deletions bin/bin.js
Original file line number Diff line number Diff line change
@@ -1,79 +1,87 @@
#!/usr/bin/env node

import yargs from 'yargs';
import { hideBin } from 'yargs/helpers'
import { hideBin } from 'yargs/helpers';
import { Generator, getDirectories } from '../src/generator.js';
import swaggerMerger from 'swagger-merger'
import { cosmiconfigSync } from 'cosmiconfig'
import openapiMerger from 'openapi-merger';
import { cosmiconfigSync } from 'cosmiconfig';
import Debug from 'debug';
import npmAddScript from 'npm-add-script'


import npmAddScript from 'npm-add-script';
import PostmanConverter from 'openapi-to-postmanv2';
import fs from 'fs';
// import swagToStatic from './static.js'

Debug.colors = [1,3,6,2,4,5];
const debug = Debug('foas')
Debug.colors = [1, 3, 6, 2, 4, 5];
const debug = Debug('foas');

debug('booting %o', 'foas');


// **** Get cli arguments ****//
const argv = yargs(hideBin(process.argv))
.option('config', {
alias: 'c',
type: 'string',
description: 'set config file'
})
.argv

debug('argv %O', argv)


const libName = 'feathers-oas'
const searchPlaces = argv.config ? [argv.config] : [
'package.json',
'.feathers-oas.json'
]

const explorer = cosmiconfigSync(libName,{searchPlaces});
const fullConfig = explorer.search() || {}
let { config } = fullConfig


if(argv._[0] === 'generate'){

let dirs = config?.entities || await getDirectories('./src/services') || []
for (const entity of dirs){
console.log(entity)
let gen = new Generator(entity, fullConfig)
await gen.init()
await gen.generate()
}

const argv = yargs(hideBin(process.argv)).option('config', {
alias: 'c',
type: 'string',
description: 'set config file'
}).argv;

debug('argv %O', argv);

const libName = 'feathers-oas';
const searchPlaces = argv.config ? [argv.config] : ['package.json', '.feathers-oas.json'];

const explorer = cosmiconfigSync(libName, { searchPlaces });
const fullConfig = explorer.search() || {};
const { config } = fullConfig;

if (argv._[0] === 'generate') {
const dirs = config?.entities || (await getDirectories('./src/services')) || [];
for (const entity of dirs) {
console.log(entity);
const gen = new Generator(entity, fullConfig);
await gen.init();
await gen.generate();
}
}

if(argv._[0] == 'merge'){
swaggerMerger({
input: './specifications/openapi/spec.yml',
output: './specifications/openapi/_merged.yml',
compact: false
}).catch(e => {
console.error(e)
})
if (argv._[0] === 'merge') {
openapiMerger({
input: './specifications/openapi/spec.yml',
output: config.mergePath || './specifications/openapi/_merged.yml',
compact: false
}).catch(e => {
console.error(e);
});
}

if(argv._[0] == 'swagger'){
if (argv._[0] === 'postman') {
await fs.promises.mkdir('./specifications/postman/', { recursive: true });
const openapiData = fs.readFileSync('./specifications/openapi/_merged.yml', { encoding: 'UTF8' });
PostmanConverter.convert({ type: 'string', data: openapiData, parametersResolution: 'Example' }, {}, (err, conversionResult) => {
if (err) {
console.error(err);
}
if (!conversionResult.result) {
console.log('Could not convert', conversionResult.reason);
} else {
fs.writeFileSync('./specifications/postman/postman.json', JSON.stringify(conversionResult.output[0].data));
console.log('Postman collection has been written to ./postman/postman.json');
}
});
}

// if (argv._[0] === 'swagger') {

}
// }

if(argv._[0] == 'init'){
npmAddScript({key: "spec:build" , value: "npm run spec:generate; npm run spec:merge; npm run spec:validate; npm run spec:swagger"})
npmAddScript({key: "spec:merge" , value: "npx foas merge"})
npmAddScript({key: "spec:generate" , value: "npx foas generate"})
npmAddScript({key: "spec:validate" , value: "npx swagger-cli validate ./specifications/openapi/_merged.yml"})
npmAddScript({key: "spec:mock" , value: "npx @stoplight/prism-cli mock ./specifications/openapi/_merged.yml"})
npmAddScript({key: "spec:swagger'" , value: "node ./node_modules/swagger-to-static/index.js ./specifications/openapi/_merged.yml ./specifications/build"})
if (argv._[0] === 'init') {
npmAddScript({ key: 'spec:build', value: 'npm run spec:generate; npm run spec:merge; npm run spec:validate; npm run spec:swagger' });
npmAddScript({ key: 'spec:merge', value: 'npx foas merge' });
npmAddScript({ key: 'spec:generate', value: 'npx foas generate' });
npmAddScript({ key: 'spec:validate', value: 'npx @redocly/cli lint --extends=minimal ./specifications/openapi/_merged.yml' });
npmAddScript({ key: 'spec:mock', value: 'npx @stoplight/prism-cli mock ./specifications/openapi/_merged.yml' });
npmAddScript({
key: 'spec:swagger',
value: 'node ./node_modules/feathers-oas/node_modules/swagger-to-static/index.js ./specifications/openapi/_merged.yml ./specifications/build'
});
}

// "spec:swagger": "node ./node_modules/swagger-to-static/index.js ./specifications/openapi/_merged.yml ./specifications/build",
6 changes: 3 additions & 3 deletions example/knexfile.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// For more information about this file see https://dove.feathersjs.com/guides/cli/databases.html
import { app } from './src/app.js'
import { app } from './src/app.js';

// Load our database connection info from the app configuration
const config = app.get('sqlite')
const config = app.get('sqlite');

export default config
export default config;
12 changes: 6 additions & 6 deletions example/migrations/20230306184416_books.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
export async function up(knex) {
export async function up (knex) {
await knex.schema.createTable('books', (table) => {
table.increments('id')
table.string('text')
})
table.increments('id');
table.string('text');
});
}

export async function down(knex) {
await knex.schema.dropTable('books')
export async function down (knex) {
await knex.schema.dropTable('books');
}
12 changes: 6 additions & 6 deletions example/migrations/20230306211235_ducks.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
export async function up(knex) {
export async function up (knex) {
await knex.schema.createTable('ducks', (table) => {
table.increments('id')
table.string('text')
})
table.increments('id');
table.string('text');
});
}

export async function down(knex) {
await knex.schema.dropTable('ducks')
export async function down (knex) {
await knex.schema.dropTable('ducks');
}
1 change: 1 addition & 0 deletions example/schema_gen.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class Generator{
async importJson(path){
let exists = await this.checkExists(path)
if(!exists) return false
// eslint-disable-next-line
let json = await import(path,{assert:{ type: 'json' }})
if(!json || !json.default) throw new Error(`JSON file does not exist at ${path}`)
return json.default
Expand Down
40 changes: 20 additions & 20 deletions example/src/app.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
// For more information about this file see https://dove.feathersjs.com/guides/cli/application.html
import { feathers } from '@feathersjs/feathers'
import configuration from '@feathersjs/configuration'
import { koa, rest, bodyParser, errorHandler, parseAuthentication, cors, serveStatic } from '@feathersjs/koa'
import { feathers } from '@feathersjs/feathers';
import configuration from '@feathersjs/configuration';
import { koa, rest, bodyParser, errorHandler, parseAuthentication, cors, serveStatic } from '@feathersjs/koa';

import { configurationValidator } from './configuration.js'
import { logError } from './hooks/log-error.js'
import { sqlite } from './sqlite.js'
import { services } from './services/index.js'
import { configurationValidator } from './configuration.js';
import { logError } from './hooks/log-error.js';
import { sqlite } from './sqlite.js';
import { services } from './services/index.js';

const app = koa(feathers())
const app = koa(feathers());

// Load our app configuration (see config/ folder)
app.configure(configuration(configurationValidator))
app.configure(configuration(configurationValidator));

// Set up Koa middleware
app.use(cors())
app.use(serveStatic(app.get('public')))
app.use(errorHandler())
app.use(parseAuthentication())
app.use(bodyParser())
app.use(cors());
app.use(serveStatic(app.get('public')));
app.use(errorHandler());
app.use(parseAuthentication());
app.use(bodyParser());

// Configure services and transports
app.configure(rest())
app.configure(sqlite)
app.configure(rest());
app.configure(sqlite);

app.configure(services)
app.configure(services);

// Register hooks that run on all service methods
app.hooks({
Expand All @@ -34,11 +34,11 @@ app.hooks({
before: {},
after: {},
error: {}
})
});
// Register application setup and teardown hooks here
app.hooks({
setup: [],
teardown: []
})
});

export { app }
export { app };
8 changes: 4 additions & 4 deletions example/src/configuration.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { defaultAppSettings, getValidator } from '@feathersjs/schema'
import { defaultAppSettings, getValidator } from '@feathersjs/schema';

import { dataValidator } from './validators.js'
import { dataValidator } from './validators.js';

export const configurationSchema = {
$id: 'configuration',
Expand All @@ -13,6 +13,6 @@ export const configurationSchema = {
port: { type: 'number' },
public: { type: 'string' }
}
}
};

export const configurationValidator = getValidator(configurationSchema, dataValidator)
export const configurationValidator = getValidator(configurationSchema, dataValidator);
Loading

0 comments on commit 5ff128e

Please sign in to comment.