fix(generators): Move generators and CLI to featherscloud/pinion (#3386)

This commit is contained in:
David Luecke 2024-01-22 08:56:39 -08:00 committed by GitHub
parent 59fb40b9eb
commit eb87c9922d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
58 changed files with 4179 additions and 5966 deletions

View File

@ -1,5 +1,5 @@
import type { Callable, PinionContext } from '@feathershq/pinion'
import { generator, install, prompt, runGenerators, toFile } from '@feathershq/pinion'
import type { Callable, PinionContext } from '@featherscloud/pinion'
import { generator, install, prompt, runGenerators, toFile } from '@featherscloud/pinion'
export interface ModuleContext extends PinionContext {
name: string

View File

@ -1,4 +1,4 @@
import { generator, renderTemplate, toFile } from '@feathershq/pinion'
import { generator, renderTemplate, toFile } from '@featherscloud/pinion'
import { ModuleContext } from '../package'
interface Context extends ModuleContext {}

View File

@ -1,4 +1,4 @@
import { generator, renderTemplate, toFile } from '@feathershq/pinion'
import { generator, renderTemplate, toFile } from '@featherscloud/pinion'
import { ModuleContext } from '../package'
interface Context extends ModuleContext {}

View File

@ -1,4 +1,4 @@
import { generator, toFile, writeJSON } from '@feathershq/pinion'
import { generator, toFile, writeJSON } from '@featherscloud/pinion'
import { ModuleContext } from '../package'
interface Context extends ModuleContext {}

View File

@ -1,4 +1,4 @@
import { generator, renderTemplate, toFile } from '@feathershq/pinion'
import { generator, renderTemplate, toFile } from '@featherscloud/pinion'
import { ModuleContext } from '../package'
const template = ({ description, moduleName }: ModuleContext) => `# ${moduleName}

View File

@ -1,4 +1,4 @@
import { generator, renderTemplate, toFile } from '@feathershq/pinion'
import { generator, renderTemplate, toFile } from '@featherscloud/pinion'
import { ModuleContext } from '../package'
interface Context extends ModuleContext {}

View File

@ -1,4 +1,4 @@
import { generator, toFile, writeJSON } from '@feathershq/pinion'
import { generator, toFile, writeJSON } from '@featherscloud/pinion'
import { ModuleContext } from '../package'
export const generate = (context: ModuleContext) =>

9435
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -38,14 +38,14 @@
"lint": "npm run prettier && npm run eslint",
"compile": "lerna run compile",
"build:docs": "npm run build --workspace docs",
"update-dependencies": "ncu -u && npm exec --workspaces -- ncu -u --dep prod,dev,optional,peer -x node-fetch,chalk,\"@sinclair/typebox\"",
"update-dependencies": "ncu -u && npm exec --workspaces -- ncu -u --dep prod,dev,optional,peer -x node-fetch,\"@sinclair/typebox\"",
"clean": "find . -name node_modules -exec rm -rf '{}' + && find . -name package-lock.json -exec rm -rf '{}' +",
"test:deno": "deno test --config deno/tsconfig.json deno/test.ts",
"test": "npm run lint && npm run compile && c8 lerna run test --ignore @feathersjs/tests",
"generate:package": "pinion run generators/package.ts"
},
"devDependencies": {
"@feathershq/pinion": "^0.4.0-pre.3",
"@featherscloud/pinion": "^0.5.0",
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.19.0",
"c8": "^9.1.0",

View File

@ -1,6 +1,6 @@
#!/usr/bin/env node
'use strict'
const { program } = require('../lib')
import { program } from '../lib/index.js'
program.parse()

View File

@ -3,7 +3,8 @@
"description": "The command line interface for creating Feathers applications",
"version": "5.0.14",
"homepage": "https://feathersjs.com",
"main": "lib/",
"main": "lib/index.js",
"type": "module",
"bin": {
"feathers": "./bin/feathers"
},
@ -45,7 +46,7 @@
"scripts": {
"prepublish": "npm run compile",
"compile": "shx rm -rf lib/ && tsc",
"mocha": "mocha --timeout 60000 --config ../../.mocharc.json --recursive test/**.test.ts test/**/*.test.ts",
"mocha": "mocha --timeout 60000 --config ../../.mocharc.json --require tsx --recursive test/**.test.ts test/**/*.test.ts",
"test": "npm run compile && npm run mocha"
},
"publishConfig": {
@ -53,7 +54,7 @@
},
"dependencies": {
"@feathersjs/generators": "^5.0.14",
"chalk": "^4.0.1",
"chalk": "^5.3.0",
"commander": "^11.1.0"
},
"devDependencies": {

View File

@ -1,7 +1,7 @@
import chalk from 'chalk'
import { Command } from 'commander'
import { dirname } from 'path'
import { generator, runGenerator, getContext, FeathersBaseContext, version } from '@feathersjs/generators'
import { runGenerator, getContext, FeathersBaseContext, version } from '@feathersjs/generators'
export * from 'commander'
export { chalk }
@ -12,7 +12,7 @@ export const commandRunner = (name: string) => async (options: any) => {
...options
})
await generator(ctx)
await Promise.resolve(ctx)
.then(runGenerator(folder, name, 'index'))
.catch((error) => {
const { logger } = ctx.pinion

View File

@ -5,6 +5,7 @@
],
"compilerOptions": {
"outDir": "lib",
"resolveJsonModule": true
"module": "ESNext",
"moduleResolution": "Node"
}
}

View File

@ -29,8 +29,9 @@
"engines": {
"node": ">= 16"
},
"main": "lib/",
"main": "lib/index.js",
"types": "lib/",
"type": "module",
"files": [
"CHANGELOG.md",
"LICENSE",
@ -43,7 +44,7 @@
"scripts": {
"prepublish": "npm run compile",
"compile": "shx rm -rf lib/ && tsc && shx cp -r src/. lib/",
"test": "npm run compile && mocha --config ../../.mocharc.json --recursive test/**.test.ts test/**/*.test.ts"
"test": "npm run compile && mocha --config ../../.mocharc.json --require tsx --recursive test/**.test.ts test/**/*.test.ts"
},
"directories": {
"lib": "lib"
@ -52,8 +53,8 @@
"access": "public"
},
"dependencies": {
"@feathershq/pinion": "^0.3.5",
"chalk": "^4.0.1",
"@featherscloud/pinion": "^0.5.0",
"chalk": "^5.3.0",
"lodash": "^4.17.21",
"prettier": "^3.2.4",
"typescript": "^5.3.3"
@ -88,7 +89,7 @@
"pg": "^8.11.3",
"shx": "^0.3.4",
"sqlite3": "^5.1.7",
"ts-node": "^10.9.2",
"tsx": "^4.7.0",
"type-fest": "^4.9.0",
"typescript": "^5.3.3"
},

View File

@ -1,8 +1,17 @@
import { sep } from 'path'
import { sep, dirname } from 'path'
import chalk from 'chalk'
import { generator, prompt, runGenerators, fromFile, install, copyFiles, toFile } from '@feathershq/pinion'
import { FeathersBaseContext, FeathersAppInfo, initializeBaseContext, addVersions } from '../commons'
import { generate as connectionGenerator, prompts as connectionPrompts } from '../connection'
import { prompt, runGenerators, fromFile, copyFiles, toFile } from '@featherscloud/pinion'
import {
FeathersBaseContext,
FeathersAppInfo,
initializeBaseContext,
addVersions,
install
} from '../commons.js'
import { generate as connectionGenerator, prompts as connectionPrompts } from '../connection/index.js'
// Set __dirname in es module
const __dirname = dirname(new URL(import.meta.url).pathname)
export interface AppGeneratorData extends FeathersAppInfo {
/**
@ -36,7 +45,7 @@ export type AppGeneratorContext = FeathersBaseContext &
export type AppGeneratorArguments = FeathersBaseContext & Partial<AppGeneratorData>
export const generate = (ctx: AppGeneratorArguments) =>
generator(ctx)
Promise.resolve(ctx)
.then(initializeBaseContext())
.then((ctx) => ({
...ctx,
@ -44,7 +53,7 @@ export const generate = (ctx: AppGeneratorArguments) =>
devDependencies: []
}))
.then(
prompt<AppGeneratorArguments, AppGeneratorContext>((ctx) => [
prompt((ctx) => [
{
name: 'language',
type: 'list',
@ -142,7 +151,7 @@ export const generate = (ctx: AppGeneratorArguments) =>
}
})
.then(
install<AppGeneratorContext>(
install(
({ transports, framework, dependencyVersions, dependencies, schema }) => {
const hasSocketio = transports.includes('websockets')
@ -181,7 +190,7 @@ export const generate = (ctx: AppGeneratorArguments) =>
)
)
.then(
install<AppGeneratorContext>(
install(
({ language, devDependencies, dependencyVersions }) => {
devDependencies.push(
'nodemon',

View File

@ -1,6 +1,6 @@
import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { AppGeneratorContext } from '../index'
import { toFile } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { AppGeneratorContext } from '../index.js'
const template = ({
lib
@ -47,4 +47,4 @@ describe('Feathers application tests', () => {
`
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(renderSource(template, toFile('test', 'app.test')))
Promise.resolve(ctx).then(renderSource(template, toFile('test', 'app.test')))

View File

@ -1,6 +1,6 @@
import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { AppGeneratorContext } from '../index'
import { toFile } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { AppGeneratorContext } from '../index.js'
const tsKoaApp = ({
transports,
@ -133,7 +133,7 @@ const template = (ctx: AppGeneratorContext) =>
ctx.framework === 'express' ? tsExpressApp(ctx) : tsKoaApp(ctx)
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
renderSource(
template,
toFile<AppGeneratorContext>(({ lib }) => lib, 'app')

View File

@ -1,6 +1,6 @@
import { generator, toFile, when } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { AppGeneratorContext } from '../index'
import { toFile, when } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { AppGeneratorContext } from '../index.js'
const template = ({
language
@ -43,7 +43,7 @@ export const channels = (app: Application) => {
`
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
when<AppGeneratorContext>(
({ transports }) => transports.includes('websockets'),
renderSource(

View File

@ -1,6 +1,6 @@
import { generator, toFile, when } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { AppGeneratorContext } from '../index'
import { toFile, when } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { AppGeneratorContext } from '../index.js'
const template = ({ lib }: AppGeneratorContext) => /* ts */ `import assert from 'assert'
import axios from 'axios'
@ -23,6 +23,6 @@ describe('client tests', () => {
`
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
when<AppGeneratorContext>((ctx) => ctx.client, renderSource(template, toFile('test', 'client.test')))
)

View File

@ -1,6 +1,6 @@
import { generator, toFile, when } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { AppGeneratorContext } from '../index'
import { toFile, when } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { AppGeneratorContext } from '../index.js'
const template = ({
name,
@ -42,7 +42,7 @@ export const createClient = <Configuration = any> (
`
export const generate = async (ctx: AppGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
when<AppGeneratorContext>(
(ctx) => ctx.client,
renderSource(

View File

@ -1,6 +1,6 @@
import { generator, toFile, when, writeJSON } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { AppGeneratorContext } from '../index'
import { toFile, when, writeJSON } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { AppGeneratorContext } from '../index.js'
const defaultConfig = ({}: AppGeneratorContext) => ({
host: 'localhost',
@ -73,7 +73,7 @@ export const configurationValidator = getValidator(configurationSchema, dataVali
`
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx)
Promise.resolve(ctx)
.then(writeJSON(defaultConfig, toFile('config', 'default.json')))
.then(writeJSON(testConfig, toFile('config', 'test.json')))
.then(writeJSON(customEnvironment, toFile('config', 'custom-environment-variables.json')))

View File

@ -1,5 +1,5 @@
import { generator, toFile, when, renderTemplate } from '@feathershq/pinion'
import { AppGeneratorContext } from '../index'
import { toFile, when, renderTemplate } from '@featherscloud/pinion'
import { AppGeneratorContext } from '../index.js'
const template = ({
framework,
@ -31,7 +31,7 @@ export type HookContext<S = any> = FeathersHookContext<Application, S>
`
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
when<AppGeneratorContext>(
({ language }) => language === 'ts',
renderTemplate(

View File

@ -1,5 +1,5 @@
import { generator, renderTemplate, toFile } from '@feathershq/pinion'
import { AppGeneratorContext } from '../index'
import { renderTemplate, toFile } from '@featherscloud/pinion'
import { AppGeneratorContext } from '../index.js'
const template = ({ name, description }: AppGeneratorContext) => /* html */ `<!DOCTYPE html>
<html lang="en">
@ -41,4 +41,4 @@ const template = ({ name, description }: AppGeneratorContext) => /* html */ `<!D
`
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(renderTemplate(template, toFile('public', 'index.html')))
Promise.resolve(ctx).then(renderTemplate(template, toFile('public', 'index.html')))

View File

@ -1,6 +1,6 @@
import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { AppGeneratorContext } from '../index'
import { toFile } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { AppGeneratorContext } from '../index.js'
const template = ({}: AppGeneratorContext) => /* ts */ `import { app } from './app'
import { logger } from './logger'
@ -18,7 +18,7 @@ app.listen(port).then(() => {
`
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
renderSource(
template,
toFile<AppGeneratorContext>(({ lib }) => lib, 'index')

View File

@ -1,6 +1,6 @@
import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { AppGeneratorContext } from '../index'
import { toFile } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { AppGeneratorContext } from '../index.js'
const template =
({}: AppGeneratorContext) => /* ts */ `// For more information about this file see https://dove.feathersjs.com/guides/cli/logging.html
@ -41,7 +41,7 @@ export const logError = async (context: HookContext, next: NextFunction) => {
`
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx)
Promise.resolve(ctx)
.then(
renderSource(
template,

View File

@ -1,5 +1,5 @@
import { generator, toFile, writeJSON } from '@feathershq/pinion'
import { AppGeneratorContext } from '../index'
import { toFile, writeJSON } from '@featherscloud/pinion'
import { AppGeneratorContext } from '../index.js'
const jsPackageJson = (lib: string) => ({
type: 'module',
@ -75,4 +75,4 @@ const packageJson = ({
})
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(writeJSON(packageJson, toFile('package.json')))
Promise.resolve(ctx).then(writeJSON(packageJson, toFile('package.json')))

View File

@ -1,9 +1,9 @@
import { generator, toFile, writeJSON } from '@feathershq/pinion'
import { AppGeneratorContext } from '../index'
import { PRETTIERRC } from '../../commons'
import { toFile, writeJSON } from '@featherscloud/pinion'
import { AppGeneratorContext } from '../index.js'
import { PRETTIERRC } from '../../commons.js'
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
writeJSON<AppGeneratorContext>(
(ctx) => ({
...PRETTIERRC,

View File

@ -1,5 +1,5 @@
import { generator, renderTemplate, toFile } from '@feathershq/pinion'
import { AppGeneratorContext } from '../index'
import { renderTemplate, toFile } from '@featherscloud/pinion'
import { AppGeneratorContext } from '../index.js'
const template = ({ name, description, language, database }: AppGeneratorContext) => /* md */ `# ${name}
@ -54,4 +54,4 @@ For more information on all the things you can do with Feathers visit [docs.feat
`
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(renderTemplate(template, toFile('readme.md')))
Promise.resolve(ctx).then(renderTemplate(template, toFile('readme.md')))

View File

@ -1,6 +1,6 @@
import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { AppGeneratorContext } from '../index'
import { toFile } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { AppGeneratorContext } from '../index.js'
const template =
({}: AppGeneratorContext) => /* ts */ `// For more information about this file see https://dove.feathersjs.com/guides/cli/application.html#configure-functions
@ -12,7 +12,7 @@ export const services = (app: Application) => {
`
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
renderSource(
template,
toFile<AppGeneratorContext>(({ lib }) => lib, 'services', 'index')

View File

@ -1,8 +1,8 @@
import { generator, toFile, when, writeJSON } from '@feathershq/pinion'
import { AppGeneratorContext } from '../index'
import { toFile, when, writeJSON } from '@featherscloud/pinion'
import { AppGeneratorContext } from '../index.js'
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
when<AppGeneratorContext>(
(ctx) => ctx.language === 'ts',
writeJSON<AppGeneratorContext>(

View File

@ -1,6 +1,6 @@
import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { AppGeneratorContext } from '../index'
import { toFile } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { AppGeneratorContext } from '../index.js'
const validatorTemplate = /* ts */ `// For more information about this file see https://dove.feathersjs.com/guides/cli/validators.html
import { Ajv, addFormats } from '@feathersjs/schema'
@ -31,7 +31,7 @@ export const queryValidator: Ajv = addFormats(new Ajv({
`
export const generate = (ctx: AppGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
renderSource(
validatorTemplate,
toFile<AppGeneratorContext>(({ lib }) => lib, 'validators')

View File

@ -1,7 +1,17 @@
import chalk from 'chalk'
import { generator, runGenerators, prompt, install } from '@feathershq/pinion'
import { addVersions, checkPreconditions, FeathersBaseContext, initializeBaseContext } from '../commons'
import { generate as serviceGenerator, ServiceGeneratorContext } from '../service/index'
import { dirname } from 'path'
import { runGenerators, prompt } from '@featherscloud/pinion'
import {
addVersions,
checkPreconditions,
FeathersBaseContext,
initializeBaseContext,
install
} from '../commons.js'
import { generate as serviceGenerator, ServiceGeneratorContext } from '../service/index.js'
// Set __dirname in es module
const __dirname = dirname(new URL(import.meta.url).pathname)
export interface AuthenticationGeneratorContext extends ServiceGeneratorContext {
service: string
@ -14,62 +24,60 @@ export type AuthenticationGeneratorArguments = FeathersBaseContext &
Partial<Pick<AuthenticationGeneratorContext, 'service' | 'authStrategies' | 'path' | 'schema' | 'type'>>
export const generate = (ctx: AuthenticationGeneratorArguments) =>
generator(ctx)
Promise.resolve(ctx)
.then(initializeBaseContext())
.then(checkPreconditions())
.then(
prompt<AuthenticationGeneratorArguments, AuthenticationGeneratorContext>(
(ctx: AuthenticationGeneratorArguments) => [
{
type: 'checkbox',
name: 'authStrategies',
when: !ctx.authStrategies,
message: 'Which authentication methods do you want to use?',
suffix: chalk.grey(' Other methods and providers can be added at any time.'),
choices: [
{
name: 'Email + Password',
value: 'local',
checked: true
},
{
name: 'Google',
value: 'google'
},
{
name: 'Facebook',
value: 'facebook'
},
{
name: 'Twitter',
value: 'twitter'
},
{
name: 'GitHub',
value: 'github'
},
{
name: 'Auth0',
value: 'auth0'
}
]
},
{
name: 'service',
type: 'input',
when: !ctx.service,
message: 'What is your authentication service name?',
default: 'user'
},
{
name: 'path',
type: 'input',
when: !ctx.path,
message: 'What path should the service be registered on?',
default: 'users'
}
]
)
prompt((ctx: AuthenticationGeneratorArguments) => [
{
type: 'checkbox',
name: 'authStrategies',
when: !ctx.authStrategies,
message: 'Which authentication methods do you want to use?',
suffix: chalk.grey(' Other methods and providers can be added at any time.'),
choices: [
{
name: 'Email + Password',
value: 'local',
checked: true
},
{
name: 'Google',
value: 'google'
},
{
name: 'Facebook',
value: 'facebook'
},
{
name: 'Twitter',
value: 'twitter'
},
{
name: 'GitHub',
value: 'github'
},
{
name: 'Auth0',
value: 'auth0'
}
]
},
{
name: 'service',
type: 'input',
when: !ctx.service,
message: 'What is your authentication service name?',
default: 'user'
},
{
name: 'path',
type: 'input',
when: !ctx.path,
message: 'What path should the service be registered on?',
default: 'users'
}
])
)
.then(async (ctx) => {
const serviceContext = await serviceGenerator({
@ -85,6 +93,7 @@ export const generate = (ctx: AuthenticationGeneratorArguments) =>
}
})
.then(runGenerators(__dirname, 'templates'))
.then((ctx) => ctx as AuthenticationGeneratorContext)
.then((ctx) => {
const dependencies: string[] = []

View File

@ -1,7 +1,7 @@
import { generator, before, toFile } from '@feathershq/pinion'
import { injectSource, renderSource } from '../../commons'
import { AuthenticationGeneratorContext } from '../index'
import { localTemplate, oauthTemplate } from '../../commons'
import { before, toFile } from '@featherscloud/pinion'
import { injectSource, renderSource } from '../../commons.js'
import { AuthenticationGeneratorContext } from '../index.js'
import { localTemplate, oauthTemplate } from '../../commons.js'
const template = ({
authStrategies
@ -41,7 +41,7 @@ const configureTemplate = 'app.configure(authentication)'
const toAppFile = toFile<AuthenticationGeneratorContext>(({ lib }) => [lib, 'app'])
export const generate = (ctx: AuthenticationGeneratorContext) =>
generator(ctx)
Promise.resolve(ctx)
.then(
renderSource(
template,

View File

@ -1,7 +1,7 @@
import { generator, toFile, when } from '@feathershq/pinion'
import { fileExists, renderSource } from '../../commons'
import { AuthenticationGeneratorContext } from '../index'
import { localTemplate } from '../../commons'
import { toFile, when } from '@featherscloud/pinion'
import { fileExists, renderSource } from '../../commons.js'
import { AuthenticationGeneratorContext } from '../index.js'
import { localTemplate } from '../../commons.js'
const template = ({
authStrategies,
@ -66,7 +66,7 @@ describe('application client tests', () => {
`
export const generate = (ctx: AuthenticationGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
when<AuthenticationGeneratorContext>(
({ lib, language }) => fileExists(lib, `client.${language}`),
renderSource(

View File

@ -1,9 +1,9 @@
import crypto from 'crypto'
import { generator, toFile, mergeJSON } from '@feathershq/pinion'
import { AuthenticationGeneratorContext } from '../index'
import { toFile, mergeJSON } from '@featherscloud/pinion'
import { AuthenticationGeneratorContext } from '../index.js'
export const generate = (ctx: AuthenticationGeneratorContext) =>
generator(ctx)
Promise.resolve(ctx)
.then(
mergeJSON<AuthenticationGeneratorContext>(
({ authStrategies }) => {

View File

@ -1,5 +1,5 @@
import { generator, inject, before, toFile, when, append } from '@feathershq/pinion'
import { AuthenticationGeneratorContext } from '../index'
import { inject, before, toFile, when, append } from '@featherscloud/pinion'
import { AuthenticationGeneratorContext } from '../index.js'
const importTemplate = ({
upperName,
@ -24,7 +24,7 @@ declare module '@feathersjs/feathers' {
const toDeclarationFile = toFile<AuthenticationGeneratorContext>(({ lib }) => lib, 'declarations.ts')
export const generate = (ctx: AuthenticationGeneratorContext) =>
generator(ctx)
Promise.resolve(ctx)
.then(
when(
(ctx) => ctx.language === 'ts',

View File

@ -1,5 +1,5 @@
import fs from 'fs'
import { join } from 'path'
import { join, dirname } from 'path'
import { PackageJson } from 'type-fest'
import { readFile, writeFile } from 'fs/promises'
import {
@ -10,12 +10,16 @@ import {
getCallable,
renderTemplate,
inject,
Location
} from '@feathershq/pinion'
import * as ts from 'typescript'
Location,
exec
} from '@featherscloud/pinion'
import ts from 'typescript'
import prettier, { Options as PrettierOptions } from 'prettier'
import path from 'path'
// Set __dirname in es module
const __dirname = dirname(new URL(import.meta.url).pathname)
export const { version } = JSON.parse(fs.readFileSync(join(__dirname, '..', 'package.json')).toString())
export type DependencyVersions = { [key: string]: string }
@ -251,6 +255,20 @@ export const renderSource =
return renderer(ctx).then(prettify(target))
}
export const install =
<C extends PinionContext & { language: 'js' | 'ts' }>(
dependencies: Callable<string[], C>,
dev: Callable<boolean, C>,
packager: Callable<string, C>
) =>
async (ctx: C) => {
const dependencyList = await getCallable(dependencies, ctx)
const packageManager = await getCallable(packager, ctx)
const flags = dev ? [packageManager === 'yarn' ? '--dev' : '--save-dev'] : []
return exec(packager, [packageManager === 'yarn' ? 'add' : 'install', ...dependencyList, ...flags])(ctx)
}
/**
* Inject a source template as the language set in the context.
*

View File

@ -1,13 +1,18 @@
import { generator, runGenerator, prompt, install, mergeJSON, toFile, when } from '@feathershq/pinion'
import { dirname } from 'path'
import { runGenerator, prompt, mergeJSON, toFile, when } from '@featherscloud/pinion'
import chalk from 'chalk'
import {
install,
FeathersBaseContext,
DatabaseType,
getDatabaseAdapter,
addVersions,
checkPreconditions,
initializeBaseContext
} from '../commons'
} from '../commons.js'
// Set __dirname in es module
const __dirname = dirname(new URL(import.meta.url).pathname)
export interface ConnectionGeneratorContext extends FeathersBaseContext {
name?: string
@ -74,10 +79,11 @@ export const getDatabaseClient = (database: DatabaseType) =>
database === 'other' ? null : DATABASE_CLIENTS[database]
export const generate = (ctx: ConnectionGeneratorArguments) =>
generator(ctx)
Promise.resolve(ctx)
.then(initializeBaseContext())
.then(checkPreconditions())
.then(prompt<ConnectionGeneratorArguments, ConnectionGeneratorContext>(prompts))
.then(prompt(prompts))
.then((ctx) => ctx as ConnectionGeneratorContext)
.then(
when<ConnectionGeneratorContext>(
(ctx) => ctx.database !== 'other',

View File

@ -1,6 +1,6 @@
import { generator, toFile, before, mergeJSON } from '@feathershq/pinion'
import { ConnectionGeneratorContext } from '../index'
import { injectSource, renderSource } from '../../commons'
import { toFile, before, mergeJSON } from '@featherscloud/pinion'
import { ConnectionGeneratorContext } from '../index.js'
import { injectSource, renderSource } from '../../commons.js'
import { mkdir } from 'fs/promises'
import path from 'path'
@ -45,7 +45,7 @@ const configureTemplate = ({ database }: ConnectionGeneratorContext) => `app.con
const toAppFile = toFile<ConnectionGeneratorContext>(({ lib }) => [lib, 'app'])
export const generate = (ctx: ConnectionGeneratorContext) =>
generator(ctx)
Promise.resolve(ctx)
.then(
renderSource(
template,

View File

@ -1,6 +1,6 @@
import { generator, toFile, before, prepend, append } from '@feathershq/pinion'
import { ConnectionGeneratorContext } from '../index'
import { injectSource, renderSource } from '../../commons'
import { toFile, before, prepend, append } from '@featherscloud/pinion'
import { ConnectionGeneratorContext } from '../index.js'
import { injectSource, renderSource } from '../../commons.js'
const template = ({
database
@ -37,7 +37,7 @@ const toAppFile = toFile<ConnectionGeneratorContext>(({ lib }) => [lib, 'app'])
const toValidatorFile = toFile<ConnectionGeneratorContext>(({ lib }) => [lib, 'validators'])
export const generate = (ctx: ConnectionGeneratorContext) =>
generator(ctx)
Promise.resolve(ctx)
.then(
renderSource(
template,

View File

@ -1,6 +1,10 @@
import { generator, prompt, runGenerators } from '@feathershq/pinion'
import { dirname } from 'path'
import { prompt, runGenerators } from '@featherscloud/pinion'
import _ from 'lodash'
import { checkPreconditions, FeathersBaseContext, initializeBaseContext } from '../commons'
import { checkPreconditions, FeathersBaseContext, initializeBaseContext } from '../commons.js'
// Set __dirname in es module
const __dirname = dirname(new URL(import.meta.url).pathname)
export interface HookGeneratorContext extends FeathersBaseContext {
name: string
@ -10,7 +14,7 @@ export interface HookGeneratorContext extends FeathersBaseContext {
}
export const generate = (ctx: HookGeneratorContext) =>
generator(ctx)
Promise.resolve(ctx)
.then(initializeBaseContext())
.then(checkPreconditions())
.then(

View File

@ -1,6 +1,6 @@
import { generator, toFile } from '@feathershq/pinion'
import { HookGeneratorContext } from '../index'
import { renderSource } from '../../commons'
import { toFile } from '@featherscloud/pinion'
import { HookGeneratorContext } from '../index.js'
import { renderSource } from '../../commons.js'
const aroundTemplate = ({
camelName,
@ -25,7 +25,7 @@ export const ${camelName} = async (context: HookContext) => {
}`
export const generate = (ctx: HookGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
renderSource(
(ctx) => (ctx.type === 'around' ? aroundTemplate(ctx) : regularTemplate(ctx)),
toFile<HookGeneratorContext>(({ lib, kebabName }) => [lib, 'hooks', kebabName])

View File

@ -1,8 +1,8 @@
export * from '@feathershq/pinion'
export * from '@featherscloud/pinion'
export * from './commons'
export * as app from './app'
export * as authentication from './authentication'
export * as connection from './connection'
export * as hook from './hook'
export * as service from './service'
export * from './commons.js'
export * as app from './app/index.js'
export * as authentication from './authentication/index.js'
export * as connection from './connection/index.js'
export * as hook from './hook/index.js'
export * as service from './service/index.js'

View File

@ -1,5 +1,10 @@
import { dirname } from 'path'
import _ from 'lodash'
import { generator, runGenerator, runGenerators, prompt } from '@feathershq/pinion'
import { runGenerator, runGenerators, prompt } from '@featherscloud/pinion'
import chalk from 'chalk'
// Set __dirname in es module
const __dirname = dirname(new URL(import.meta.url).pathname)
import {
checkPreconditions,
@ -8,8 +13,7 @@ import {
fileExists,
getDatabaseAdapter,
initializeBaseContext
} from '../commons'
import chalk from 'chalk'
} from '../commons.js'
export interface ServiceGeneratorContext extends FeathersBaseContext {
/**
@ -83,104 +87,102 @@ export type ServiceGeneratorArguments = FeathersBaseContext &
>
export const generate = (ctx: ServiceGeneratorArguments) =>
generator(ctx)
Promise.resolve(ctx)
.then(initializeBaseContext())
.then(checkPreconditions())
.then(
prompt<ServiceGeneratorArguments, ServiceGeneratorContext>(
({ name, path, type, schema, authentication, isEntityService, feathers, lib, language }) => {
const sqlDisabled = DATABASE_TYPES.every(
(name) => name === 'mongodb' || name === 'other' || !fileExists(lib, `${name}.${language}`)
)
const mongodbDisabled = !fileExists(lib, `mongodb.${language}`)
prompt(({ name, path, type, schema, authentication, isEntityService, feathers, lib, language }) => {
const sqlDisabled = DATABASE_TYPES.every(
(name) => name === 'mongodb' || name === 'other' || !fileExists(lib, `${name}.${language}`)
)
const mongodbDisabled = !fileExists(lib, `mongodb.${language}`)
return [
{
name: 'name',
type: 'input',
when: !name,
message: 'What is the name of your service?',
validate: (input) => {
if (!input || input === 'authentication') {
return 'Invalid service name'
}
return true
return [
{
name: 'name',
type: 'input',
when: !name,
message: 'What is the name of your service?',
validate: (input: any) => {
if (!input || input === 'authentication') {
return 'Invalid service name'
}
},
{
name: 'path',
type: 'input',
when: !path,
message: 'Which path should the service be registered on?',
default: (answers: ServiceGeneratorArguments) => `${_.kebabCase(answers.name)}`,
validate: (input) => {
if (!input || input === 'authentication') {
return 'Invalid service path'
}
return true
}
},
{
name: 'authentication',
type: 'confirm',
when: authentication === undefined && !isEntityService,
message: 'Does this service require authentication?'
},
{
name: 'type',
type: 'list',
when: !type,
message: 'What database is the service using?',
default: getDatabaseAdapter(feathers?.database),
choices: [
{
value: 'knex',
name: `SQL${sqlDisabled ? chalk.gray(' (connection not available)') : ''}`,
disabled: sqlDisabled
},
{
value: 'mongodb',
name: `MongoDB${mongodbDisabled ? chalk.gray(' (connection not available)') : ''}`,
disabled: mongodbDisabled
},
{
value: 'custom',
name: 'A custom service'
}
]
},
{
name: 'schema',
type: 'list',
when: schema === undefined,
message: 'Which schema definition format do you want to use?',
suffix: chalk.grey(' Schemas allow to type, validate, secure and populate data'),
default: feathers?.schema,
choices: (answers: ServiceGeneratorContext) => [
{
value: 'typebox',
name: `TypeBox ${chalk.gray(' (recommended)')}`
},
{
value: 'json',
name: 'JSON schema'
},
{
value: false,
name: `No schema${
answers.type !== 'custom' ? chalk.gray(' (not recommended with a database)') : ''
}`
}
]
return true
}
]
}
)
},
{
name: 'path',
type: 'input',
when: !path,
message: 'Which path should the service be registered on?',
default: (answers: ServiceGeneratorArguments) => `${_.kebabCase(answers.name)}`,
validate: (input: any) => {
if (!input || input === 'authentication') {
return 'Invalid service path'
}
return true
}
},
{
name: 'authentication',
type: 'confirm',
when: authentication === undefined && !isEntityService,
message: 'Does this service require authentication?'
},
{
name: 'type',
type: 'list',
when: !type,
message: 'What database is the service using?',
default: getDatabaseAdapter(feathers?.database),
choices: [
{
value: 'knex',
name: `SQL${sqlDisabled ? chalk.gray(' (connection not available)') : ''}`,
disabled: sqlDisabled
},
{
value: 'mongodb',
name: `MongoDB${mongodbDisabled ? chalk.gray(' (connection not available)') : ''}`,
disabled: mongodbDisabled
},
{
value: 'custom',
name: 'A custom service'
}
]
},
{
name: 'schema',
type: 'list',
when: schema === undefined,
message: 'Which schema definition format do you want to use?',
suffix: chalk.grey(' Schemas allow to type, validate, secure and populate data'),
default: feathers?.schema,
choices: (answers: ServiceGeneratorContext) => [
{
value: 'typebox',
name: `TypeBox ${chalk.gray(' (recommended)')}`
},
{
value: 'json',
name: 'JSON schema'
},
{
value: false,
name: `No schema${
answers.type !== 'custom' ? chalk.gray(' (not recommended with a database)') : ''
}`
}
]
}
]
})
)
.then(async (ctx): Promise<ServiceGeneratorContext> => {
const { name, path, type, authStrategies = [] } = ctx
const { name, path, type, authStrategies = [] } = ctx as any as ServiceGeneratorContext
const kebabName = _.kebabCase(name)
const camelName = _.camelCase(name)
const upperName = _.upperFirst(camelName)
@ -205,7 +207,7 @@ export const generate = (ctx: ServiceGeneratorArguments) =>
relative,
authStrategies,
...ctx
}
} as ServiceGeneratorContext
})
.then(runGenerators<ServiceGeneratorContext>(__dirname, 'templates'))
.then(runGenerator<ServiceGeneratorContext>(__dirname, 'type', ({ type }) => `${type}.tpl`))

View File

@ -1,6 +1,6 @@
import { generator, toFile, after, before, when } from '@feathershq/pinion'
import { fileExists, injectSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
import { toFile, after, before, when } from '@featherscloud/pinion'
import { fileExists, injectSource } from '../../commons.js'
import { ServiceGeneratorContext } from '../index.js'
const importTemplate = ({ upperName, folder, fileName, camelName }: ServiceGeneratorContext) => /* ts */ `
import { ${camelName}Client } from './services/${folder.join('/')}/${fileName}.shared'
@ -18,7 +18,7 @@ const registrationTemplate = ({ camelName }: ServiceGeneratorContext) =>
const toClientFile = toFile<ServiceGeneratorContext>(({ lib }) => [lib, 'client'])
export const generate = async (ctx: ServiceGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
when<ServiceGeneratorContext>(
({ lib, language }) => fileExists(lib, `client.${language}`),
injectSource(registrationTemplate, before('return client'), toClientFile),

View File

@ -1,6 +1,6 @@
import { generator, toFile, when } from '@feathershq/pinion'
import { fileExists, localTemplate, renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
import { toFile, when } from '@featherscloud/pinion'
import { fileExists, localTemplate, renderSource } from '../../commons.js'
import { ServiceGeneratorContext } from '../index.js'
const authFieldsTemplate = (authStrategies: string[]) =>
authStrategies
@ -127,7 +127,7 @@ export const ${camelName}QueryResolver = resolve<${upperName}Query, HookContext<
`
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
when<ServiceGeneratorContext>(
({ schema }) => schema === 'json',
renderSource(

View File

@ -1,6 +1,6 @@
import { generator, toFile, when } from '@feathershq/pinion'
import { fileExists, localTemplate, renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
import { toFile, when } from '@featherscloud/pinion'
import { fileExists, localTemplate, renderSource } from '../../commons.js'
import { ServiceGeneratorContext } from '../index.js'
const authFieldsTemplate = (authStrategies: string[]) =>
authStrategies
@ -115,7 +115,7 @@ export const ${camelName}QueryResolver = resolve<${upperName}Query, HookContext<
`
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
when<ServiceGeneratorContext>(
({ schema }) => schema === 'typebox',
renderSource(

View File

@ -1,6 +1,6 @@
import { generator, toFile, after, prepend } from '@feathershq/pinion'
import { fileExists, injectSource, renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
import { toFile, after, prepend } from '@featherscloud/pinion'
import { fileExists, injectSource, renderSource } from '../../commons.js'
import { ServiceGeneratorContext } from '../index.js'
export const template = ({
camelName,
@ -132,7 +132,7 @@ declare module '${relative}/declarations' {
const toServiceIndex = toFile(({ lib }: ServiceGeneratorContext) => [lib, 'services', `index`])
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx)
Promise.resolve(ctx)
.then(
renderSource(
template,

View File

@ -1,6 +1,6 @@
import { generator, toFile, when } from '@feathershq/pinion'
import { fileExists, renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
import { toFile, when } from '@featherscloud/pinion'
import { fileExists, renderSource } from '../../commons.js'
import { ServiceGeneratorContext } from '../index.js'
const sharedTemplate = ({
camelName,
@ -48,7 +48,7 @@ declare module '${relative}/client' {
`
export const generate = async (ctx: ServiceGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
when<ServiceGeneratorContext>(
({ lib, language }) => fileExists(lib, `client.${language}`),
renderSource(

View File

@ -1,6 +1,6 @@
import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
import { toFile } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { ServiceGeneratorContext } from '../index.js'
const template = ({
relative,
@ -20,7 +20,7 @@ describe('${path} service', () => {
`
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
renderSource(
template,
toFile<ServiceGeneratorContext>(({ test, folder, fileName }) => [

View File

@ -1,6 +1,6 @@
import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
import { toFile } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { ServiceGeneratorContext } from '../index.js'
export const template = ({
className,
@ -99,7 +99,7 @@ export const getOptions = (app: Application) => {
`
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
renderSource(
template,
toFile<ServiceGeneratorContext>(({ lib, folder, fileName }) => [

View File

@ -1,6 +1,6 @@
import { generator, toFile } from '@feathershq/pinion'
import { renderSource, yyyymmddhhmmss } from '../../commons'
import { ServiceGeneratorContext } from '../index'
import { toFile } from '@featherscloud/pinion'
import { renderSource, yyyymmddhhmmss } from '../../commons.js'
import { ServiceGeneratorContext } from '../index.js'
const migrationTemplate = ({
kebabPath,
@ -85,7 +85,7 @@ export const getOptions = (app: Application): KnexAdapterOptions => {
`
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx)
Promise.resolve(ctx)
.then(
renderSource(
template,

View File

@ -1,6 +1,6 @@
import { generator, toFile } from '@feathershq/pinion'
import { renderSource } from '../../commons'
import { ServiceGeneratorContext } from '../index'
import { toFile } from '@featherscloud/pinion'
import { renderSource } from '../../commons.js'
import { ServiceGeneratorContext } from '../index.js'
export const template = ({
className,
@ -51,7 +51,7 @@ export const getOptions = (app: Application): MongoDBAdapterOptions => {
`
export const generate = (ctx: ServiceGeneratorContext) =>
generator(ctx).then(
Promise.resolve(ctx).then(
renderSource(
template,
toFile<ServiceGeneratorContext>(({ lib, folder, fileName }) => [

View File

@ -1,5 +1,5 @@
import { strictEqual } from 'assert'
import { getJavaScript } from '../src/commons'
import { getJavaScript } from '../lib/commons'
describe('common tests', () => {
it('getJavaScript returns transpiled JavaScript', () => {

View File

@ -3,7 +3,7 @@ import os from 'os'
import path from 'path'
import { mkdtemp } from 'fs/promises'
import assert from 'assert'
import { getContext } from '@feathershq/pinion'
import { getContext } from '@featherscloud/pinion'
import { AppGeneratorContext } from '../src/app'
import { FeathersBaseContext } from '../src/commons'
@ -15,8 +15,8 @@ import { generate as generateApp } from '../lib/app'
import { generate as generateConnection } from '../lib/connection'
import { generate as generateAuthentication } from '../lib/authentication'
import { generate as generateService } from '../lib/service'
import { listAllFiles } from '@feathershq/pinion/lib/utils'
import { AuthenticationGeneratorArguments } from '../src/authentication'
import { listAllFiles } from '@featherscloud/pinion/lib/utils'
import { AuthenticationGeneratorArguments } from '../lib/authentication'
const matrix = {
language: ['js', 'ts'] as const,

View File

@ -3,6 +3,9 @@ import pkg from '../package.json'
import { DependencyVersions } from '../src/commons'
import { readFileSync } from 'fs'
// Set __dirname in es module
const __dirname = path.dirname(new URL(import.meta.url).pathname)
export function combinate<O extends Record<string | number, any[]>>(obj: O) {
let combos: { [k in keyof O]: O[k][number] }[] = []
for (const key of Object.keys(obj)) {

View File

@ -5,6 +5,7 @@
],
"compilerOptions": {
"outDir": "lib",
"resolveJsonModule": true
"module": "ESNext",
"moduleResolution": "Node"
}
}

View File

@ -322,7 +322,10 @@ export class KnexAdapter<
return result
}, {})
await this.db(params).update(newObject, '*', { includeTriggerModifications: true }).where(this.id, id).catch(errorHandler)
await this.db(params)
.update(newObject, '*', { includeTriggerModifications: true })
.where(this.id, id)
.catch(errorHandler)
return this._get(id, params)
}