From eaa5e0b13c275453d3db72765df1678ac4c3463c Mon Sep 17 00:00:00 2001 From: Chris Watts Date: Thu, 23 Nov 2017 22:01:05 -0800 Subject: [PATCH] Add blueprints for typescript files --- .../files/test/acceptance/__name__-test.ts | 6 + blueprints/acceptance-test/index.ts | 30 ++++ .../action/files/app/actions/__name__.ts | 10 ++ .../files/test/unit/actions/__name__-test.ts | 3 + blueprints/action/index.ts | 66 +++++++ .../files/config/migrations/__filename__.ts | 11 ++ blueprints/migration/index.ts | 33 ++++ blueprints/model/files/app/models/__name__.ts | 5 + .../model/files/app/serializers/__name__.ts | 9 + .../files/test/unit/models/__name__-test.ts | 3 + .../test/unit/serializers/__name__-test.ts | 3 + blueprints/model/index.ts | 35 ++++ .../files/app/orm-adapters/__name__.ts | 165 ++++++++++++++++++ .../test/unit/orm-adapters/__name__-test.ts | 3 + blueprints/orm-adapter/index.ts | 39 +++++ .../app/actions/__plural.name__/create.ts | 11 ++ .../app/actions/__plural.name__/destroy.ts | 12 ++ .../files/app/actions/__plural.name__/list.ts | 9 + .../files/app/actions/__plural.name__/show.ts | 10 ++ .../app/actions/__plural.name__/update.ts | 13 ++ .../files/app/models/__singular.name__.ts | 8 + .../app/serializers/__singular.name__.ts | 9 + .../test/acceptance/__plural.name__-test.ts | 56 ++++++ .../unit/models/__singular.name__-test.ts | 3 + .../serializers/__singular.name__-test.ts | 3 + blueprints/resource/index.ts | 59 +++++++ .../files/app/serializers/__name__.ts | 9 + .../test/unit/serializers/__name__-test.ts | 3 + blueprints/serializer/index.ts | 34 ++++ .../service/files/app/services/__name__.ts | 4 + .../files/test/unit/services/__name__-test.ts | 3 + blueprints/service/index.ts | 30 ++++ 32 files changed, 697 insertions(+) create mode 100644 blueprints/acceptance-test/files/test/acceptance/__name__-test.ts create mode 100644 blueprints/acceptance-test/index.ts create mode 100644 blueprints/action/files/app/actions/__name__.ts create mode 100644 blueprints/action/files/test/unit/actions/__name__-test.ts create mode 100644 blueprints/action/index.ts create mode 100644 blueprints/migration/files/config/migrations/__filename__.ts create mode 100644 blueprints/migration/index.ts create mode 100644 blueprints/model/files/app/models/__name__.ts create mode 100644 blueprints/model/files/app/serializers/__name__.ts create mode 100644 blueprints/model/files/test/unit/models/__name__-test.ts create mode 100644 blueprints/model/files/test/unit/serializers/__name__-test.ts create mode 100644 blueprints/model/index.ts create mode 100644 blueprints/orm-adapter/files/app/orm-adapters/__name__.ts create mode 100644 blueprints/orm-adapter/files/test/unit/orm-adapters/__name__-test.ts create mode 100644 blueprints/orm-adapter/index.ts create mode 100644 blueprints/resource/files/app/actions/__plural.name__/create.ts create mode 100644 blueprints/resource/files/app/actions/__plural.name__/destroy.ts create mode 100644 blueprints/resource/files/app/actions/__plural.name__/list.ts create mode 100644 blueprints/resource/files/app/actions/__plural.name__/show.ts create mode 100644 blueprints/resource/files/app/actions/__plural.name__/update.ts create mode 100644 blueprints/resource/files/app/models/__singular.name__.ts create mode 100644 blueprints/resource/files/app/serializers/__singular.name__.ts create mode 100644 blueprints/resource/files/test/acceptance/__plural.name__-test.ts create mode 100644 blueprints/resource/files/test/unit/models/__singular.name__-test.ts create mode 100644 blueprints/resource/files/test/unit/serializers/__singular.name__-test.ts create mode 100644 blueprints/resource/index.ts create mode 100644 blueprints/serializer/files/app/serializers/__name__.ts create mode 100644 blueprints/serializer/files/test/unit/serializers/__name__-test.ts create mode 100644 blueprints/serializer/index.ts create mode 100644 blueprints/service/files/app/services/__name__.ts create mode 100644 blueprints/service/files/test/unit/services/__name__-test.ts create mode 100644 blueprints/service/index.ts diff --git a/blueprints/acceptance-test/files/test/acceptance/__name__-test.ts b/blueprints/acceptance-test/files/test/acceptance/__name__-test.ts new file mode 100644 index 0000000..9bfade3 --- /dev/null +++ b/blueprints/acceptance-test/files/test/acceptance/__name__-test.ts @@ -0,0 +1,6 @@ +import test from 'ava'; +import { appAcceptanceTest } from 'denali'; + +appAcceptanceTest(test); + +test.todo('<%= humanizedName %>'); \ No newline at end of file diff --git a/blueprints/acceptance-test/index.ts b/blueprints/acceptance-test/index.ts new file mode 100644 index 0000000..c03c70d --- /dev/null +++ b/blueprints/acceptance-test/index.ts @@ -0,0 +1,30 @@ +import { + lowerCase +} from 'lodash'; +import { Blueprint, unwrap } from 'denali-cli'; + +/** + * Generates a model, serializer, CRUD actions, and tests for a resource + * + * @package blueprints + */ +export default class ResourceBlueprint extends Blueprint { + + /* tslint:disable:completed-docs typedef */ + static blueprintName = 'acceptance-test'; + static description = 'Generates a blank acceptance test'; + static longDescription = unwrap` + Usage: denali generate acceptance-test + + Generates a blank acceptance test, suitable for testing your app end-to-end with simulated HTTP + requests and responses. + `; + + static params = ''; + + locals(argv: any) { + let name = argv.name; + return { name, humanizedName: lowerCase(name) }; + } + +} diff --git a/blueprints/action/files/app/actions/__name__.ts b/blueprints/action/files/app/actions/__name__.ts new file mode 100644 index 0000000..76d08c7 --- /dev/null +++ b/blueprints/action/files/app/actions/__name__.ts @@ -0,0 +1,10 @@ +import ApplicationAction from '<%= nesting %>/application'; +import { ResponderParams } from 'denali'; + +export default class <%= className %>Action extends ApplicationAction { + + async respond(/*{ body, params, query, headers }: ResponderParams */) { + + } + +} diff --git a/blueprints/action/files/test/unit/actions/__name__-test.ts b/blueprints/action/files/test/unit/actions/__name__-test.ts new file mode 100644 index 0000000..2d9169f --- /dev/null +++ b/blueprints/action/files/test/unit/actions/__name__-test.ts @@ -0,0 +1,3 @@ +import test from 'ava'; + +test.todo('<%= className %>Action'); diff --git a/blueprints/action/index.ts b/blueprints/action/index.ts new file mode 100644 index 0000000..10fcaeb --- /dev/null +++ b/blueprints/action/index.ts @@ -0,0 +1,66 @@ +import { + upperFirst, + camelCase +} from 'lodash'; +import { Blueprint, unwrap } from 'denali-cli'; + +/** + * Generate an new action class + tests. + * + * @package blueprints + */ +export default class ActionBlueprint extends Blueprint { + + /* tslint:disable:completed-docs typedef */ + static blueprintName = 'action'; + static description = 'Generates a new action class & unit tests'; + static longDescription = unwrap` + Usage: denali generate action [options] + + Generates an action with the given name (can be a deeply nested path), along with unit test + stubs. + + Guides: http://denalijs.org/master/guides/application/actions/ + `; + + static params = ''; + + static flags = { + method: { + description: 'The HTTP method to use for the route to this action', + default: 'post', + type: 'string' + } + }; + + static runsInApp = true; + + locals(argv: any): any { + let name = argv.name; + let levels = name.split('/').map(() => '..'); + levels.pop(); + let nesting: string; + if (levels.length > 0) { + nesting = levels.join('/'); + } else { + nesting = '.'; + } + return { + name, + className: upperFirst(camelCase(name)), + nesting + }; + } + + async postInstall(argv: any): Promise { + let name = argv.name; + let method = argv.method || 'post'; + this.addRoute(method.toLowerCase(), `/${ name }`, name); + } + + async postUninstall(argv: any): Promise { + let name = argv.name; + let method = argv.method || 'post'; + this.removeRoute(method.toLowerCase(), `/${ name }`, name); + } +} diff --git a/blueprints/migration/files/config/migrations/__filename__.ts b/blueprints/migration/files/config/migrations/__filename__.ts new file mode 100644 index 0000000..645aa82 --- /dev/null +++ b/blueprints/migration/files/config/migrations/__filename__.ts @@ -0,0 +1,11 @@ +import * as Knex from 'knex'; + +export async function up(knex: Knex) { + return knex.schema.createTable('posts', (post) => { + post.text('title'); + }); +} + +export async function down(knex: Knex) { + return knex.schema.dropTable('posts'); +} diff --git a/blueprints/migration/index.ts b/blueprints/migration/index.ts new file mode 100644 index 0000000..81f4077 --- /dev/null +++ b/blueprints/migration/index.ts @@ -0,0 +1,33 @@ +import { Blueprint, unwrap } from 'denali-cli'; +import * as moment from 'moment'; +import * as assert from 'assert'; + +/** + * Generates a database schema migration + * + * @package blueprints + */ +export default class MigrationBlueprint extends Blueprint { + + /* tslint:disable:completed-docs typedef */ + static blueprintName = 'migration'; + static description = 'Generates a database schema migration'; + static longDescription = unwrap` + Usage: denali generate migration [options] + + Generates a new blank migration. The filename will include the current Unix timestamp to ensure + proper sorting and execution order when running migrations. + + Guides: http://denalijs.org/master/guides/data/migrations/ + `; + + static params = ''; + + locals(argv: any) { + let name = argv.name; + assert(name, 'You must provide a name for this migration'); + let filename = `${ moment().format('X') }-${ name }`; + return { name, filename }; + } + +} diff --git a/blueprints/model/files/app/models/__name__.ts b/blueprints/model/files/app/models/__name__.ts new file mode 100644 index 0000000..a067953 --- /dev/null +++ b/blueprints/model/files/app/models/__name__.ts @@ -0,0 +1,5 @@ +// import { attr, hasOne, hasMany } from 'denali'; +import ApplicationModel from './application'; + +export default class <%= className %>Model extends ApplicationModel { +} diff --git a/blueprints/model/files/app/serializers/__name__.ts b/blueprints/model/files/app/serializers/__name__.ts new file mode 100644 index 0000000..4b94859 --- /dev/null +++ b/blueprints/model/files/app/serializers/__name__.ts @@ -0,0 +1,9 @@ +import ApplicationSerializer from './application'; + +export default class <%= className %>Serializer extends ApplicationSerializer { + + attributes: string[] = []; + + relationships: any = {}; + +} diff --git a/blueprints/model/files/test/unit/models/__name__-test.ts b/blueprints/model/files/test/unit/models/__name__-test.ts new file mode 100644 index 0000000..18cdd68 --- /dev/null +++ b/blueprints/model/files/test/unit/models/__name__-test.ts @@ -0,0 +1,3 @@ +import test from 'ava'; + +test.todo('<%= className %>Model'); diff --git a/blueprints/model/files/test/unit/serializers/__name__-test.ts b/blueprints/model/files/test/unit/serializers/__name__-test.ts new file mode 100644 index 0000000..177d3df --- /dev/null +++ b/blueprints/model/files/test/unit/serializers/__name__-test.ts @@ -0,0 +1,3 @@ +import test from 'ava'; + +test.todo('<%= className %>Serializer'); diff --git a/blueprints/model/index.ts b/blueprints/model/index.ts new file mode 100644 index 0000000..323cbd5 --- /dev/null +++ b/blueprints/model/index.ts @@ -0,0 +1,35 @@ +import { + upperFirst, + camelCase +} from 'lodash'; +import { Blueprint, unwrap } from 'denali-cli'; + +/** + * Generates a blank model + * + * @package blueprints + */ +export default class ModelBlueprint extends Blueprint { + + /* tslint:disable:completed-docs typedef */ + static blueprintName = 'model'; + static description = 'Generates a blank model'; + static longDescription = unwrap` + Usage: denali generate model [options] + + Generates a blank model, along with a serializer for that model, and unit tests for both. + + Guides: http://denalijs.org/master/guides/data/models/ + `; + + static params = ''; + + locals(argv: any) { + let name = argv.name; + return { + name, + className: upperFirst(camelCase(name)) + }; + } + +} diff --git a/blueprints/orm-adapter/files/app/orm-adapters/__name__.ts b/blueprints/orm-adapter/files/app/orm-adapters/__name__.ts new file mode 100644 index 0000000..06728a9 --- /dev/null +++ b/blueprints/orm-adapter/files/app/orm-adapters/__name__.ts @@ -0,0 +1,165 @@ +import { ORMAdapter } from 'denali'; + +export default class <%= className %>Adapter extends ORMAdapter { + + /** + * Find a record by id. + */ + async find(type, id, options) { + } + + /** + * Find a single record that matches the given query. + */ + async queryOne(type, query, options) { + } + + /** + * Find all records of this type. + */ + async all(type, options) { + } + + /** + * Find all records that match the given query. + */ + async query(type, query, options) { + } + + /** + * Return the id for the given model. + */ + idFor(model) { + } + + /** + * Set the id for the given model. + */ + setId(model, value) { + } + + /** + * Build an internal record instance of the given type with the given data. Note that this method + * should return the internal, ORM representation of the record, not a Denali Model. + */ + buildRecord(type, data, options) { + } + + /** + * Return the value for the given attribute on the given record. + */ + getAttribute(model, attribute) { + } + + /** + * Set the value for the given attribute on the given record. + * + * @returns returns true if set operation was successful + */ + setAttribute(model, attribute, value) { + } + + /** + * Delete the value for the given attribute on the given record. The semantics of this may behave + * slightly differently depending on backend - SQL databases may NULL out the value, while + * document stores like Mongo may actually delete the key from the document (rather than just + * nulling it out) + * + * @returns returns true if delete operation was successful + */ + deleteAttribute(model, attribute) { + } + + /** + * Return the related record(s) for the given relationship. + * + * @param model The model whose related records are being fetched + * @param relationship The name of the relationship on the model that should be fetched + * @param descriptor The RelationshipDescriptor of the relationship being fetch + * @param query An optional query to filter the related records by + */ + async getRelated(model, relationship, descriptor, query, options) { + } + + /** + * Set the related record(s) for the given relationship. Note: for has-many relationships, the + * entire set of existing related records should be replaced by the supplied records. The old + * related records should be "unlinked" in their relationship. Whether that results in the + * deletion of those old records is up to the ORM adapter, although it is recommended that they + * not be deleted unless the user has explicitly expressed that intent. + * + * @param model The model whose related records are being altered + * @param relationship The name of the relationship on the model that should be altered + * @param descriptor The RelationshipDescriptor of the relationship being altered + * @param related The related record(s) that should be linked to the given relationship + */ + async setRelated(model, relationship, descriptor, related, options) { + } + + /** + * Add related record(s) to a hasMany relationship. Existing related records should remain + * unaltered. + * + * @param model The model whose related records are being altered + * @param relationship The name of the relationship on the model that should be altered + * @param descriptor The RelationshipDescriptor of the relationship being altered + * @param related The related record(s) that should be linked to the given relationship + */ + async addRelated(model, relationship, descriptor, related, options) { + } + + /** + * Remove related record(s) from a hasMany relationship. Note: The removed related records should + * be "unlinked" in their relationship. Whether that results in the deletion of those old records + * is up to the ORM adapter, although it is recommended that they not be deleted unless the user + * has explicitly expressed that intent. + * + * @param model The model whose related records are being altered + * @param relationship The name of the relationship on the model that should be altered + * @param descriptor The RelationshipDescriptor of the relationship being altered + * @param related The related record(s) that should be removed from the relationship; if not + * provided, then all related records should be removed + */ + async removeRelated(model, relationship, descriptor, related, options) { + } + + /** + * Persist the supplied model. + */ + async saveRecord(model, options) { + } + + /** + * Delete the supplied model from the persistent data store. + */ + async deleteRecord(model, options) { + } + + /** + * Takes an array of Denali Models and defines an ORM specific model class, and/or any other ORM + * specific setup that might be required for that Model. + */ + // async defineModels(models) { + // }; + + /** + * Start a transaction that will wrap a test, and be rolled back afterwards. If the data store + * doesn't support transactions, just omit this method. Only one test transaction will be opened + * per process, and the ORM adapter is responsible for keeping track of that transaction so it + * can later be rolled back. + */ + // async startTestTransaction() { + // } + + /** + * Roll back the test transaction. + */ + // async rollbackTestTransaction() { + // } + + /** + * The current test transaction, if applicable + */ + // testTransaction; + +} diff --git a/blueprints/orm-adapter/files/test/unit/orm-adapters/__name__-test.ts b/blueprints/orm-adapter/files/test/unit/orm-adapters/__name__-test.ts new file mode 100644 index 0000000..2e1b493 --- /dev/null +++ b/blueprints/orm-adapter/files/test/unit/orm-adapters/__name__-test.ts @@ -0,0 +1,3 @@ +import test from 'ava'; + +test.todo('<%= className %> ORM Adapter'); diff --git a/blueprints/orm-adapter/index.ts b/blueprints/orm-adapter/index.ts new file mode 100644 index 0000000..c4c9d2c --- /dev/null +++ b/blueprints/orm-adapter/index.ts @@ -0,0 +1,39 @@ +import { Blueprint, unwrap } from 'denali-cli'; +import { singularize } from 'inflection'; +import { + upperFirst, + camelCase +} from 'lodash'; + +/** + * Generates a blank ORM adapter with stubs for all the required methods + * + * @package blueprints + */ +export default class ORMAdapterBlueprint extends Blueprint { + + /* tslint:disable:completed-docs typedef */ + static blueprintName = 'orm-adapter'; + static description = 'Generates a blank ORM adapter with stubs for all the required methods'; + static longDescription = unwrap` + Usage: denali generate orm-adapter [options] + + Generates a new ORM adapter with stubs for all the required adapter methods. Note: this is + typically an advanced use case (i.e. using a niche, specialty database). You should check to + make sure there isn't already a Denali addon that implements the ORM adapter you need. + + Guides: http://denalijs.org/master/guides/data/orm-adapters/ + `; + + static params = ''; + + locals(argv: any) { + let name = argv.name; + name = singularize(name); + return { + name, + className: upperFirst(camelCase(name)) + }; + } + +} diff --git a/blueprints/resource/files/app/actions/__plural.name__/create.ts b/blueprints/resource/files/app/actions/__plural.name__/create.ts new file mode 100644 index 0000000..5ebef31 --- /dev/null +++ b/blueprints/resource/files/app/actions/__plural.name__/create.ts @@ -0,0 +1,11 @@ +import { ResponderParams } from 'denali'; +import ApplicationAction from '../application'; + +export default class Create<%= singular.className %> extends ApplicationAction { + + async respond({ body }: ResponderParams) { + let post = await this.db.create('<%= singular.dasherized %>', body).save(); + this.render(201, post); + } + +} diff --git a/blueprints/resource/files/app/actions/__plural.name__/destroy.ts b/blueprints/resource/files/app/actions/__plural.name__/destroy.ts new file mode 100644 index 0000000..7022868 --- /dev/null +++ b/blueprints/resource/files/app/actions/__plural.name__/destroy.ts @@ -0,0 +1,12 @@ +import { ResponderParams } from 'denali'; +import ApplicationAction from '../application'; + +export default class Destroy<%= singular.className %> extends ApplicationAction { + + async respond({ params }: ResponderParams) { + let post = await this.db.find('<%= singular.dasherized %>', params.id); + await post.destroy(); + this.render(204); + } + +} diff --git a/blueprints/resource/files/app/actions/__plural.name__/list.ts b/blueprints/resource/files/app/actions/__plural.name__/list.ts new file mode 100644 index 0000000..b85bd2c --- /dev/null +++ b/blueprints/resource/files/app/actions/__plural.name__/list.ts @@ -0,0 +1,9 @@ +import ApplicationAction from '../application'; + +export default class List<%= plural.className %> extends ApplicationAction { + + async respond() { + return await this.db.all('<%= singular.dasherized %>'); + } + +} diff --git a/blueprints/resource/files/app/actions/__plural.name__/show.ts b/blueprints/resource/files/app/actions/__plural.name__/show.ts new file mode 100644 index 0000000..bc32895 --- /dev/null +++ b/blueprints/resource/files/app/actions/__plural.name__/show.ts @@ -0,0 +1,10 @@ +import { ResponderParams } from 'denali'; +import ApplicationAction from '../application'; + +export default class Show<%= singular.className %> extends ApplicationAction { + + async respond({ params }: ResponderParams) { + return this.db.find('<%= singular.dasherized %>', params.id); + } + +} diff --git a/blueprints/resource/files/app/actions/__plural.name__/update.ts b/blueprints/resource/files/app/actions/__plural.name__/update.ts new file mode 100644 index 0000000..14f4312 --- /dev/null +++ b/blueprints/resource/files/app/actions/__plural.name__/update.ts @@ -0,0 +1,13 @@ +import { ResponderParams } from 'denali'; +import ApplicationAction from '../application'; + + +export default class Update<%= singular.className %> extends ApplicationAction { + + async respond({ params, body }: ResponderParams) { + let post = await this.db.find('<%= singular.dasherized %>', params.id); + Object.assign(post, body); + return await post.save(); + } + +} diff --git a/blueprints/resource/files/app/models/__singular.name__.ts b/blueprints/resource/files/app/models/__singular.name__.ts new file mode 100644 index 0000000..3e4e058 --- /dev/null +++ b/blueprints/resource/files/app/models/__singular.name__.ts @@ -0,0 +1,8 @@ +import { attr /* , hasOne, hasMany */ } from 'denali'; +import ApplicationModel from './application'; + +export default class <%= singular.className %> extends ApplicationModel { + + // static title = attr('text'); + +} diff --git a/blueprints/resource/files/app/serializers/__singular.name__.ts b/blueprints/resource/files/app/serializers/__singular.name__.ts new file mode 100644 index 0000000..9f4cd5e --- /dev/null +++ b/blueprints/resource/files/app/serializers/__singular.name__.ts @@ -0,0 +1,9 @@ +import ApplicationSerializer from './application'; + +export default class <%= singular.className %>Serializer extends ApplicationSerializer { + + attributes: string[] = []; + + relationships: any = {}; + +} diff --git a/blueprints/resource/files/test/acceptance/__plural.name__-test.ts b/blueprints/resource/files/test/acceptance/__plural.name__-test.ts new file mode 100644 index 0000000..b9112ff --- /dev/null +++ b/blueprints/resource/files/test/acceptance/__plural.name__-test.ts @@ -0,0 +1,56 @@ +import { appAcceptanceTest } from 'denali'; + +let test = appAcceptanceTest(); + +test('POST /<%= plural.dasherized %> > creates a <%= singular.humanized %>', async (t) => { + let result = await t.context.app.post('/<%= plural.name %>', { + // Add the <%= singular.humanized %> payload here + }); + + t.is(result.status, 201); + // t.is(result.body.foo, 'bar'); +}); + +test('GET /<%= plural.dasherized %> > should list <%= plural.humanized %>', async (t) => { + let result = await t.context.app.get('/<%= plural.name %>'); + + t.is(result.status, 200); + // t.is(result.body.foo, 'bar'); +}); + +test('GET /<%= plural.dasherized %>/:id > should show a <%= singular.humanized %>', async (t) => { + let { body } = await t.context.app.post('/<%= plural.name %>', { + // Add the <%= singular.humanized %> payload here + }); + let id = body.data.id; + + let result = await t.context.app.get(`/<%= plural.name %>/${ id }`); + + t.is(result.status, 200); + // t.is(result.body.foo, 'bar'); +}); + +test('PATCH /<%= plural.dasherized %>/:id > should update a <%= singular.humanized %>', async (t) => { + let { body } = await t.context.app.post('/<%= plural.name %>', { + // Add the <%= singular.humanized %> payload here + }); + let id = body.data.id; + + let result = await t.context.app.patch(`/<%= plural.name %>/${ id }`, { + // Add the <%= singular.humanized %> payload here + }); + + t.is(result.status, 200); + // t.is(result.body.foo, 'bar'); +}); + +test('DELETE /<%= plural.dasherized %>/:id > should delete a <%= singular.humanized %>', async (t) => { + let { body } = await t.context.app.post('/<%= plural.name %>', { + // Add the <%= singular.humanized %> payload here + }); + let id = body.data.id; + + let result = await t.context.app.delete(`/<%= plural.name %>/${ id }`); + + t.is(result.status, 204); +}); diff --git a/blueprints/resource/files/test/unit/models/__singular.name__-test.ts b/blueprints/resource/files/test/unit/models/__singular.name__-test.ts new file mode 100644 index 0000000..b57c889 --- /dev/null +++ b/blueprints/resource/files/test/unit/models/__singular.name__-test.ts @@ -0,0 +1,3 @@ +import test from 'ava'; + +test.todo('<%= singular.className %> Model'); diff --git a/blueprints/resource/files/test/unit/serializers/__singular.name__-test.ts b/blueprints/resource/files/test/unit/serializers/__singular.name__-test.ts new file mode 100644 index 0000000..0e94778 --- /dev/null +++ b/blueprints/resource/files/test/unit/serializers/__singular.name__-test.ts @@ -0,0 +1,3 @@ +import test from 'ava'; + +test.todo('<%= singular.className %>Serializer'); diff --git a/blueprints/resource/index.ts b/blueprints/resource/index.ts new file mode 100644 index 0000000..7ad4dd5 --- /dev/null +++ b/blueprints/resource/index.ts @@ -0,0 +1,59 @@ +import { + upperFirst, + camelCase, + lowerCase, + kebabCase +} from 'lodash'; +import { singularize, pluralize } from 'inflection'; +import { Blueprint, unwrap } from 'denali-cli'; + +/** + * Generates a model, serializer, CRUD actions, and tests for a resource + * + * @package blueprints + */ +export default class ResourceBlueprint extends Blueprint { + + /* tslint:disable:completed-docs typedef */ + static blueprintName = 'resource'; + static description = 'Generates a model, serializer, CRUD actions, and tests for a resource'; + static longDescription = unwrap` + Usage: denali generate resource [options] + + Generates a complete, end-to-end RESTful resource scaffold. This includes a Model to represent + the data, a Serializer to determine how to send it over the wire, CRUD actions for manipulating + the resource, and tests for all of the above. + `; + + static params = ''; + + locals(argv: any) { + let name = argv.name; + name = pluralize(name); + let plural = { + name, + camelCased: camelCase(name), + className: upperFirst(camelCase(name)), + dasherized: kebabCase(name), + humanized: lowerCase(name) + }; + name = singularize(name); + let singular = { + name, + camelCased: camelCase(name), + className: upperFirst(camelCase(name)), + dasherized: kebabCase(name), + humanized: lowerCase(name) + }; + return { plural, singular }; + } + + async postInstall(argv: any) { + this.addRoute('resource', singularize(argv.name)); + } + + async postUninstall(argv: any) { + this.removeRoute('resource', singularize(argv.name)); + } + +} diff --git a/blueprints/serializer/files/app/serializers/__name__.ts b/blueprints/serializer/files/app/serializers/__name__.ts new file mode 100644 index 0000000..4b94859 --- /dev/null +++ b/blueprints/serializer/files/app/serializers/__name__.ts @@ -0,0 +1,9 @@ +import ApplicationSerializer from './application'; + +export default class <%= className %>Serializer extends ApplicationSerializer { + + attributes: string[] = []; + + relationships: any = {}; + +} diff --git a/blueprints/serializer/files/test/unit/serializers/__name__-test.ts b/blueprints/serializer/files/test/unit/serializers/__name__-test.ts new file mode 100644 index 0000000..177d3df --- /dev/null +++ b/blueprints/serializer/files/test/unit/serializers/__name__-test.ts @@ -0,0 +1,3 @@ +import test from 'ava'; + +test.todo('<%= className %>Serializer'); diff --git a/blueprints/serializer/index.ts b/blueprints/serializer/index.ts new file mode 100644 index 0000000..a8086b5 --- /dev/null +++ b/blueprints/serializer/index.ts @@ -0,0 +1,34 @@ +import { + upperFirst, + camelCase +} from 'lodash'; +import { Blueprint, unwrap } from 'denali-cli'; + +/** + * Generates a blank serializer + * + * @package blueprints + */ +export default class SerializerBlueprint extends Blueprint { + + /* tslint:disable:completed-docs typedef */ + static blueprintName = 'serializer'; + static description = 'Generates a blank serializer'; + static longDescription = unwrap` + Usage: denali generate serializer [options] + + Generates a blank serializer for the given model. + + Guides: http://denalijs.org/master/guides/data/serializers/ + `; + + static params = ''; + + locals(argv: any) { + let name = argv.name; + return { + name, + className: upperFirst(camelCase(name)) + }; + } +} diff --git a/blueprints/service/files/app/services/__name__.ts b/blueprints/service/files/app/services/__name__.ts new file mode 100644 index 0000000..8fc4491 --- /dev/null +++ b/blueprints/service/files/app/services/__name__.ts @@ -0,0 +1,4 @@ +import { Service } from 'denali'; + +export default class <%= className %>Service extends Service { +} diff --git a/blueprints/service/files/test/unit/services/__name__-test.ts b/blueprints/service/files/test/unit/services/__name__-test.ts new file mode 100644 index 0000000..bf92e94 --- /dev/null +++ b/blueprints/service/files/test/unit/services/__name__-test.ts @@ -0,0 +1,3 @@ +import test from 'ava'; + +test.todo('<%= className %>Service'); diff --git a/blueprints/service/index.ts b/blueprints/service/index.ts new file mode 100644 index 0000000..8676198 --- /dev/null +++ b/blueprints/service/index.ts @@ -0,0 +1,30 @@ +import { Blueprint, unwrap } from 'denali-cli'; +import { upperFirst, camelCase } from 'lodash'; + +/** + * Generates a blank service + * + * @package blueprints + */ +export default class ServiceBlueprint extends Blueprint { + + /* tslint:disable:completed-docs typedef */ + static blueprintName = 'service'; + static description = 'Generates a blank service'; + static longDescription = unwrap` + Usage: denali generate service [options] + + Generates a blank service class. + + Guides: http://denalijs.org/master/guides/application/services/ + `; + + static params = ''; + + locals(argv: any) { + let name = argv.name; + let className = upperFirst(camelCase(name)); + return { name, className }; + } + +}