@bmstravel/nvp-plop-templates 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE.md +3 -0
- package/lib/base-api/actions/action.hbs +121 -0
- package/lib/base-api/methods/method.hbs +11 -0
- package/lib/base-api/schemas/model.hbs +62 -0
- package/lib/base-api/services/service.hbs +93 -0
- package/lib/base-api/services/serviceWithModel.hbs +174 -0
- package/lib/base-api/services/types/model.hbs +52 -0
- package/package.json +19 -0
package/LICENSE.md
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
import { IBaseAction, IBaseAdapter, I{{pascalCase serviceName}}Service, UsersAuthMeta } from "@src/types";
|
2
|
+
import { Context } from "moleculer";
|
3
|
+
import { VISIBILITY, ERR_SYSTEM } from "@src/common";
|
4
|
+
import { MoleculerRegularError } from "@src/errors";
|
5
|
+
|
6
|
+
export type {{pascalCase actionName}}Params = {
|
7
|
+
|
8
|
+
}
|
9
|
+
|
10
|
+
/**
|
11
|
+
* @description {{pascalCase actionName}} action
|
12
|
+
* @example
|
13
|
+
* rest: "POST {{pascalCase serviceName}}/{{pascalCase actionName}}",
|
14
|
+
* cacher: {
|
15
|
+
* keys: ["#token", "user"],
|
16
|
+
* },
|
17
|
+
* visibility: VISIBILITY.PUBLISHED,
|
18
|
+
* timeout: 5000, // 5 secs
|
19
|
+
* params: {
|
20
|
+
* id: { type: "number", positive: true, integer: true },
|
21
|
+
* name: "string|min:3|max:20", // empty:true,length:20,pattern:/^[a-z]$/,contains,numeric,enum,alpha,alphanum,alphadash,singleLine,hex,base64,trim,trimLeft,trimRight,lowercase:true,uppercase:true,convert:true
|
22
|
+
* age: "number|optional|integer|positive|min:0|max:99", // convert:true, negative:true
|
23
|
+
* thumb: "string|nullable|optional",
|
24
|
+
* foo: "string[]",
|
25
|
+
* recent: "boolean|default:true",
|
26
|
+
* createdAt: {
|
27
|
+
* type: "date",
|
28
|
+
* default: (schema, field, parent, context) => new Date()
|
29
|
+
* }
|
30
|
+
* email: { type: "email" },
|
31
|
+
* money: { type: "currency", currencySymbol: '$' },
|
32
|
+
* dob: { type: "date" },
|
33
|
+
* sex: { type: "enum", values: ["male", "female"] },
|
34
|
+
* cache: [
|
35
|
+
* { type: "string" },
|
36
|
+
* { type: "boolean" }
|
37
|
+
* ],
|
38
|
+
* roles: [
|
39
|
+
* { type: "array", unique: true },
|
40
|
+
* // { type: "array", items: "string", default: ["user"] },
|
41
|
+
* // { type: "array", items: "string", enum: [ "user", "admin" ] }
|
42
|
+
* ],
|
43
|
+
* status: { type: "multi", rules: [
|
44
|
+
* { type: "boolean" },
|
45
|
+
* { type: "number" }
|
46
|
+
* ], default: true } // true,false,1,0
|
47
|
+
* dot: {
|
48
|
+
* $$type: "object",
|
49
|
+
* x: "number", // object props here
|
50
|
+
* y: "number", // object props here
|
51
|
+
* },
|
52
|
+
* circle: {
|
53
|
+
* $$type: "object|optional",
|
54
|
+
* o: {
|
55
|
+
* $$type: "object",
|
56
|
+
* x: "number",
|
57
|
+
* y: "number",
|
58
|
+
* },
|
59
|
+
* r: "number"
|
60
|
+
* },
|
61
|
+
* list: { type: "array", min: 2, items: {
|
62
|
+
* type: "number", positive: true, integer: true
|
63
|
+
* } },
|
64
|
+
* mac: { type: "mac" } // 01:C8:95:4B:65:FE, 01C8.954B.65FE, 01-C8-95-4B-65-FE,
|
65
|
+
* url: { type: "url" },
|
66
|
+
* uuid: { type: "uuid" },
|
67
|
+
* _id: {
|
68
|
+
* type: "objectID",
|
69
|
+
* ObjectID // passing the ObjectID class example: const { ObjectID } = require("mongodb")
|
70
|
+
* }
|
71
|
+
* },
|
72
|
+
* async handler(ctx: Context<any, any>) {}
|
73
|
+
*/
|
74
|
+
const {{pascalCase actionName}}Action: IBaseAction = {
|
75
|
+
{{#if actionPath}}
|
76
|
+
rest: "{{method}} {{actionPath}}",
|
77
|
+
{{/if}}
|
78
|
+
{{#eq visibility "published"}}
|
79
|
+
visibility: VISIBILITY.PUBLISHED,
|
80
|
+
{{/eq}}
|
81
|
+
{{#eq visibility "public"}}
|
82
|
+
visibility: VISIBILITY.PUBLIC,
|
83
|
+
{{/eq}}
|
84
|
+
{{#eq visibility "protected"}}
|
85
|
+
visibility: VISIBILITY.PROTECTED,
|
86
|
+
{{/eq}}
|
87
|
+
{{#eq visibility "private"}}
|
88
|
+
visibility: VISIBILITY.PRIVATE,
|
89
|
+
{{/eq}}
|
90
|
+
params: {
|
91
|
+
},
|
92
|
+
async handler(ctx: Context<{{pascalCase actionName}}Params, UsersAuthMeta>) {
|
93
|
+
const $this: I{{pascalCase serviceName}}Service = this;
|
94
|
+
const $adapter: IBaseAdapter = $this.adapter;
|
95
|
+
const i18next = ctx.broker.i18next
|
96
|
+
try {
|
97
|
+
const params = ctx.params;
|
98
|
+
this.logger.info(`🎁 INFO $this:`, $this);
|
99
|
+
this.logger.info(`🎁 INFO $adapter:`, $adapter);
|
100
|
+
this.logger.info(`🎁 INFO params:`, params);
|
101
|
+
|
102
|
+
return {
|
103
|
+
code: 0,
|
104
|
+
data: {},
|
105
|
+
};
|
106
|
+
} catch(err) {
|
107
|
+
throw new MoleculerRegularError({
|
108
|
+
message: i18next.t('ERR_SYSTEM', ERR_SYSTEM.message),
|
109
|
+
code: ERR_SYSTEM.code,
|
110
|
+
type: ERR_SYSTEM.type,
|
111
|
+
data: {
|
112
|
+
error: err.message,
|
113
|
+
stack: err.stack,
|
114
|
+
},
|
115
|
+
error: err,
|
116
|
+
});
|
117
|
+
}
|
118
|
+
},
|
119
|
+
};
|
120
|
+
|
121
|
+
export default {{pascalCase actionName}}Action;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { I{{pascalCase serviceName}}Service } from "@src/types";
|
2
|
+
|
3
|
+
async function {{camelCase methodName}}(payload: any) {
|
4
|
+
const $this: I{{pascalCase serviceName}}Service = this as any;
|
5
|
+
return new $this.Promise((resolve, _reject) => {
|
6
|
+
$this.logger.info("{{pascalCase methodName}} :", payload);
|
7
|
+
resolve('ok');
|
8
|
+
});
|
9
|
+
};
|
10
|
+
|
11
|
+
export default {{camelCase methodName}};
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import { DataTypes } from "sequelize";
|
2
|
+
import dayjs from "dayjs";
|
3
|
+
{{#eq dataTypeId "uuid"}}
|
4
|
+
import { generateUuid } from '@bmstravel/nvp-utils'
|
5
|
+
{{/eq}}
|
6
|
+
import { ISequelizeModel } from '@src/types'
|
7
|
+
|
8
|
+
export interface I{{pascalCase name}} {
|
9
|
+
{{#if hasId}}
|
10
|
+
id: number;
|
11
|
+
{{/if}}
|
12
|
+
// BEGIN addition here
|
13
|
+
|
14
|
+
// END addition here
|
15
|
+
{{#if hasId}}
|
16
|
+
createdAt: number;
|
17
|
+
updatedAt: number;
|
18
|
+
deletedAt: number;
|
19
|
+
{{/if}}
|
20
|
+
}
|
21
|
+
|
22
|
+
const {{pascalCase name}}Model: ISequelizeModel<I{{pascalCase name}}> = {
|
23
|
+
name: "{{camelCase name}}",
|
24
|
+
define: {
|
25
|
+
{{#if hasId}}
|
26
|
+
id: {
|
27
|
+
{{#eq dataTypeId "integer"}}
|
28
|
+
type: DataTypes.BIGINT,
|
29
|
+
autoIncrement: true,
|
30
|
+
{{/eq}}
|
31
|
+
{{#eq dataTypeId "uuid"}}
|
32
|
+
type: DataTypes.STRING,
|
33
|
+
defaultValue: generateUuid({ _prefix: '{{truncate (camelCase name) 3}}' }),
|
34
|
+
{{/eq}}
|
35
|
+
primaryKey: true,
|
36
|
+
},
|
37
|
+
{{/if}}
|
38
|
+
// BEGIN addition here
|
39
|
+
|
40
|
+
// END addition here
|
41
|
+
{{#if hasCrudDate}}
|
42
|
+
createdAt: {
|
43
|
+
type: DataTypes.BIGINT,
|
44
|
+
allowNull: false,
|
45
|
+
defaultValue: dayjs().valueOf(),
|
46
|
+
},
|
47
|
+
updatedAt: {
|
48
|
+
type: DataTypes.BIGINT,
|
49
|
+
allowNull: false,
|
50
|
+
defaultValue: dayjs().valueOf(),
|
51
|
+
},
|
52
|
+
deletedAt: { type: DataTypes.BIGINT },
|
53
|
+
{{/if}}
|
54
|
+
},
|
55
|
+
options: {
|
56
|
+
timestamps: false,
|
57
|
+
freezeTableName: true,
|
58
|
+
tableName: "{{camelCase tableName}}",
|
59
|
+
},
|
60
|
+
};
|
61
|
+
|
62
|
+
export default {{pascalCase name}}Model;
|
@@ -0,0 +1,93 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
import moleculer, { Errors } from "moleculer";
|
4
|
+
import { Service, Action, Method } from "@decorator";
|
5
|
+
import { VERSION, Config, VISIBILITY } from "@src/common";
|
6
|
+
import { ActionService, MethodService, HookService, EventService } from "@packages/nv-decorator";
|
7
|
+
|
8
|
+
const serviceName = {{camelCase serviceName}}
|
9
|
+
@Service({
|
10
|
+
name: serviceName,
|
11
|
+
version: VERSION.v1,
|
12
|
+
settings: {
|
13
|
+
},
|
14
|
+
hooks: {
|
15
|
+
before: {},
|
16
|
+
after: {},
|
17
|
+
errors: {}
|
18
|
+
},
|
19
|
+
})
|
20
|
+
@ActionService({ serviceName })
|
21
|
+
@MethodService({ serviceName })
|
22
|
+
@EventService({ serviceName })
|
23
|
+
@HookService({ serviceName })
|
24
|
+
export default class {{pascalCase serviceName}}Service extends moleculer.Service {
|
25
|
+
public constructor(
|
26
|
+
public broker: moleculer.ServiceBroker,
|
27
|
+
schema?: moleculer.ServiceSchema<{}>
|
28
|
+
) {
|
29
|
+
super(broker, schema);
|
30
|
+
}
|
31
|
+
|
32
|
+
{{#if hasHelloAction}}
|
33
|
+
/**
|
34
|
+
* Say a 'Hello' action.
|
35
|
+
* extends ActionSchema
|
36
|
+
*/
|
37
|
+
@Action({
|
38
|
+
rest: {
|
39
|
+
method: "GET",
|
40
|
+
path: "/hello",
|
41
|
+
},
|
42
|
+
visibility: VISIBILITY.PUBLISHED,
|
43
|
+
cache: {
|
44
|
+
// keys: ["#userID", "name"],
|
45
|
+
ttl: 60 * 60, // 1 hour
|
46
|
+
},
|
47
|
+
params: {
|
48
|
+
name: "string",
|
49
|
+
},
|
50
|
+
timeout: Config.TIMEOUT,
|
51
|
+
fallback: (
|
52
|
+
ctx: moleculer.Context<any, any>,
|
53
|
+
errors: Errors.MoleculerError
|
54
|
+
) => {
|
55
|
+
return new Promise((resolve) => {
|
56
|
+
resolve({
|
57
|
+
code: 99,
|
58
|
+
message: errors.message,
|
59
|
+
});
|
60
|
+
});
|
61
|
+
},
|
62
|
+
})
|
63
|
+
public hello(ctx: moleculer.Context<any, any>) {
|
64
|
+
const params = ctx.params;
|
65
|
+
this.logger.info('params ', params);
|
66
|
+
return this.sayHello(params.name);
|
67
|
+
}
|
68
|
+
|
69
|
+
/**
|
70
|
+
* sayHello method
|
71
|
+
* @methods
|
72
|
+
* @param {String} name
|
73
|
+
*
|
74
|
+
* @return {string}
|
75
|
+
*/
|
76
|
+
@Method
|
77
|
+
public sayHello(name: string) {
|
78
|
+
return `{{pascalCase serviceName}}Service, welcome ${name}!`;
|
79
|
+
}
|
80
|
+
{{/if}}
|
81
|
+
|
82
|
+
public created() {
|
83
|
+
// Fired when created
|
84
|
+
}
|
85
|
+
|
86
|
+
public async started() {
|
87
|
+
// Fired when started
|
88
|
+
}
|
89
|
+
|
90
|
+
public async stopped() {
|
91
|
+
// Fired when stopped
|
92
|
+
}
|
93
|
+
}
|
@@ -0,0 +1,174 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
import moleculer{{#if hasHelloAction}}, { Errors } {{/if}} from "moleculer";
|
4
|
+
import { DbServiceMixin, CacheCleanerMixin } from '@bmstravel/nvp-mixins'
|
5
|
+
import {
|
6
|
+
{{#if hasHelloAction}}
|
7
|
+
Action,
|
8
|
+
{{/if}}
|
9
|
+
{{#if hasSeedDb}}
|
10
|
+
Method,
|
11
|
+
{{/if}}
|
12
|
+
Service,
|
13
|
+
ActionService,
|
14
|
+
MethodService,
|
15
|
+
EventService,
|
16
|
+
HookService,
|
17
|
+
} from '@bmstravel/nvp-decorator'
|
18
|
+
import {
|
19
|
+
MoleculerDBService,
|
20
|
+
I{{pascalCase serviceName}},
|
21
|
+
{{pascalCase serviceName}}ServiceSettingsOptions,
|
22
|
+
{{pascalCase serviceName}}ServiceOptions,
|
23
|
+
} from "@src/types";
|
24
|
+
import { VERSION{{#if hasHelloAction}} , Config, VISIBILITY{{/if}} } from "@src/common";
|
25
|
+
import {{camelCase model}}Model from '@src/models/sequelize/{{camelCase model}}'
|
26
|
+
|
27
|
+
const serviceName = '{{camelCase serviceName}}'
|
28
|
+
@Service<{{pascalCase serviceName}}ServiceOptions>({
|
29
|
+
name: serviceName,
|
30
|
+
version: VERSION.v1,
|
31
|
+
mixins: [
|
32
|
+
new DbServiceMixin("{{camelCase model}}", {
|
33
|
+
adapter: {
|
34
|
+
model: {{camelCase model}}Model,
|
35
|
+
// dbUri: Config.SEQUELIZE_URI,
|
36
|
+
// dbType: "mysql",
|
37
|
+
// dbHost: Config.DB_HOST,
|
38
|
+
// dbName: Config.DB_NAME,
|
39
|
+
// dbUser: Config.DB_USER,
|
40
|
+
// dbPassword: Config.DB_PASSWORD,
|
41
|
+
// nosync: true is ingnore sync
|
42
|
+
// nosync: true
|
43
|
+
/* sync: {
|
44
|
+
// This creates the table, dropping it first if it already existed
|
45
|
+
force: true,
|
46
|
+
// This checks what is the current state of the table in the database (which columns it has, what are their data // types, etc), and then performs the necessary changes in the table to make it match the model.
|
47
|
+
alter: true,
|
48
|
+
}, */
|
49
|
+
},
|
50
|
+
}).start(),
|
51
|
+
CacheCleanerMixin(["cache.clean.{{camelCase serviceName}}"]),
|
52
|
+
],
|
53
|
+
settings: {
|
54
|
+
idField: "id",
|
55
|
+
pageSize: 10,
|
56
|
+
// /api/v1/{{camelCase serviceName}}/*
|
57
|
+
// rest: "/{{camelCase serviceName}}",
|
58
|
+
// Available fields in the responses if use method: transformDocuments(ctx, params, docs)
|
59
|
+
fields: [
|
60
|
+
"id",
|
61
|
+
"createdAt",
|
62
|
+
"updatedAt",
|
63
|
+
"deletedAt",
|
64
|
+
],
|
65
|
+
// Validator for the `create` & `insert` actions.
|
66
|
+
/* entityValidator: {
|
67
|
+
name: "string|min:3",
|
68
|
+
price: "number|positive",
|
69
|
+
}, */
|
70
|
+
},
|
71
|
+
hooks: {
|
72
|
+
before: {
|
73
|
+
/**
|
74
|
+
* Register a before hook for the `create` action.
|
75
|
+
*
|
76
|
+
* @param {Context} ctx
|
77
|
+
*/
|
78
|
+
create: (_ctx: moleculer.Context<any, any>) => {
|
79
|
+
// ctx.params.quantity = 0;
|
80
|
+
},
|
81
|
+
},
|
82
|
+
},
|
83
|
+
})
|
84
|
+
@ActionService({ serviceName })
|
85
|
+
@MethodService({ serviceName })
|
86
|
+
@EventService({ serviceName })
|
87
|
+
@HookService({ serviceName })
|
88
|
+
export default class {{pascalCase serviceName}}Service extends MoleculerDBService<
|
89
|
+
{{pascalCase serviceName}}ServiceSettingsOptions,
|
90
|
+
I{{pascalCase serviceName}}
|
91
|
+
> {
|
92
|
+
public constructor(
|
93
|
+
public broker: moleculer.ServiceBroker,
|
94
|
+
schema?: moleculer.ServiceSchema<{}>
|
95
|
+
) {
|
96
|
+
super(broker, schema);
|
97
|
+
}
|
98
|
+
|
99
|
+
{{#if hasHelloAction}}
|
100
|
+
/**
|
101
|
+
* Say a 'Hello' action.
|
102
|
+
* extends ActionSchema
|
103
|
+
*/
|
104
|
+
@Action({
|
105
|
+
rest: {
|
106
|
+
method: "GET",
|
107
|
+
path: "/hello",
|
108
|
+
},
|
109
|
+
visibility: VISIBILITY.PUBLISHED,
|
110
|
+
cache: {
|
111
|
+
// keys: ["#userID", "name"],
|
112
|
+
ttl: 60 * 60, // 1 hour
|
113
|
+
},
|
114
|
+
params: {
|
115
|
+
name: "string",
|
116
|
+
},
|
117
|
+
timeout: Config.TIMEOUT,
|
118
|
+
fallback: (
|
119
|
+
ctx: moleculer.Context<any, any>,
|
120
|
+
errors: Errors.MoleculerError
|
121
|
+
) => {
|
122
|
+
return new Promise((resolve) => {
|
123
|
+
resolve({
|
124
|
+
code: 99,
|
125
|
+
message: errors.message,
|
126
|
+
});
|
127
|
+
});
|
128
|
+
},
|
129
|
+
})
|
130
|
+
public hello(ctx: moleculer.Context<{ name: string }, any>) {
|
131
|
+
const params = ctx.params;
|
132
|
+
this.logger.info('params ', params);
|
133
|
+
return this.sayHello(params.name);
|
134
|
+
}
|
135
|
+
|
136
|
+
/**
|
137
|
+
* sayHello method
|
138
|
+
* @methods
|
139
|
+
* @param {String} name
|
140
|
+
*
|
141
|
+
* @return {string}
|
142
|
+
*/
|
143
|
+
@Method
|
144
|
+
public sayHello(name: string) {
|
145
|
+
return `{{pascalCase serviceName}}Service, welcome ${name}!`;
|
146
|
+
}
|
147
|
+
{{/if}}
|
148
|
+
|
149
|
+
{{#if hasSeedDb}}
|
150
|
+
/**
|
151
|
+
* Loading sample data to the collection.
|
152
|
+
* It is called in the DB.mixin after the database
|
153
|
+
* connection establishing & the collection is empty.
|
154
|
+
*/
|
155
|
+
@Method
|
156
|
+
public async seedDB() {
|
157
|
+
await this.adapter.insertMany([
|
158
|
+
// { name: "Samsung Galaxy S10 Plus", quantity: 10, price: 704 },
|
159
|
+
]);
|
160
|
+
}
|
161
|
+
{{/if}}
|
162
|
+
|
163
|
+
public created() {
|
164
|
+
// Fired when created
|
165
|
+
}
|
166
|
+
|
167
|
+
public async started() {
|
168
|
+
// Fired when started
|
169
|
+
}
|
170
|
+
|
171
|
+
public async stopped() {
|
172
|
+
// Fired when stopped
|
173
|
+
}
|
174
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import { Options } from '@bmstravel/nvp-decorator';
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
3
|
+
import { ServiceActionsSchema } from "moleculer";
|
4
|
+
import { DbServiceSettings } from 'moleculer-db';
|
5
|
+
import {
|
6
|
+
IBaseService,
|
7
|
+
IBaseServiceActions,
|
8
|
+
IBaseServiceMethods,
|
9
|
+
} from "./db.service-interface";
|
10
|
+
|
11
|
+
export interface {{pascalCase serviceName}}ServiceSettingsOptions extends Omit<DbServiceSettings, "fields"> {
|
12
|
+
/**
|
13
|
+
* if implements will replace /v1/{{camelCase serviceName}}/* to /{{camelCase serviceName}}/*
|
14
|
+
*/
|
15
|
+
rest?: "/{{camelCase serviceName}}";
|
16
|
+
fields?: (keyof Required<any>)[];
|
17
|
+
populates?: any;
|
18
|
+
[x: string]: any;
|
19
|
+
}
|
20
|
+
|
21
|
+
export interface {{pascalCase serviceName}}ServiceOptions extends Options {
|
22
|
+
name: '{{camelCase serviceName}}';
|
23
|
+
settings: {{pascalCase serviceName}}ServiceSettingsOptions;
|
24
|
+
}
|
25
|
+
|
26
|
+
export enum {{pascalCase serviceName}}Action {
|
27
|
+
// DELETED = 'user.deleted'
|
28
|
+
}
|
29
|
+
|
30
|
+
export enum {{pascalCase serviceName}}Event {
|
31
|
+
// DELETED = 'user.deleted'
|
32
|
+
}
|
33
|
+
|
34
|
+
export enum {{pascalCase serviceName}}RouterAlias {
|
35
|
+
// {{constantCase serviceName}} = "v1.{{pascalCase serviceName}}",
|
36
|
+
}
|
37
|
+
|
38
|
+
export interface I{{pascalCase serviceName}}Actions extends IBaseServiceActions {
|
39
|
+
/* MOL_ACTION */
|
40
|
+
{{#if hasHelloAction}}
|
41
|
+
hello: ServiceActionsSchema;
|
42
|
+
{{/if}}
|
43
|
+
}
|
44
|
+
|
45
|
+
export interface I{{pascalCase serviceName}}Methods extends IBaseServiceMethods {
|
46
|
+
/* MOL_METHOD */
|
47
|
+
}
|
48
|
+
|
49
|
+
export interface I{{pascalCase serviceName}}Service extends IBaseService<I{{pascalCase serviceName}}Actions, I{{pascalCase serviceName}}Methods>, I{{pascalCase serviceName}}Methods {
|
50
|
+
actions: I{{pascalCase serviceName}}Actions;
|
51
|
+
methods: I{{pascalCase serviceName}}Methods;
|
52
|
+
}
|
package/package.json
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"name": "@bmstravel/nvp-plop-templates",
|
3
|
+
"version": "0.0.1",
|
4
|
+
"description": "🏆 Use like a Pro!",
|
5
|
+
"license": "MIT",
|
6
|
+
"main": "lib/index.js",
|
7
|
+
"files": [
|
8
|
+
"/lib"
|
9
|
+
],
|
10
|
+
"scripts": {},
|
11
|
+
"publishConfig": {
|
12
|
+
"access": "public"
|
13
|
+
},
|
14
|
+
"authors": [
|
15
|
+
"phongnv86 <phongnguyenvan86@gmail.com>",
|
16
|
+
"phongnv86 <phongnv@media-one.vn>"
|
17
|
+
],
|
18
|
+
"gitHead": "eb8158343e7a7d7297244b6ceb9624af2d635e73"
|
19
|
+
}
|